Is there a way to force a context switch in C++ to a specific thread, assuming I have the thread handle or thread ID?
-
3If an application could force a certain thread to execute, that would eventually mean that a higher-priority process or thread would get starved, rendering any kind of process priorities or scheduler fairness algorithm moot. Also, what if the thread you were forcing to run were not ready to run? If it's blocked on a read, and wakes up, it's going to assume that there's something to read. – Mike DeSimone May 01 '11 at 12:55
-
What's the motivation behind the question? – David Heffernan May 01 '11 at 13:00
-
I need the non-running thread to take control of a critical section. :) – Idov May 01 '11 at 13:17
-
Ok, never mind, I'll just busy loop until this thread kicks in :) – Idov May 01 '11 at 13:28
-
2@ldov you should just release the critical section and the other thread will take control when it runs again. Busy loop doesn't sound like a very good idea. – David Heffernan May 01 '11 at 13:40
6 Answers
No, you won't be able to force operating system to run the thread you want. You can use yield
to force a context switch though...
yield
in Win32 API is function SwitchToThread
. If there is no other thread available for running, then a ZERO value will be returned and current thread will keep running anyway.

- 176,835
- 32
- 241
- 292
-
Actually this is not true. SwitchToThread does not guarantee a context switch. If there are no threads eligible to run on this processor then this thread will continue. – David Heffernan May 01 '11 at 12:58
-
but it can be ANY thread running that processor, not just in my process, right? – Idov May 01 '11 at 13:18
-
@Idov: right. It can be ANY thread running, not just your process. That's an OS limitation. OS is in full control of process/thread scheduling. – Pablo Santa Cruz May 01 '11 at 14:34
-
@David Hefferman: true. In the extremely unlikely case that there is absolutely no other thread in that process or in other process, then I guess it will keep the current thread running. – Pablo Santa Cruz May 01 '11 at 14:35
-
Well, it's very common for there to be no ready threads waiting to run. That happens often, when there are more logical cores than ready to run, waiting threads. – David Heffernan May 01 '11 at 14:38
-
@David: you mean in a process? Or in the whole operating system? – Pablo Santa Cruz May 01 '11 at 14:39
-
@Pablo No, in the whole OS. Right now as I type this, every time I pause to think the CPU utilisation drops to 0% because there is no thread ready to run. All threads in the system are blocking. – David Heffernan May 01 '11 at 14:49
You can only encourage the Windows thread scheduler to pick a certain thread, you can't force it. You do so first by making the thread block on a synchronization object and signaling it. Secondary by bumping up its priority.
Explicit context switching is supported, you'll have to use fibers. Review SwitchToFiber(). A fiber is not a thread by a long shot, it is similar to a co-routine of old. Fibers' heyday has come and gone, they are not competitive with threads anymore. They have very crappy cpu cache locality and cannot take advantage of multiple cores.

- 121,135
- 26
- 193
- 155

- 922,412
- 146
- 1,693
- 2,536
The only way to force a particular thread to run is by using process/thread affinity, but I can't imagine ever having a problem for which this was a reasonable solution.
The only way to force a context switch is to force a thread onto a different processor using affinity.
In other words, what you are trying to do isn't really viable.
Calling SwitchToThread()
will result in a context switch if there is another thread ready to run that are eligible to run on this processor. The documentation states it as follows:
If calling the SwitchToThread function causes the operating system to switch execution to another thread, the return value is nonzero.
If there are no other threads ready to execute, the operating system does not switch execution to another thread, and the return value is zero.

- 601,492
- 42
- 1,072
- 1,490
You can create two synchronization objects (such as two events) and use the API SignalObjectAndWait.
If the hObjectToWaitOn
is non-signaled and your other thread is waiting on the hObjectToSignal
, the OS can theoretically perform quick context switch inside this API, before end of time slice.
And if you want the current thread to automatically resume, simply inform a small value (such as 50 or 100) on the dwMilliseconds
.

- 7,012
- 5
- 40
- 61
You can temporarily bump the priority of the other thread, while looping with Sleep(0)
calls: this passes control to other threads. Suppose that the other thread has increased a lock
variable and you need to wait until it becomes zero again:
// Wait until other thread releases lock
SetThreadPriority(otherThread, THREAD_PRIORITY_HIGHER);
while (InterlockedRead(&lock) != 0)
Sleep(0);
SetThreadPriority(otherThread, THREAD_PRIORITY_NORMAL);

- 6,471
- 28
- 39
-
What you state here is incorrect. From the documentation of `Sleep()`: A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution. – David Heffernan May 01 '11 at 14:23
-
No it doesn't. If there isn't another thread ready to run the `Sleep(0)` is effectively a no-op. – David Heffernan May 01 '11 at 14:33
-
Sure, but if there isn't another thread ready to run, nothing else will work either. – Frederik Slijkerman May 01 '11 at 18:39
I would check out the book Concurrent Programming for Windows. The scheduler seems to do a few things worth noting.
Sleep(0) only yields to higher priority threads (or possibly others at the same priority). This means you cannot fix priority inversion situations with just a Sleep(0), where other lower priority threads need to run. You must use SwitchToThread, Sleep a non-zero duration, or fully block on some kernel HANDLE.

- 616
- 6
- 5