Behavior of sched_yield Behavior of sched_yield multithreading multithreading

Behavior of sched_yield


http://www.kernel.org/doc/man-pages/online/pages/man2/sched_yield.2.html

sched_yield() causes the calling thread to relinquish the CPU. The thread is moved to the end of the queue for its static priority and a new thread gets to run.

If the calling thread is the only thread in the highest priority list at that time, it will continue to run after a call to sched_yield().

The sched_yield is not a .Net call and the threading/process model is different to. The scheduler of Windows/.NET is not the same as scheduler of Linux. Linux even have several possible schedulers.

So, your expectations about sched_yield is wrong.

If you want to control, how threads are run, you can bind each thread to CPU. Then, threads will run only on binded CPU. If you will have several threads, binded to the same CPU, the using of sched_yield MAY switch to another thread which is binded to current CPU and is ready to run.

Also it can be bad idea to use several threads per CPU if each thread want to do a lot of CPU-intensive work.

If you want to get full control, how threads are run, you can use RealTime threads. http://www.linuxjournal.com/magazine/real-time-linux-kernel-scheduler - SCHED_FIFO and SCHED_RR RT policies.


Why would you want to give up the CPU? Well...

I am fixing a bug in client code. Basically, they have a shared struct that holds information:

  1. how many coins in escrow - return them
  2. how many bills in escrow - return them

The above are in process A. the rest of the code is in process B. Process B sends messages to Process A to compute and return the money in escrow (this is a vending machine). Without getting into the history of why the code is written this way, the original code sequence is:

(Process B) send message RETURN_ESCROWED_BILLS to Process A send message RETURN_ESCROWED COINS to Process A Zero out the common structure

This gets executed as:

(Process B): send the messages; zero out the struct;

(later .. Process A): get the messages; all fields in common struct are 0; nothing to do;

oops ... the money is still in escrow, but the process A code has lost that knowledge. What is really needed (other than a massive restructuring of the code) is:

(Process B): send the messages; yield the CPU;

(Process A): determine the escrowed money and return; yield the CPU; (could just go to the end of the timeslice, no special method needed)

(Process B): zero out the common struct;

Any time you have IPC messages and the processes that send/receive the messages are tightly coupled. the best way is to have a two-way handshake. However, there are cases out there (usually as the result of a poor or non-existent design) where you must tightly couple processes that are really supposed to be loosely coupled. Usually the yield of the CPU is a hack because you do not have a choice. The addition of multicore CPUs is a source of pain, especially when porting from a single core to a multi-core.