10

I have few questions about the sched_yield function because I'm seeing that it is not functioning as intended in my code. Many times I see that the same thread runs again and again, even in the presence of other threads, when I try to yield it by calling sched_yield.

Also If I have multicores, will sched_yield yield for threads running on all cores, or only one core. Say for example I have Threads 1, 2 and 3 running on core 1 and Threads 4, 5 and 6 on core 2 and If sched_yield is called from Thread 2, will it be replaced by Thread 1 and 3 only, or 1, 3, 4, 5 and 6 are all possible? I am asking this because in .Net Thread.Yield only yields to threads running on the same core/processor.

skaffman
  • 398,947
  • 96
  • 818
  • 769
MetallicPriest
  • 29,191
  • 52
  • 200
  • 356
  • 4
    How do you intend it to function? TBH, I don't really understand why this call is useful, either on POSIX/***X, Windows or any preemptive multitasker. If you yield your thread, you have no guarantee that the OS will not just load it on again immediately, maybee on the same core if the other threads are not ready at that time. If the .NET version has a processor affinity, (and yes, I googled it and it appears that it has), that is even weirder - I guess it might improve performance with fibers? – Martin James Jun 15 '11 at 13:43
  • 3
    @MartinJames it's a useful call when you have more runnable processes/threads than cores and you want to give the other threads/processes a chance to make progress (e.g., one thread has just given another thread something to do and the cost of the first thread going to sleep to wait on completion is more than the cost of (the second thread doing the "something" + the first thread checking that it's been done). – jhfrontz Nov 27 '13 at 13:55

2 Answers2

6

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.

osgx
  • 90,338
  • 53
  • 357
  • 513
-7

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.

  • 2
    This answer is wrong. sched_yield() is not meant for interprocess communication, nor will calling it ensure that another thread actually runs. As described by osgx, the idea is to help the OS schedule efficiently. – uli Jun 23 '15 at 11:14
  • yes, sched_yield() is not explicity for interprocess communication, but: the sending thread needed to give up the CPU in a predictable manner to allow the receiving thread to actually have a chance to get the CPU. Also, both processes are at the same priority level, and the receiving thread is blocking, waiting on the message. Otherwise there was a race between when the sending task lost the CPU and the receiving task got the CPU. This method was predictable (Ubunto 8) – user2913342 Apr 14 '17 at 20:09