Pthread condition wait and signal - c

I have a doubt regarding pthread_cond_wait and pthread_cond_signal functions. I was not able to understand after reading the man pages also.
Please consider the following code.
void* thread_handler(){
... // counts till COUNT_LIMIT is reached
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
my_id, count);
...
}
void* thread_handler1(){
... // waits till the previous thread has finished counting
pthread_mutex_lock(&count_mutex);
while (count<COUNT_LIMIT) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %ld Condition signal received.\n", my_id);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
The code is working as per expectations. I am trying to understand the code. Here is how the program works
Enter thread_handler1 and do cond_wait. From the man page i understood that cond_wait will immediatly release the lock atomically. So why are they releasing the lock again below in thread_handler1
After first thread has satisfied the condition and hits the condition signal I expected the thread which was blocking to execute its steps. Instead i got the printfs below the thread which executed the cond_signal. Why is this happening
Overall why do we need to take a lock before waiting and signalling. Cant this be done without a lock.
For a briefer look at the program, please see the Complete program here. You can find it under the section "Using Conditional Variables"
Thanks in advance
Chidambaram

Enter thread_handler1 and do cond_wait. From the man page i understood
that cond_wait will immediatly release the lock atomically. So why are
they releasing the lock again below in thread_handler1
Because the thread that is supposed to wait will release the lock when calling wait, but will then reacquire after it gets signaled (when it becomes available). That's why you need to rerelease it explicitly later.
After first thread has satisfied the condition and hits the condition
signal I expected the thread which was blocking to execute its steps.
Instead i got the printfs below the thread which executed the
cond_signal. Why is this happening
Because calling signal does not switch the thread from the CPU. It will continue to run normally.

Related

Thread synchronization in Linux?

I am writing a code wherein I am making my threads wait till I do a pthread_cond_broadcast. I have three threads in this code. Threads line2_thread and line3_thread, are running in the order of their priority like they are supposed to run. However, my third thread doesn't even enter its thread function (line4_thread). Can anyone tell me why is my main() not being able to call my line4_thread ?
pthread_cond_t sstart;
pthread_mutex_t sstart_mutex;
void *l3_thread(void *arg){
pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/
pthread_exit(NULL);
}
void *l2_thread(void *arg){
pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/
pthread_exit(NULL);
}
void *l4_thread(void *arg){
pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/
pthread_exit(NULL);
}
int main(){
pthread_cond_init(&sstart, NULL);
//thread creation
pthread_cond_broadcast(&sstart);
pthread_cond_destroy(&sstart);
pthread_mutex_destroy(&sstart_mutex);
return 0;
}
I think you have a few problems here. With apologies (I'm on my phone so typing a long answer is hard) I'm just going to focus on a couple things, since it's not 100% clear to me what you're actually trying to do.
When all your threads start they all try to acquire the mutex, and only one succeeds. Probably l3 but I don't think that's guaranteed here. It then calls the pthread_cond_wait and unlocks the mutex allowing one of the other threads to reach its pthread_cond_wait. But in the meantime. You've allowed your main thread to call pthread_cond_broadcast, and you've taken no steps to synchronize this with the other threads. It may happen before the others get unblocked from waiting for the mutex, and before their wait call, so they could miss the signal and block forever.
Further, I think it's a bit sketchy to immediately call pthread_cond_destroy. Like I said there's no synchronization between your main thread and your worker threads, so it's possible you could call pthread_cond_broadcast followed by pthread_cond_destroy, so some of your threads might be calling pthread_cond_wait on an invalid condition variable and deadlock.
Check the return values of pthread_cond_wait. If I'm right, it might return EINVAL in some cases. But I haven't tested this so there might be a flaw in my reasoning.

why PTHREAD_MUTEX_ADAPTIVE_NP behaves like PTHREAD_MUTEX_TIMED_NP when more than one pthreads compete for the mutex lock

Program creates a PTHREAD_MUTEX_ADAPTIVE_NP mutex, and now thread A gets the lock. Three threads(B, C, D) compete for this lock when thread A give it.
What I wonder is, why the thread which have waited for the longest time always first gets this lock and then the second longest time thread...and so on.
I think PTHREAD_MUTEX_ADAPTIVE_NP is like pthread_spinlock just like answer of Kaz Sir in What is PTHREAD_MUTEX_ADAPTIVE_NP:
The approach is also not suitable in situations in which fairness is important: it is an opportunistic lock.
Your basic idea is correct. However, the adaptive mutex only busy-spins for a very short time (a loop with at most 100 PAUSE instruction calls). As soon as it enters the kernel-sleep phase, it behaves like a regular mutex again.
This is because adaptive mutexes are meant for very short, very aggressively contended locked sections, so that there is a reasonable chance that a 100-loop spin will lead to the lock becoming available.
So given your second-long sleep calls, all your locks are sleeping in the kernel and the busyspin logic is irrelevant.
You can look up the implementation of adaptive mutexes here for pthread_mutex_lock.c. In case the busy-spin fails to acquire the lock, nptl falls back to futex locks, which I believe are at least a deterministic order.
Code like this
`Thread A:
main() {
mutex_lock;
pthread_create(B);
pthread_create(C);
pthread_create(D);
sleep(3);
mutex_unlock;
}`
Thread B() {
sleep(2);
mutex_lock;
printf("Thread B");
mutex_unlock;
}
Thread C() {
sleep(1);
mutex_lock;
printf("Thread C");
mutex_unlock;
}
Thread D() {
mutex_lock;
printf("Thread D");
mutex_unlock;
}
The trace is always first "Thread D" -> Second "Thread C" -> last "Thread B"
Sleep cause ADAPTIVE mutex to TIMED mutex?

pthread_mutex_trylock() use to wait , until other lock has not released

In my code I am using pthread_mutx_trylock() to check thread 1 has completed his
job and release the mutexlock or not ?Please let me know either its a valid way or not ?
In Thread 1:
pthread_mutex_lock(&sync_wait);
// Waiting for return type.
pthread_mutex_unlock(&sync_wait);
In Thread 2:
while (pthread_mutex_trylock(&sync_wait) == 0) {
}; // Wait until other thread has lock
// Waiting till thread 1 sync wait lock has not released.
pthread_mutex_unlock(&sync_wait);
From manual Page
The pthread_mutex_trylock() function shall return zero if a lock on
the mutex object referenced by mutex is acquired. Otherwise, an error
number is returned to indicate the error.
// so this will loop forever once you aquire lock
while (pthread_mutex_trylock(&sync_wait) == 0) {
}; // Wait until other thread has lock
Edit:
This section of code should handle your scenario
while ( int ret = pthread_mutex_trylock( &sync_wait) )
{
// Unable to get Mutex probably some other thread aquired it
// sleep for some time usleep or even better use pthread_mutex_timedlock
// Ideally possible ret values should have been handled but for now
// this will do
}
and yes pthread_mutex_unlock( );once done with work
here is the manpage
also there is a question on so about difference between pthread_mutex_lock and pthread_mutex_trylock here
this is another example of handling multiple return values from pthread_try_lock()
If you want to wake up a specific thread once another thread reaches a certain point in its execution, mutexes are typically not the appropriate synchronization primitive. Alternatives are:
Barriers and the pthread_barrier_wait function
Conditional variables and the pthread_cond_wait and pthread_cond_signal functions
Possibly semaphores and the sem_wait and sem_post functions

Explanation why conditional variable in C does not work correctly

I want to write a simple multithreaded program making use of conditional variables in C.
I want to have main thread (thread A) which sleeps 5 sec and then wake up waiting clients (therads B, possible many) that print a message. This should be repeated all the time.
I have already read the manual but I don't understand why this does not work.
Let's assume that I have those variables given to all threads via pointers (properly, I have checked that):
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int* variable;
I have the following code:
THREAD A (sleeping):
while(1)
{
lockMutex(mutex);
(*variable) = 1;
pthread_cond_broadcast(cond);
unlockMutex(mutex);
sleep(5);
lockMutex(mutex);
(*variable) = 0;
pthread_cond_broadcast(cond);
unlockMutex(mutex);
}
THREAD B (printing):
while(1)
{
lockMutex(mutex);
while((*variable) == 1)
pthread_cond_wait(cond, mutex);
unlockMutex(mutex);
fprintf("Active thread! Number: %d\n", id);
lockMutex(mutex);
while((*(variable))==0)
pthread_cond_wait(cond, mutex);
unlockMutex(mutex);
}
I don't have deadlock, but unfortunatelly this doesn't work as I expected. Can somebody give me an explanation what should I do? I would be grateful for any help.
The likely problem is that Thread A is immediately setting *variable = 1 before any of the sleeping threads have a chance to see it as 0. Just because the condition variable will wake up waiting threads doesn't mean those woken threads will get scheduled fast enough to prevent Thread A from writing to *variable again.

pthread_cond_signal blocks the thread

I have the following code running for N threads with count=0 initially as shared variable. Every variable is initialised before the working of the threads. I am trying to execute the critical section of code only for MAX number of threads.
void *tmain(){
while(1){
pthread_mutex_lock(&count_mutex);
count++;
if(count>MAX){
pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
pthread_mutex_unlock(&count_mutex);
/*
some code not associated with count_mutex or count_threshold_cv
*/
pthread_mutex_lock(&count_mutex);
count--;
pthread_cond_signal(&count_threshold_cv);
pthread_mutex_unlock(&count_mutex);
}
}
But after running for some time the threads get blocked at pthread_cond_signal(). I am unable to understand why this is occuring. Any help is appreciated.
This code has one weak point that may lead to a blocking problem.
More precisely, it is not protected against so called spurious wakes up,
meaning that the pthread_cond_wait() function may return when no signal were delivered explicitly by calling either pthread_cond_signal() or pthread_cond_broadcast().
Therefore, the following lines from the code do not guarantee that the thread wakes up when the count variable is less or equal MAX
if(count>MAX){
pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
Let's see what may happen when one thread wakes up when the count still greater than MAX:
immediately after that the mutex is unlocked.
Now other thread can enter the critical session and increment the count variable more than expected:
pthread_mutex_lock(&count_mutex);
count++;
How to protect code against spurious signals?
The pthread_cond_wait wake up is a recommendation to check the predicate (count>MAX).
If it is still false, we need to continue to wait on the conditional variable.
Try to fix your code by changing the if statement to the while statement (and, as remarked by #alk, change the tmain() signature):
while(count>MAX)
{
pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
Now, if a spurious wake up occurs and the count still greater than MAX,
the flow will wait on the conditional variable again. The flow will escape the waiting loop only when a wake up is accompanied by the predicate change.
The reason your code blocks is because you place count++ before the wait:
count++;
if(count>MAX){
pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
Instead you should write
while (count >= MAX) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
count++;
The reason is that count should be the number of working threads.
A thread must only increment count when it is done waiting.
Your count variable, on the other hand, counts the number of working threads plus the number of waiting threads. This count is too large and leads to the condition count > MAX being true which blocks.
You should also replace "if" with "while" as MichaelGoren writes. Using "if" instead of "while" does not lead to blocking, but rather to too many threads running simultaneously; the woken thread starts working even if count > MAX.
The reason that you need "while" is that pthread_cond_signal unblocks one of the waiting threads. The unblocked thread, however, is still waiting for the mutex, and it is not necessarily scheduled to run either. When the awoken thread finally acquires the mutex and starts running, the call to pthread_cond_wait returns. In the mean time, between pthread_cond_signal and return of pthread_cond_wait, other threads could have owned the mutex. So you must check the condition again, which is what "while" does.
Also, because count++ is now after wait, the condition becomes count >= MAX instead of count > MAX. You should wait even if the number of workers is MAX.
Alternatively, you could have used semaphores for this problem.

Resources