views:

176

answers:

8

I am looking for a way to yield the remainder of the thread execution's scheduled time slice to a different thread. There is a SwitchToThread function in WINAPI, but it doesn't let the caller specify the thread it wants to switch to. I browsed MSDN for quite some time and haven't found anything that would offer just that.

For an operating-system-internals layman like me, it seems that yielding thread should be able to specify which thread does it want to pass the execution to. Is it possible or is it just my imagination?

+3  A: 

The reason you can't yield processor time-slices to a designated thread is that Windows features a preemptive scheduling kernel which pretty much places the responsibility and authority of scheduling the processor time in the hands of the kernel and only the kernel.

As such threads don't have any control over when they run, if they run, and even less over which thread is switched to after their time slice is up.

However, there are a few way you may influence context switches:

  • by increasing the priority of a certain thread you may force the scheduler to schedule it more often in the detriment of other threads (obviously the reverse applies as well - you can lower the priority of other threads)

  • you can code your process to place threads in kernel wait mode when they don't have work to do in order to help the scheduler do it's job. When using proper kernel wait constructs such as Critical Sections, Mutexes, Semaphores, and Timers you effectively tell the kernel a certain thread doesn't need to be scheduled until a certain codition is met.

Note: There is rarely a reason you should tamper with task priorities so USE WITH CAUTION

Miky Dinescu
+1  A: 

This is not possible. Only the kernel can decide what code runs next though you can influence it by reducing the non-waiting threads it has to choose from to run next, and by setting thread priorities with SetThreadPriority.

martinr
+1  A: 

You can use regular synchronization primitives like events, semaphores, etc. to serialize your two threads. This does not in any form prevent the kernel from scheduling other threads in between, or in parallel on another CPU core, or virtually simultaneously on the same core. This is due to preemtive multitasking nature of modern general purpose operating systems.

Nikolai N Fetissov
+2  A: 

You might use 'fibers' instead of 'threads': for example there's a Win32 API named SwitchToFiber which lets you specify the fiber to be scheduled.

ChrisW
+1  A: 

If you want to do your own scheduling under Windows, you can use fibers, which essentially are threads that you have to schedule yourself. However, given that you describe yourself as a layman to the OS internals world, that would probably be a bad idea, as fibers are something of an advanced feature.

dsolimano
Hey, it's not like I'd cause any serious harm - there's always a good opportunity to learn and be less of a layman. Learning new things is (almost) never a bad idea :)
Marcin Seredynski
+1  A: 

Take a look at UMS (User-mode scheduling) threads in Windows 7

http://msdn.microsoft.com/en-us/library/dd627187(VS.85).aspx

Mark oskin
Ah, it looks like a very interesting read. Unfortunately I'm targetting both 32 and 64 bit platforms from XP upwards and can't use it. What a shame. Thanks for pointing that to me, though!
Marcin Seredynski
+1  A: 

The second thread can simply wait for the yielding thread either by calling WaitForSingleObject() on its handle or periodically polling GetExitCodeThread(). The other answers are correct about altering the operating system's scheduling mechanisms - it is better to design the threads properly in the first place.

Steve Sanders
A: 

Can I ask why you want to use SwitchToThread?

If for example it's some form of because thread x is computing some value that you want to wait for on thread Y, then I'd really suggest looking at the Parallel Pattern Library or the Asynchronous Agents Library in Visual Studio 2010 which allows you to do this either with message blocks (receive on an asynchronous value) or simply via tasks : wait for a set of tasks to complete and inline their execution while waiting...

//i.e. on an arbitrary thread
task_group* tasks;
tasks->run(... / some functor/)

a call to tasks->wait() will wait and inline any tasks running.

Rick
As for the "why" part - I don't remember the exact scenario I had in mind when I posted my question originally, but in general, I'm looking for a way to ensure my application (a simple game engine I'm making) gets some of the scheduler's attention as often as possible - ideally in every time slice. I want to keep it as smooth as possible, and have a budget of 16.67ms of processing time per frame with 60Hz screen refresh rate. A simple test proved that my thread can get preempted for more than 10ms. I guess I'll just have to live with fact a frame may be skipped if I want to be nice for the OS.
Marcin Seredynski
As for the "PPL" and "AAL" - they look very interesting, thanks for showing them to me.
Marcin Seredynski
If you really want to take muck with priorities then take a look at AvSetMmThreadCharacteristics and AvSetMmThreadPriority. They are appropriate for what your scenario of providing guarantees.Again I'd encourage you to look at the APIs. I'm also writing a game to demonstrate how this can be done with them.
Rick