Does pthread_cond_wait put the calling thread to wait state to be waken up by pthread_cond_signal/pthread_cond_broadcast, so that it does not poll and churn the CPU?
Also, does sem_wait put the thread in wait state? If I understand correctly the mutex acquire/release methods make the threads poll continuously on the mutex and do not put the thread in waiting state.
Yes, pthread_cond_wait, when successful, causes the thread to wait until notified. That is the purpose of the call.
sem_wait will put the thread in the wait state if the semaphore cannot be decremented. In it's in a high state, then the call will return immediately.
In most situations, you needn't concern yourself with whether the locks are implemented via busy-waiting or scheduler yielding. Either way, you get the guaranteed behavior, and generally the library implementer will choose the most efficient method available on the platform on which you are running. In some cases (where you have more than one core and the expected wait time is small) that's busy-waiting.
Yes, the task which calls pthread_cond_wait() will be put into wait state:
pthread_cond_wait atomically releases mutex and cause the
calling thread to block on the condition variable cond
In the internal of current linux, it uses futex to do the stuffs.
sem_wait will block the task until either it becomes possible to
perform the decrement for the semaphore if the semaphore currently
has the value zero when call.
Related
For the code below, the mutex will not available by the time second cond_broadcast is executed(assuming multiple threads already waiting on the condition). In such situation, does the broadcast select the thread(waiting on the condition) to hand the mutex to and wait for the mutex to be unlocked by some other thread or the second cond_broadcast is just ignored?
void* func(void* arg){
pthread_mutex_lock(&m);
while(condition){
pthread_cond_wait(&c,&m);
}
pthread_cond_broadcast(&c);
pthread_mutex_unlock(&m);
pthread_cond_broadcast(&c);
}
For the code below, the mutex will not available by the time second
cond_broadcast is executed(assuming multiple threads already waiting
on the condition).
I think you mean that the mutex will not be available to the thread calling pthread_cond_broadcast() at the second call to that function, but that's irrelevant. Calling pthread_cond_broadcast() is independent of holding any mutex.
Or perhaps you mean that one of the previously blocked threads will have acquired the mutex by the time the second broadcast happens, but (1) that's not certain, and (2) if it does happen, that has no particular significance with respect to the broadcast.
In such situation, does the broadcast select the
thread(waiting on the condition) to hand the mutex to and wait for the
mutex to be unlocked by some other thread or the second cond_broadcast
is just ignored?
Neither. pthread_cond_broadcast() and pthread_cond_signal() have no role in locking or transferring control of any mutex. They just wake threads blocked on the associated CV. That each such thread must acquire the mutex before returning from the call is a separate consideration -- they all contend normally to lock the mutex, and they do not return from pthread_cond_wait() until they do. They also do not go back to waiting without first returning from their wait and then calling pthread_cond_wait() again.
But that does not mean that the second pthread_cond_broadcast() in your code necessarily will have no effect. One of the just-woken threads might loop around and wait on the CV again between the two calls, or some other thread might arrive at the CV. That becomes possible as soon as the first thread releases the mutex, and the fact that the first thing that thread tries to do is another broadcast does not ensure that the broadcast happens before another thread can start waiting.
It is unlikely that you want two broadcasts one after the other like that, but which one you retain has little, if any, effect on the overall semantics of the program.
I know that we can use pthread_cond_init, pthread_cond_wait, and pthread_cond_broadcast to implement thread condition signaling in user space. But how can we implement it in a kernel module that is using kthread?
linux/mutex.h provides locking as discussed in this question. But it does not seem to be associated with any condition variables.
linex/wait.h seems to have condition waiting but it has no documentation so there are too many concerns around it. For example, wake_up_interruptable could have a race condition when used as suggested in examples with no mutex. It seems unlikely that the wait queues could be combined with mutex waits in a way that would implement semantics like pthread_cond_wait, because the thread scheduling functions implementing these different APIs need to be integrated to provide atomic semantics.
How can a kernel module get atomic sleep-and-unlock semantics, like in a normal user-space API, like pthread_cond_wait?
The specific semantics I need are (from the pthread_cond_wait* manpage):
These functions atomically release mutex and cause the calling thread
to block on the condition variable cond; atomically here means
"atomically with respect to access by another thread to the mutex and
then the condition variable". That is, if another thread is able to
acquire the mutex after the about-to-block thread has released it,
then a subsequent call to pthread_cond_broadcast() or
pthread_cond_signal() in that thread shall behave as if it were issued
after the about-to-block thread has blocked.
The important requirements are:
The condition is a shared structure, and can only be accessed when the mutex is held.
Atomicity prevents the condition from becoming true in between the mutex release and thread blocking. Without this, the thread could check the condition (when it's false), then release the mutex, then the condition becomes true (and a signal is generated and propagated), and then the thread falls asleep and misses the signal.
(Here is how pthread_cond_wait is used in a program).
Scenario 1: release mutex then wait
Scenario 2: wait and then release mutex
Trying to understand conceptually what it does.
If the mutex were released before the calling thread is considered "blocked" on the condition variable, then another thread could lock the mutex, change the state that the predicate is based on, and call pthread_cond_signal without the waiting thread ever waking up (since it's not yet blocked). That's the problem.
Scenario 2, waiting then releasing the mutex, is internally how any real-world implementation has to work, since there's no such thing as an atomic implementation of the necessary behavior. But from the application's perspective, there's no way to observe the thread being part of the blocked set without the mutex also being released, so in the sense of the "abstract machine", it's atomic.
Edit: To go into more detail, the real-world implementation of a condition variable wait generally looks like:
Modify some internal state of the condition variable object such that the caller is considered to be part of the blocked set for it.
Unlock the mutex.
Perform a blocking wait operation, with the special property that it will return immediately if the state of the condition variable object from step 1 has changed due to a signal from any other thread.
Thus, the act of "blocking" is split between two steps, one of which happens before the mutex is unlocked (gaining membership in the blocked set) and the other of which happens after the mutex is unlocked (possibly sleeping and yielding control to other threads). It's this split that's able to make the "condition wait" operation "atomic" in the abstract machine.
Regarding this:
How To Use Condition Variable
Say we have number of consumer threads that execute such code (copied from the referenced page):
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
I assume that scenario here is: main thread calls pthread_cond_signal() to tell consumer threads to do some work.
As I understand it - subsequent threads call pthread_mutex_lock() and then pthread_cond_wait() (which atomically unlocks the mutex). By now none of the consumer threads is claiming the mutex, they all wait on pthread_cond_wait().
When the main thread calls pthread_cond_signal(), following the manpage, at least one thread is waken up. When any of them returns from pthread_cond_wait() it automatically claims the mutex.
So my question is: what happens now regarding the provided example code? Namely, what does the thread that lost the contest for the mutex do now?
(AFAICT the thread that won the mutex, should run the rest of the code and release the mutex. The one that lost should be stuck waiting on the mutex - somewhere in the 1st nested while loop - while the winner holds it and after it's been released start blocking on pthread_cond_wait() beacuse the while (avail == 0) will be satisfied by then. Am I correct?)
Note that pthread_cond_signal() is generally intended to wake up only one waiting thread (that's all that it guarantees). But it could wake more 'accidentally'. The while (avail > 0) loop performs two functions:
it allows the one thread guaranteed to be woken up to consume all queued work units
it prevents additional 'accidentally' awakened threads from assuming that there's work to be done, when there might not be since the initial thread would have handled all of them.
It also prevents a race condition where a work unit might have been placed on the queue after the while (avail > 0) has completed, but before the worker thread has waited on the condition again - but that race is also handled by the if test just before calling pthread_cond_wait().
Basically when a thread is awakened, all it knows is that there might be work units for it to consume, but there might not (another thread might have consumed them).
So the sequence of events that occurs when pthread_cond_signal() is called is:
the system will wake one or more threads waiting on the condition
all the threads that are awakened will then try to acquire the mutex - only one of them can acquire it at any particular moment, since that's the purpose of a mutex
that thread will then proceed, perform the work in the while (avail > 0) loop, then will release the mutex
at that point one of the other threads that were previously woken up will acquire the mutex and work the same loop, then release the mutex. Generally, there will be no work units available anymore (since the first thread would have consumed all of them), but if another thread had added an additional unit (or more), then this thread would handle that work
the next thread will acquire the mutex and perform that same set of logic
pthread_cond_wait() has to acquire given mutex once signaled/woken up. If another thread wins that race, the function blocks until the mutex is released. So from the application point of view it doesn't return until current thread holds the mutex. The wait is always done in a loop (while (avail == 0) { ... above) to make sure that application condition we are waiting for still holds (buffer not empty, more work available, etc.)
Hope this helps.
The thread that lost the contest wakes up once the mutex is unlocked, checks the condition again, then goes to sleep on the condition variable.
When any of them returns from pthread_cond_wait() it automatically claims the mutex.
Ah, but it doesn't. Not "automatically", that is, depending on what "automatically" means. You might be confused by the "atomic" semantics of pthread_cond_wait; but that semantics is played out on the entry side: a thread is somehow registered for waiting on the condition before giving up the mutex, so that there isn't any window during which the thread no longer has the mutex, and is not yet waiting on the variable.
Each thread which returns from pthread_cond_wait has to acquire the mutex and therefore contend for it. Those which lose the race for the mutex have to block on the mutex, similarly as if they called pthread_mutex_lock.
The way the mutex is acquired on exit from pthread_cond_wait can be modeled as a regular pthread_mutex_lock operation. Essentially, the threads have to queue up on the mutex in order to exit. Each thread which acquires the mutex then returns from the function; the others have to wait until that thread gives up the mutex before they are allowed to return.
No thread woken up by the signal gets the mutex "automatically", in the sense of somehow being transferred ownership due to special eligibility. Firstly, on a multiprocessor, a woken thread can lose the race to a thread already running on another processor which snatches the mutex, if it is available, or else queue to wait on the mutex ahead of the thread which received the signal. Secondly, the thread which calls pthread_cond_signal may itself not have given up the mutex, and may continue to hold it indefinitely, which means that all the woken threads will queue up on a mutex lock operation and none will emerge from pthread_mutex_lock until that thread gives up the mutex.
All that is "automatic" is that the pthread_cond_wait operation doesn't return until acquiring the mutex again, and so the application doesn't have to take the step to acquire the mutex.
I have encountered a problem while implementing wait and signal conditions on multiple threads.
A thread needs to lock a mutex and wait on a condition variable until some other thread signals it. In the meanwhile, another thread locks the same mutex and waits on the same condition variable. Now, the thread which is running concurrently throughout the process signals the condition variable but I want only the first thread that is waiting must be signalled and not the others.
If two threads wait on the same condition variable, they must be prepared to handle the same conditions, or you must carefully construct your program so they are never waiting on the condition variable at the same time.
Why does this notification have to be handled by the first thread and not the second?
You may be better off with two separate condition variables.
Use pthread_cond_signal() to wake up one of the threads.
However, more than one might be awoken; this is termed spurious wakeup. You need a variable to track your application state, as described in the manual page linked above.
Your requirement is impossible. You say "... I want only the first thread that is waiting must be signalled and not the others." But condition variables never, ever provide any way to ensure a thread isn't signaled. So if you have a requirement that a thread must not be signaled, you cannot use condition variables.
You must always use a condition variable like this:
while(NotSupposedToRun)
pthread_cond_wait(...);
So if the thread wakes up when it's not supposed to, the while is still false and the thread just goes back to sleep. This is mandatory because POSIX does not ever provide any guarantee that a thread won't be woken. An implementation is perfectly free to implement pthread_cond_signal as a call to pthread_cond_broadcast and unblock all threads on every signal if it wants to.
Because condition variables are stateless, the implementation never knows whether a thread is supposed to be woken or not for sure. It is your job to call pthread_cond_wait always, and only, when a thread should not be running.
See
http://en.wikipedia.org/wiki/Spurious_wakeup
for more details.
If you cannot precisely specify the wakeup conditions for each thread in a while loop like the one above, you should not be using condition variables.