Which thread would be notified by pthread_cond_signal? - c

When a thread call pthread_cond_signal(), Unix network programming said pthread_cond_signal() just would nofity just one thread, beacause it isn't pthread_cond_broadcast(). It means there is no race condition. However, the book does not say which thread would be notified, and how. Does the function wake thread randomly?

Straight from the man:
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked.
The "scheduling policy" is the order the operating systems decided on. It's one of the four listed in the below link, but you don't really know (without some impressive hackery at least) which one is "first" anyway. It shouldn't matter either - all threads waiting on the condition should be equally ready to continue - otherwise you have a design problem.
Scheduling policies in Linux Kernel has a bit of discussion on some linux policies, and you can google from there if it's important.

See below my example which will help you to understand about it very clearly.I am using 3 mutexs and 3 conditions. With the below example you can synchronized or prioritize any number of threads in C. If you see the first thread here it locked mutex lock1 and waiting on cond1, likewise second thread locked mutex lock2 and waits on condition cond2 and 3rd thread locked mutex lock3 and waits on condition cond3. This is the current situation of all the threads after they are being created and now all the threads are waiting for a signal to execute further on its condition variable. In the main thread (i.e. main function, every program has one main thread, in C/C++ this main thread created automatically by operating system once control pass to the main method by kernal) we are calling pthread_cond_signal(&cond1); once this system call done thread1 who was waiting on cond1 will be release and it will start executing. Once it finished with its task it will call pthread_cond_signal(&cond3); now thread who was waiting on condition cond3 i.e. thread3 will be release and it will start execute and will call pthread_cond_signal(&cond2); which will release the thread who is waiting on condition cond2 i.e. in this case thread2.
include<pthread.h>
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock3 = PTHREAD_MUTEX_INITIALIZER;
int TRUE = 1;
void print(char *p)
{
printf("%s",p);
}
void * threadMethod1(void *arg)
{
printf("In thread1\n");
do{
pthread_mutex_lock(&lock1);
pthread_cond_wait(&cond1, &lock1);
print("I am thread 1st\n");
pthread_cond_signal(&cond3);/* Now allow 3rd thread to process */
pthread_mutex_unlock(&lock1);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod2(void *arg)
{
printf("In thread2\n");
do
{
pthread_mutex_lock(&lock2);
pthread_cond_wait(&cond2, &lock2);
print("I am thread 2nd\n");
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&lock2);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod3(void *arg)
{
printf("In thread3\n");
do
{
pthread_mutex_lock(&lock3);
pthread_cond_wait(&cond3, &lock3);
print("I am thread 3rd\n");
pthread_cond_signal(&cond2);
pthread_mutex_unlock(&lock3);
}while(TRUE);
pthread_exit(NULL);
}
int main(void)
{
pthread_t tid1, tid2, tid3;
int i = 0;
printf("Before creating the threads\n");
if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
printf("Failed to create thread1\n");
if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
printf("Failed to create thread2\n");
if( pthread_create(&tid3, NULL, threadMethod3, NULL) != 0 )
printf("Failed to create thread3\n");
pthread_cond_signal(&cond1);/* Now allow first thread to process first */
sleep(1);
TRUE = 0;/* Stop all the thread */
sleep(3);
/* this is how we join thread before exit from a system */
/*
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);*/
exit(0);
}

Yes, it will wake one thread seemingly randomly. It's up to the operating system to decide which one will be woken.

Related

Pthread execute unexpectedly in C

I want to let pthreads can run their task in a specified order:
thread 1 -> thread 3 -> thread 2
When I run my code, I found the result is not fixed.
My OS is Ubuntu 16.04
Sometimes the result is (unexpectd) :
Before creating the threads
In thread1
In thread2
!!!!!!!!!!!!!!!!!!
I am thread1 generating the final report and inserting into a table
In thread3
Sometimes the result is (expectd) :
Before creating the threads
In thread1
In thread2
In thread3
!!!!!!!!!!!!!!!!!!
I am thread1 generating the final report and inserting into a table
I am thread3 generating the final report and inserting into a table
I am thread2 generating the final report and inserting into a table
I am thread1 generating the final report and inserting into a table
I am thread3 generating the final report and inserting into a table
I am thread2 generating the final report and inserting into a table
I am thread1 generating the final report and inserting into a table
I am thread3 generating the final report and inserting into a table
I am thread2 generating the final report and inserting into a table
I am thread1 generating the final report and inserting into a table
I am thread3 generating the final report and inserting into a table
below is my code:
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <signal.h>
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock3 = PTHREAD_MUTEX_INITIALIZER;
int TRUE = 1;
void * threadMethod1(void *arg)
{
printf("In thread1\n");
do{
pthread_mutex_lock(&lock1);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond1, &lock1);
printf("I am thread1 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond3);/* Now allow 3rd thread to process */
pthread_mutex_unlock(&lock1);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod2(void *arg)
{
printf("In thread2\n");
do
{
pthread_mutex_lock(&lock2);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond2, &lock2);
printf("I am thread2 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&lock2);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod3(void *arg)
{
printf("In thread3\n");
do
{
pthread_mutex_lock(&lock3);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond3, &lock3);
printf("I am thread3 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond2);
pthread_mutex_unlock(&lock3);
}while(TRUE);
pthread_exit(NULL);
}
void my_alarm_handler(int a)
{
TRUE = 0;//重新設定
}
int main(void)
{
pthread_t tid1, tid2, tid3;
int i = 0;
signal( SIGALRM, my_alarm_handler );
printf("Before creating the threads\n");
if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
printf("Failed to create thread1\n");
if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
printf("Failed to create thread2\n");
if( pthread_create(&tid3, NULL, threadMethod3, NULL) != 0 )
printf("Failed to create thread3\n");
pthread_cond_signal(&cond1);/* Now allow first thread to process first */
alarm(1);
//TRUE = 0;/* Stop all the thread */
/* this is how we join thread before exit from a system */
printf("!!!!!!!!!!!!!!!!!!\n");
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
return 0;
}
What wrong make the result is not fixed?
thank you in advance!
You are using your condition variables incorrectly. As the Linux manual page for pthread_cond_wait() puts it:
When using condition variables there is always a Boolean predicate
involving shared variables associated with each condition wait that is
true if the thread should proceed. Spurious wakeups from the
pthread_cond_timedwait() or pthread_cond_wait() functions may occur.
Since the return from pthread_cond_timedwait() or pthread_cond_wait()
does not imply anything about the value of this predicate, the
predicate should be re-evaluated upon such return.
That means that it is not appropriate for a thread to interpret returning from a pthread_cond_wait() as an indication that it should proceed. Instead, it should interpret such a return as a sign that it should check some condition involving one or more shared variables to determine whether it should proceed. If the condition is not satisfied then typically, it should wait some more. It usually is appropriate to check the condition before waiting the first time, too, to avoid missing a signal.
Of course, all accesses to a shared variable should be performed under protection of the same mutex, at least if any of them may be writes.
On the receiving side, that all looks something like this:
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
_Bool should_proceed1 = 0;
void *thread1(void *arg) {
pthread_mutex_lock(&lock1);
while (!should_proceed1) {
pthread_cond_wait(&cond1, &lock1);
}
pthread_mutex_unlock(&lock1);
// ...
}
On the signaling side, it might look like this:
pthread_mutex_lock(&lock1);
should_proceed1 = 1;
pthread_mutex_unlock(&lock1);
pthread_cond_signal(&cond1);
Note that the shared variable should_proceed1 is accessed under protection of the same mutex in both places, and that this is also the mutex that the waiting thread associates with the CV for its wait. Also, the pthread_cond_signal() call can happen inside the mutex-protected region, too -- you don't have to unlock the mutex first -- but although a waiting thread will wake immediately (if there are any), it will not proceed until it can reacquire the mutex.
Use of pthread_cond_wait outside of a condition (usually a loop) testing some condition dependent on the state protected by the mutex is always an error. In the comments, dragosht noted:
You're not waiting for thread1 to wait on the condition variable
But there's no way to "wait on a thread to wait on the condition variable". Instead, the thread must not wait on the condition variable if the condition it's waiting for has already been satisfied.
Instead you should be doing something like:
while (next_to_run != MY_NUMBER)
pthread_cond_wait(&cond, &lock);
and the signaling thread should be setting next_to_run before signaling (with the mutex held).

About threads and condition variable and synchronise

i am trying to understand the condition variables in thread programming can anyone explain how it works with the mutex and what are the condition variable so it can synchronise threads??
condition variables and threads
Here you go. Here I am using 3 mutexs and 3 condition variables. With the below examples you can schedule or control any number of threads in C. First look at the first thread below. Here it locked mutex lock1 (so that other thread could not access the codes) starts executing (codes not added just comments) and finally after completing its task waiting on cond1, likewise second thread locked mutex lock2, starts executing its business logic and finally waits on condition cond2 and 3rd thread locked mutex lock3, starts executing its business logic and finally waits on condition cond3. I am not adding any business logic here because this is just an example. In the commented section you can add your business logic which will execute in parallel mode. Suppose thread3 depends on final output of thread1 which is going to be inserted in a table and thread3 will read that information before creating it final result and thread2 depends on final outcome of thread3 to generate its final outcome. Hence thread1 after inserting the data into table, signals thread3 through condition variable to go ahead with its final process. That means thread1 controls thread3. As thread2 depends on final outcome from thread3, hence thread3 controls the execution of Thread2. Here we can allow thread1 to execute independently as its operation does not depends on any other thread, but for example of thread control we are controlling all the threads here and hence thread1 is being controlled from thread2.
To start the controlling process, we are releasing thread1 first. In the main thread (i.e. main function, every program has one main thread, in C/C++ this main thread is created automatically by operating system once the control pass to the main method/function by kernel) we are calling pthread_cond_signal(&cond1); Once this function called from main thread, thread1 which was waiting on cond1 will be released and it will start executing further. Once it finishes with its final task, it will call pthread_cond_signal(&cond3); now thread which was waiting on condition cond3 i.e. thread3 will be released and it will start to execute it’s final stage and will call pthread_cond_signal(&cond2); and it will release the thread which is waiting on condition cond2 i.e. in this case thread2. This is the way we can schedule and control execution of thread in multi-threaded environment.
#include<pthread.h>
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock3 = PTHREAD_MUTEX_INITIALIZER;
int TRUE = 1;
void * threadMethod1(void *arg)
{
printf("In thread1\n");
do{
pthread_mutex_lock(&lock1);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond1, &lock1);
printf("I am thread1 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond3);/* Now allow 3rd thread to process */
pthread_mutex_unlock(&lock1);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod2(void *arg)
{
printf("In thread2\n");
do
{
pthread_mutex_lock(&lock2);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond2, &lock2);
printf("I am thread2 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&lock2);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod3(void *arg)
{
printf("In thread3\n");
do
{
pthread_mutex_lock(&lock3);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond3, &lock3);
printf("I am thread3 generating the final report and inserting into a table \n");
pthread_cond_signal(&cond2);
pthread_mutex_unlock(&lock3);
}while(TRUE);
pthread_exit(NULL);
}
int main(void)
{
pthread_t tid1, tid2, tid3;
int i = 0;
printf("Before creating the threads\n");
if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
printf("Failed to create thread1\n");
if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
printf("Failed to create thread2\n");
if( pthread_create(&tid3, NULL, threadMethod3, NULL) != 0 )
printf("Failed to create thread3\n");
pthread_cond_signal(&cond1);/* Now allow first thread to process first */
sleep(1);
TRUE = 0;/* Stop all the thread */
sleep(3);
/* this is how we join thread before exit from a system */
/*
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);*/
exit(0);
}

Using pthread_cond_t to signal end of execution

I am using pthread_cond_t to signal the end of execution of child threads to the main thread. Since I'm not synchronizing the access to a shared resource, I wonder what the loop embracing pthread_cond_wait would be? Here's what I have:
pthread_mutex_t mutex;
pthread_cond_t cond;
int main(int argc, char *argv[])
{
pthread_cond_init(&cond, NULL);
cond = PTHREAD_COND_INITIALIZER;
pthread_create(&tid1, NULL, func1, NULL);
pthread_create(&tid2, NULL, func2, NULL);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
//Join the thread that first completes
}
void *func1(void *arg)
{
....
pthread_cond_signal(&cond);
pthread_exit((void *) 1);
}
void *func2(void *arg)
{
....
pthread_cond_signal(&cond);
pthread_exit((void *) 1);
}
Would the main thread, by default, wait until thread1 or thread2 send it a signal or would we need some sort of a conditional loop around the wait?
Also, how would the main thread have access to the exit status of the thread that signaled without explicitly calling pthread_join? Or, is there a way to get the thread_id of the thread that signaled so that the main thread may join it to retrieve its exit status?
If both threads run to completion before the main thread reaches the pthread_cond_wait(), then it will wait forever. Otherwise, the main thread will wait until one of the other threads signals the condition.
No, you cannot ask the condition who signalled it.
Your pthread condition has no memory; if no thread is waiting on the condition when it is signalled, the signal is not remembered. What matters is the state you manage, protected by the mutex. The pthread condition is simply the mechanism which allows the thread to wait if the state requires it.
So, whatever information you need to pass from the child threads to the parent, the trick is to do that under the mutex. In this case you want to pass the fact that the child has finished. Perhaps a simple bool, so the main thread:
pthread_mutex_lock(&mutex) ;
while (!t1_done && !t2_done)
pthread_cond_wait(&cond, &mutex) ;
pthread_mutex_unlock(&mutex) ;
And thread the first:
pthread_mutex_lock(&mutex) ;
t1_done = true ;
pthread_cond_signal(&cond) ;
pthread_mutex_unlock(&mutex) ;
...all pretty straightforward, really.

understanding pthread_cond_wait() and pthread_cond_signal()

I have this code as an example where two threads are created and then it looks like a pthread_cond_wait() is used to suspend that thread until it is ready to work again by the use of pthread_cond_signal(). My question is what if multiple threads are waiting at the same time? How will executing pthread_cond_signal() pick the correct thread to wake up? Is there a way to pick a specific thread to awake? Lets say i have a producer thread that puts customer orders into seperate queues where each queue is managed by a thread. If two consumer threads are suspend with wait() because they have nothing in their queue but then the producer thread only inserts an order into ONE of the consumer queues, how the heck do we differentiate? If this is not possible then what OTHER methods can i use to accomplish what i want?
Here is an example code because stackoverflow likes code... not that relevant:
Example
#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include "check.h"
/* For safe condition variable usage, must use a boolean predicate and */
/* a mutex with the condition. */
int workToDo = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#define NTHREADS 2
void *threadfunc(void *parm)
{
int rc;
while (1) {
/* Usually worker threads will loop on these operations */
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
while (!workToDo) {
printf("Thread blocked\n");
rc = pthread_cond_wait(&cond, &mutex);
checkResults("pthread_cond_wait()\n", rc);
}
printf("Thread awake, finish work!\n");
/* Under protection of the lock, complete or remove the work */
/* from whatever worker queue we have. Here it is simply a flag */
workToDo = 0;
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
}
return NULL;
}
int main(int argc, char **argv)
{
int rc=0;
int i;
pthread_t threadid[NTHREADS];
printf("Enter Testcase - %s\n", argv[0]);
printf("Create %d threads\n", NTHREADS);
for(i=0; i<NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
sleep(5); /* Sleep is not a very robust way to serialize threads */
for(i=0; i<5; ++i) {
printf("Wake up a worker, work to do...\n");
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
/* In the real world, all the threads might be busy, and */
/* we would add work to a queue instead of simply using a flag */
/* In that case the boolean predicate might be some boolean */
/* statement like: if (the-queue-contains-work) */
if (workToDo) {
printf("Work already present, likely threads are busy\n");
}
workToDo = 1;
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_broadcast()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
sleep(5); /* Sleep is not a very robust way to serialize threads */
}
printf("Main completed\n");
exit(0);
return 0;
}
Output:
Enter Testcase - QP0WTEST/TPCOS0
Create 2 threads
Thread blocked
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Main completed
In practical terms, only one thread is awakened and you can't control which one it is.
(pthread_cond_signal wakes up at least one thread waiting on the given condition variable, and the thread chosen is determined by scheduling policy.)
In your case, you need to reconsider what the "condition" represented by your condition variable (condvar) means.
If the condvar truly means "a producer has added an item to one of several queues, each of which has a dedicated consumer," then you should pthread_cond_broadcast to awaken each queue's consumer and let the awakened threads figure out if there is work to do. Alternatively, you might recast the condition as "a producer has added an item to this queue, which has a dedicated consumer," and use one condvar per queue.

Check to see if a pthread mutex is locked or unlocked (After a thread has locked itself)

I need to see if a mutex is locked or unlocked in an if statement so I check it like this...
if(mutex[id] != 2){
/* do stuff */
}
but when I check it gcc gives me the following error:
error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')
So how can I check to see if the mutex is locked or not?
EDIT:
A key component to my problem is that my threads (by design) lock themselves right AFTER passing control to another thread. So when thread A passes control to thread B thread A is locked, thread B does some stuff, then when thread B is done it will unlock thread A.
The problem with this is that if thread B attempts to unlock thread A and thread A has not yet completed locking itself then the call to unlock is lost and thread A remains locked which causes a dead lock.
UPDATE:
I remade my program taking caf's suggestion but I am still running into problems. I have molded my program into the structure caf provided the best I can but I cannot even tell what is causing the dead lock now... I have created a new question here seeking help with my code.
Below is a runnable version of caf's suggestion. I made a small reordering in the function for thread a, without which both thread a and thread b would have been locked upon their creation, waiting for a condition that could never change.
#include <pthread.h>
int run_a = 0;
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER;
int run_b = 0;
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;
void *a(void *);
void *b(void *);
int main(){
int status;
pthread_t thread_a;
pthread_t thread_b;
pthread_create(&thread_a, NULL, a, (void *)0);
pthread_create(&thread_b, NULL, b, (void *)0);
pthread_join(thread_a, (void **)&status);
pthread_join(thread_b, (void **)&status);
}
/* thread A */
void *a(void *i){
while (1) {
printf("thread A is running\n");
sleep(1);
/* unlock thread B */
pthread_mutex_lock(&lock_b);
run_b = 1;
pthread_cond_signal(&cond_b);
pthread_mutex_unlock(&lock_b);
/* wait for thread A to be runnable */
pthread_mutex_lock(&lock_a);
while (!run_a)
pthread_cond_wait(&cond_a, &lock_a);
run_a = 0;
pthread_mutex_unlock(&lock_a);
}
}
/* thread B */
void *b(void *i){
while (1) {
/* wait for thread B to be runnable */
pthread_mutex_lock(&lock_b);
while (!run_b)
pthread_cond_wait(&cond_b, &lock_b);
run_b = 0;
pthread_mutex_unlock(&lock_b);
printf("thread B is running\n");
sleep(1);
/* unlock thread A */
pthread_mutex_lock(&lock_a);
run_a = 1;
pthread_cond_signal(&cond_a);
pthread_mutex_unlock(&lock_a);
}
}
You can use pthread_mutex_trylock. If that succeeds, the mutex was unclaimed and you now own it (so you should release it and return "unheld", in your case). Otherwise, someone is holding it.
I have to stress though that "check to see if a mutex is unclaimed" is a very bad idea. There are inherent race conditions in this kind of thinking. If such a function tells you at time t that the lock is unheld, that says absolutely nothing about whether or not some other thread acquired the lock at t+1.
In case this is better illustrated with a code example, consider:
bool held = is_lock_held();
if (!held)
{
// What exactly can you conclude here? Pretty much nothing.
// It was unheld at some point in the past but it might be held
// by the time you got to this point, or by the time you do your
// next instruction...
}
Mutexes are not the right primitive for the scheme that you want to implement. You should be using condition variables:
int run_thread_a = 0;
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER;
int run_thread_b = 0;
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER;
/* thread A */
while (1) {
/* Wait for Thread A to be runnable */
pthread_mutex_lock(&run_lock_a);
while (!run_thread_a)
pthread_cond_wait(&run_cond_a, &run_lock_a);
run_thread_a = 0;
pthread_mutex_unlock(&run_lock_a);
/* Do some work */
/* Now wake thread B */
pthread_mutex_lock(&run_lock_b);
run_thread_b = 1;
pthread_cond_signal(&run_cond_b);
pthread_mutex_unlock(&run_lock_b);
}
/* thread B */
while (1) {
/* Wait for Thread B to be runnable */
pthread_mutex_lock(&run_lock_b);
while (!run_thread_b)
pthread_cond_wait(&run_cond_b, &run_lock_b);
run_thread_b = 0;
pthread_mutex_unlock(&run_lock_b);
/* Do some work */
/* Now wake thread A */
pthread_mutex_lock(&run_lock_a);
run_thread_a = 1;
pthread_cond_signal(&run_cond_a);
pthread_mutex_unlock(&run_lock_a);
}
Each thread will block in pthread_cond_wait() until the other thread signals it to wake up. This will not deadlock.
It can easily be extended to many threads, by allocating one int, pthread_cond_t and pthread_mutex_t per thread.
You can't compare a pthread_mutex_t with a int.
You can use
int pthread_mutex_trylock(pthread_mutex_t *mutex);
to check that.

Resources