Mutex Threading - Code doesn't seem to Exit Properly - c

So I have code here which makes two kinds of threads. One kind "produces" data and the other one "consumes" it. There can only be a certain amount of data that can exist at any one time, so the Producers will pause producing once there is a certain amount of data created (ie, when sharedData = BUFFER), and the consumers will pause when sharedData = 0. There is also only so much data that can be made (amount stored in dataleft), and once all the data has been made and consumed, the program should end.
For some reason, the printf() lines I have at the end of the code don't seem to ever trigger. I can't tell if the threads are closed properly or not because of this. It feels like I've done something really stupid, but I can't see the issue.
A couple of definitions at the start:
#define NUMCONSUMERS 4
#define NUMPRODUCERS 4
#define PACKETS 10
#define tryMainlock pthread_mutex_trylock(&dataMutex)
#define openMainlock pthread_mutex_lock(&dataMutex)
#define closeMainlock pthread_mutex_unlock(&dataMutex)
#define waitMainlock pthread_cond_wait(&dataPresentCondition, &dataMutex);
#define signalMainlock pthread_cond_signal(&dataPresentCondition);
#define trydatalock pthread_mutex_trylock(&IsthereDataleft)
#define opendatalock pthread_mutex_lock(&IsthereDataleft)
#define closedatalock pthread_mutex_unlock(&IsthereDataleft)
pthread_mutex_t dataMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t dataPresentCondition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t IsthereDataleft = PTHREAD_MUTEX_INITIALIZER;
int sharedData=0; //amount of data present
int BUFFER = 5;
int dataleft=PACKETS;
The Main Function:
int main(int argc, char **argv)
{
int rc;
int i;
pthread_t consumer[NUMCONSUMERS];
pthread_t producer[NUMPRODUCERS];
rc = opendatalock; //lock to determine whether there's any point waiting for data
for (i=0; i <NUMPRODUCERS; i++) { //Build up the producers
rc = pthread_create(&producer[i], NULL, Producer, (void *)i);
if (rc)
printf("Error building Producer Thread: %x\n", i);
}
for (i=0; i <NUMCONSUMERS; i++) { //Build up the consumers
rc = pthread_create(&consumer[i], NULL, Consumer, (void *)i);
if (rc)
printf("Error building Consumer Thread: %x\n", i);
}
printf("All Producers and Consumers created\n");
for (i=0; i <NUMPRODUCERS; i++) { //Join up the producers
rc = pthread_join(producer[i], NULL);
if (rc)
printf("Error: Producer %x: Failed to join\n", i);
}
rc = closedatalock; //producers finished, no data left to make
printf("datalock closed, consumers finishing...\n");
for (i=0; i <NUMCONSUMERS; i++) { //Join up the consumers
rc = pthread_join(consumer[i], NULL);
if (rc)
printf("Error: Consumer %x: Failed to join\n", i);
}
rc = pthread_mutex_destroy(&dataMutex);
rc = pthread_cond_destroy(&dataPresentCondition);
rc = pthread_mutex_destroy(&IsthereDataleft);
printf("All Threads finished. Exiting....\n");
return 0;
}
The Consumer Thread:
void *Consumer(void *threadid){
int rc;
printf("Consumer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Consumer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of main lock
if (rc)
{
printf("Consumer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //if main lock is taken, wait
if (rc) //if wait fails, exit the thread.
{
printf("Consumer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
while (sharedData == 0) //if the buffer is empty
{
rc = trydatalock;
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
sharedData--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Consumer %x: Releasing Lock\n", (int)threadid);
}
}
And the Producer Thread:
void *Producer(void *threadid){
int rc;
printf("Producer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Producer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of the lock
if (rc) //if lock is currently being used by a consumer or a producer
{
printf("Producer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //wait here until lock is released
if (rc)
{
printf("Producer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
if (!dataleft) //If there's no data left to add to the stream, close the thread
{
printf("Producer Thread %x: Completed, exiting...\n", (int)threadid);
exit(0);
}
while (sharedData >=BUFFER)
{
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
printf("Producer %x: Lock Acquired\n", (int)threadid);
sharedData++;
dataleft--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Producer %x: Releasing Lock\n", (int)threadid);
}
}

Check out this piece of code:
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
If the consumer has finished, the process(!) is terminated. You need to use pthread_exit() instead, or simply return from the thread function.
Then, there is also
../nptl/pthread_mutex_lock.c:80:
__pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
which I got a few times running the code. That could be caused by e.g. double unlock or some other invalid use. I'd start with cleaning up the weird macros, so that you have a free view on the logic of the program itself.
Also, one important advise concerning mutexes: Always document precisely which data should be protected by the mutex. The point is that it's not always clear and getting this wrong means that you accidentally access data without synchronization. In order to make this very clear, use a structure like here:
struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int data;
} synced_data = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER,
0
};
Actually, it's not just about the shared data that documentation is important. Consider for example IsthereDataleft: This is a mutex but it doesn't guard anything, right? Instead, it is used to signal to the started threads that there is nothing left to do, right? Documenting this not only helps others to understand your code but it makes sure that you understand yourself what the intention is. Sometimes, while trying to explain it, you will then find yourself that something doesn't make sense.

Something seems to be awry with your use of openMainlock, which expands to a pthread_mutex_lock call.
One one hand, you shouldn't expect to ever get a non-zero return value from openMainlock: pthread_mutex_lock should either return zero (lock acquired) or block, unless the mutex is not initialised or is an error-checking mutex.
Further, once the lock is acquired, if the producer is done, i.e. dataleft is zero, the thread calls exit(0), which will terminate the whole process rather than terminating the thread. pthread_exit should be used instead, or just return from the function, but note that at this point you still own the main lock, which won't be released.

Related

Why some threads don't receive pthread_cond_broadcast?

I have a threadpool of workers. Each worker executes this routine:
void* worker(void* args){
...
pthread_mutex_lock(&mtx);
while (queue == NULL && stop == 0){
pthread_cond_wait(&cond, &mtx);
}
el = pop(queue);
pthread_mutex_unlock(&mtx);
...
}
main thread:
int main(){
...
while (stop == 0){
...
pthread_mutex_lock(&mtx);
insert(queue, el);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
...
}
...
}
Then I have a signal handler that executes this code when it receives a signal:
void exit_handler(){
stop = 1;
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mtx);
}
I have omitted declarations and initialization, but the original code has them.
After a signal is received most of the time it's all ok, but sometimes it seems that some worker threads stay in the wait loop because they don't see that the variable stop is changed and/or they are not waken up by the broadcast.
So the threads never end.
What I am missing?
EDIT: stop=1 moved inside the critical section in exit_handler. The issue remains.
EDIT2: I was executing the program on a VM with Ubuntu. Since the code appears to be totally right I tried to change VM and OS (XUbuntu) and now it seems to work correctly. Still don't know why, anyone has an idea?
Some guessing here, but it's too long for a comment, so if this is wrong, I will delete. I think you may have a misconception about how pthread_cond_broadcast works (at least something I've been burned with in the past). From the man page:
The pthread_cond_broadcast() function shall unblock all threads
currently blocked on the specified condition variable cond.
Ok, that make sense, _broadcast awakens all threads currently blocked on cond. However, only one of the awakened threads will then be able to lock the mutex after they're all awoken. Also from the man page:
The thread(s) that are unblocked shall contend for the mutex according
to the scheduling policy (if applicable), and as if each had called
pthread_mutex_lock().
So this means that if 3 threads are blocked on cond and _broadcast is called, all 3 threads will wake up, but only 1 can grab the mutex. The other 2 will still be stuck in pthread_cond_wait, waiting on a signal. Because of this, they don't see stop set to 1, and exit_handler (I'm assuming a Ctrl+c software signal?) is done signaling, so the remaining threads that lost the _broadcast competition are stuck in limbo, waiting on a signal that will never come, and unable to read that the stop flag has been set.
I think there are 2 options to work-around/fix this:
Use pthread_cond_timedwait. Even without being signaled, this will return from waiting at the specified time interval, see that stop == 1, and then exit.
Add pthread_cond_signal or pthread_cond_broadcast at the end of your worker function. This way, right before a thread exits, it will signal the cond variable allowing any other waiting threads to grab the mutex and finish processing. There is no harm in signaling a conditional variable if no threads are waiting on it, so this should be fine even for the last thread.
EDIT: Here is an MCVE that proves (as far as I can tell) that my answer above is wrong, heh. As soon as I press Ctrl+c, the program exits "immediately", which says to me all the threads are quickly acquiring the mutex after the broadcast, seeing that stop is false, and exiting. Then main joins on the threads and it's process over.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#define NUM_THREADS 3
#define STACK_SIZE 10
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
volatile bool stop = false;
int stack[STACK_SIZE] = { 0 };
int sp = 0; // stack pointer,, also doubles as the current stack size
void SigHandler(int sig)
{
if (sig == SIGINT)
{
stop = true;
}
else
{
printf("Received unexcepted signal %d\n", sig);
}
}
void* worker(void* param)
{
long tid = (long)(param);
while (stop == false)
{
// acquire the lock
pthread_mutex_lock(&m);
while (sp <= 0) // sp should never be < 0
{
// there is no data in the stack to consume, wait to get signaled
// this unlocks the mutex when it is called, and locks the
// mutex before it returns
pthread_cond_wait(&c, &m);
}
// when we get here we should be guaranteed sp >= 1
printf("thread %ld consuming stack[%d] = %d\n", tid, sp-1, stack[sp-1]);
sp--;
pthread_mutex_unlock(&m);
int sleepVal = rand() % 10;
printf("thread %ld sleeping for %d seconds...\n", tid, sleepVal);
sleep(sleepVal);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
srand(time(NULL));
for (long i=0; i<NUM_THREADS; i++)
{
int rc = pthread_create(&threads[i], &attr, worker, (void*)i);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %ld\n", i);
}
}
while (stop == false)
{
// produce data in bursts
int numValsToInsert = rand() % (STACK_SIZE - sp);
printf("main producing %d values\n", numValsToInsert);
// acquire the lock
pthread_mutex_lock(&m);
for (int i=0; i<numValsToInsert; i++)
{
// produce values for the stack
int val = rand() % 10000;
// I think this should already be guaranteed..?
if (sp+1 < STACK_SIZE)
{
printf("main pushing stack[%d] = %d\n", sp, val);
stack[sp++] = val;
// signal the workers that data is ready
//printf("main signaling threads...\n");
//pthread_cond_signal(&c);
}
else
{
printf("stack full!\n");
}
}
pthread_mutex_unlock(&m);
// signal the workers that data is ready
printf("main signaling threads...\n");
pthread_cond_broadcast(&c);
int sleepVal = 1;//rand() % 5;
printf("main sleeping for %d seconds...\n", sleepVal);
sleep(sleepVal);
}
for (long i=0; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}

Thread synchronisation using semaphore for c

I am writing a c program to create three threads(1,2,3) such that at any given point of time only one thread must execute and print the output on console in the order 123123123123.........
I am making use of semaphore for synchronization.
I am having an issue with the code i have written. the code doesn't print it in the order 123123... the order is random and stops after a while.
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>
#include<stdlib.h>
sem_t sem_1;
void *func1(void *arg){
int err1=0;
while(1){
err1=sem_wait(&sem_1);
assert(err1==0);
printf("thread 1\n");
}
//return NULL;
}
void *func2(void *arg){
int err2=0;
while(1){
err2=sem_wait(&sem_1);
assert(err2==0);
printf("thread 2\n");
}
// return NULL;
}
void *func3(void *arg){
int err3=0;
while(1){
err3=sem_wait(&sem_1);
assert(err3==0);
printf("thread 3\n");
}
// return NULL;
}
int main(){
pthread_t *t1,*t2,*t3;
int i=0,rc=0,c1=0,c2=0,c3=0;
t1=(pthread_t *)malloc(sizeof(*t1));
t2=(pthread_t *)malloc(sizeof(*t2));
t3=(pthread_t *)malloc(sizeof(*t3));
i=sem_init(&sem_1,0,1);
assert(i==0);
c1=pthread_create(t1,NULL,func1,NULL);
assert(c1==0);
c2=pthread_create(t2,NULL,func2,NULL);
assert(c2==0);
c3=pthread_create(t3,NULL,func3,NULL);
assert(c3==0);
while(1){
rc=sem_post(&sem_1);
assert(rc==0);
sleep(1);
}
return 0;
}
Why would you even expect them in in an order?
Your threads do things inbetween the different waits, and according to the system scheduler, these can take different amount of time.
printf is a buffered operation that gives you exclusive access to a shared resource. So in addition to your semaphore there is a hidden lock somewhere, that also regulates the progress of your threads. Don't expect the prints to appear in order, even if the calls themselves are.
Then, for the end, using assert here is really a very bad idea. All sem_t operations can (and will) fail spuriously, so it is really bad to abort, just because such a failure.
In fact, sem_t is really a low level tool, and you should never use it without checking return values and without having a fall back strategy if such a call fails.
Of course. I can't see any order related synchronization mechanism.
One of the options to achieve the strict order is to have one semaphore per thread:
sem_t sem[3];
// ...
while(1) {
for(n = 0; n < 3; n++) {
rc=sem_post(&sem[n]);
assert(rc==0);
}
sleep(1);
}
Below Code will help to solve the problem, one semaphore for each thread used to achieve synchronization. The initial value of the semaphore does the job. used usleep to launch thread in sequence manner for needed output. The same can be done by using Mutex lock and cond variables
//declaring semaphore
sem_t sema1;
sem_t sema2;
sem_t sema3;
void* t1(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema1);
printf("Thread 1 \n");
sem_post(&sema2);
}
printf("T1 return\n");
return NULL;
}
void* t2(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema2);
printf("Thread 2 \n");
sem_post(&sema3);
}
printf("T2 return\n");
return NULL;
}
void* t3(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema3);
printf("Thread 3 \n");
sem_post(&sema1);
}
printf("T3 return \n");
return NULL;
}
int main()
{
pthread_t tid1, tid2,tid3;
sem_init(&sema1,0,1);
sem_init(&sema2,0,0);
sem_init(&sema3,0,0);
pthread_create(&tid1, NULL, t1, NULL);
usleep(100);
pthread_create(&tid2, NULL, t2, NULL);
usleep(100);
pthread_create(&tid3, NULL, t3, NULL);
pthread_join(tid3, NULL);
pthread_join(tid2, NULL);
pthread_join(tid1, NULL);
sem_destroy(&sema1);
sem_destroy(&sema2);
sem_destroy(&sema3);
return 0;
}

Creating a new thread each time a method is called using pthread

I want to create a program that creates a new thread each time a specific method is called. Here is my working code so far:
#define NUMBER_OF_THREADS 3
pthread_t threads[NUMBER_OF_THREADS];
pthread_attr_t attr;
void *BusyWork(void *t)
{
int i;
long tid;
tid = (long)t;
printf("Thread %ld running...\n",tid);
// ...
printf("Thread %ld completed...\n",tid);
pthread_exit((void*) t);
}
void createNewThread(int number){
printf("running createNewThread(%d)\n", number);
pthread_t tid;
int rc = pthread_create( &tid, &attr, BusyWork, (void *) (long)number);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
int main(int argc, char *argv[]) {
int i, rc;
//Set up thread attributes
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//Arbitary amount of calls (My real program will call the createNewThread() funcion multiple unkown amount of times)
createNewThread(15);
createNewThread(27);
createNewThread(62);
createNewThread(500);
createNewThread(8864);
createNewThread(99999);
//Free attributes
pthread_attr_destroy(&attr);
//Wait for other threads still running
// HOW CAN I DO THIS????
/*for (i=0; i< NUMBER_OF_THREADS; i++){
rc = pthread_join( ??? , NULL); //TODO
if (rc){
printf("ERROR: return code from pthread_join() %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %d\n", i);
}*/
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL); // (?) Is this part nessassary as we are on the main thread and soon to exit the program
return 0;
}
However as you can see in my code there is a few issues! For example, how can I wait for all processes to complete for the code I am using, as I am not keeping track of the thread number. Also when a thread "BusyWork" is done it does not clean up after it self and left as an orphan process.
One idea I had was to use a vector to keep track of each thread number and then use that for the final join at the end of main. However the problem with that is the array list can easily get very large and will never shrink even though a thread is complete.
Detach the threads, don't join them. Before you create a thread, increment a counter protected by a mutex. Right before a thread terminates, acquire the mutex and decrement the counter. Now you know all threads are done when the counter reads zero. You can use a condition variable to make the counter waitable if you like.

Why does pthread_cond_signal not work?

I am currently learing all around POSIX threads (pthread).
I now have created a simple program which increased a shared value by 7 until above 10000 then it should signal a condition to the next thread which decreases it by 3 until under 1000. At last it should divide the result through 2 and main should output the result.
My code:
pthread_t threads[3];
pthread_cond_t cond_a, cond_b;
pthread_mutex_t mutex;
int counter;
void * worker_one();
void * worker_two();
void * worker_three();
int main(int argv, const char ** argc) {
counter = 0;
pthread_cond_init(&cond_a, NULL);
pthread_cond_init(&cond_b, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, worker_one, NULL);
pthread_create(&threads[1], NULL, worker_two, NULL);
pthread_create(&threads[2], NULL, worker_three, NULL);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_join(threads[2], NULL);
printf("Value started at %d and ends with %d.\n", 0, counter);
return 0;
}
void * worker_one() {
printf("Worker one started.\n");
pthread_mutex_lock(&mutex);
printf("Worker one starting work.\n");
while (counter < 10000) {
counter += 7;
}
pthread_cond_signal(&cond_a);
printf("Worker one finished work with: %d.\n", counter);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void * worker_two() {
printf("Worker two started.\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond_a, &mutex);
printf("Worker two starting work.\n");
while (counter > 1000)
counter -= 3;
printf("Worker two finished work with: %d.\n", counter);
pthread_cond_signal(&cond_b);
pthread_mutex_unlock(&mutex);
sleep(1);
pthread_exit(NULL);
}
void * worker_three() {
printf("Worker three started.\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond_b, &mutex);
printf("Worker three starting work.\n");
counter /= 2;
printf("Worker three finished work with: %d.\n", counter);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
For some reason the whole execution hangs around the first thread. The signal is also fired but thread two does not react.
Can somebody tell me what I am doing wrong?
I have answered a similar question here: pthread condition variables on Linux, odd behaviour.
The problem is that you wait before even testing the condition you want to wait for is true.
What happens is that thread 1 signals before thread 2 is waiting, therefore the signal is lost and thread 2 will be waiting forever.
In order to avoid this, first test what you want to wait for, then wait only if it's not here.
EDIT: Ok, here is a possible solution with only one mutex and one condtion (untested)
Thread 1:
pthread_mutex_lock(&mutex);
while(thread_1_should_work == false){ // wait until the condition is satisfied
pthread_cond_wait(&cond, &mutex);
}
//at this point, we owe the mutex and we know thread_1_should_work is true;
// do work
thread_1_shoudl_work = false;
thread_2_should_work = true;
pthread_cond_broadcast(&cond); //wake up any waiting thread (if it's not their turn, they'll call wait again)
pthread_mutex_unlock(&mutex);
... and so on.

How to use mutexes in C

I am confused about use of multiple mutexes in C.
int main() {
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
pthread_mutex_lock(&mutex1);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_mutex_lock(&mutex2);
printf("Parent 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
pthread_join( thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
void *print_message_function( void *str ) {
pthread_mutex_lock(&mutex1);
char *message;
message = (char *) str;
printf("Child 1 received message: %s \n", message);
pthread_mutex_lock(&mutex2);
printf("child 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
output is
Parent 1
Parent 2
Child 1 received message: Thread 1
child 2
Thread 1 returns: 0
what i want is
Parent 1
Child 1 received message: Thread 1
Parent 2
child 2
Thread 1 returns: 0
When you call pthread_create you have already locked mutex1. That means that every other thread that calls pthread_mutex_lock(&mutex1); will wait for the mutex to be unlocked. That is what happen when you create a second thread: mutex1 is already locked, so the second thread cannot enter the critical section but need to wait for the mutex to be unlocked. That happens at the end of the main function.
You'll need to reorganize your code to get the output you desire.
However, to obtain such a result you should check synchronization systems, such semaphores or condition variables; they will provide a clearer and easier way to synchronize threads.
You may also check this tutorial: POSIX Threads Programming
A simple solution using semaphores (not tested, but it should work):
#include <stdio.h>
#include <semaphore.h>
sem_t sem1, sem2;
void* f(void* str) {
sem_wait(&sem1);
printf("Child 1 received message: %s \n",(char*)str);
sem_post(&sem2);
sem_wait(&sem1);
printf("Child 2\n");
return NULL;
}
int main (int argc, const char * argv[]) {
pthread_t thread;
char* message = "Thread 1";
int r;
sem_init(&sem1,0,0);
sem_init(&sem2,0,0);
r = pthread_create(&thread, NULL, f, (void*)message);
sem_post(&sem1);
sem_wait(&sem2);
printf("Parent 2\n");
sem_post(&sem1);
pthread_join(thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
Mutexes alone aren't suitable for performing the kind of closely-interlocked execution that you want - their normal use is for protecting access to a shared data structure. This is because they're designed for saying "Thing A shouldn't happen at the same time as Thing B", but they don't say anything about whether Thing A or Thing B happens first or second.
You could use mutexes and condition variables, but in this case your problem is most closely matched by a pthreads Barrier object:
#include <stdio.h>
#include <pthread.h>
pthread_barrier_t barrier;
void *print_message_function( void *str )
{
char *message;
message = (char *) str;
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (wait until parent prints first message) */
printf("Child 1 received message: %s \n", message);
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (allow parent to proceed and print second message) */
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (wait for parent to print second message) */
printf("child 2\n");
return NULL;
}
int main()
{
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_barrier_init(&barrier, NULL, 2);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (allow child to proceed and print first message) */
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (wait for child to print first message) */
printf("Parent 2\n");
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (allow child to proceed and print second message) */
pthread_join( thread1, NULL);
/* (wait for child to exit) */
printf("Thread 1 returns: %d\n",r);
return 0;
}
Note that it is not usual to try to tightly interlock the execution of threads in this way - really, you've gone to great pains to ensure that the threads don't execute in parallel at all, which is the whole point of threads in the first place. If you find yourself doing this in a real project, it's a sign that you ought to carefully re-think your design.
I think you need to unlock mutex1 sooner. You unlock it after the printf("Parent 2\n"); so thread1 is still locked waiting for pthread_mutex_lock(&mutex1);.
When thread1 starts it's first step is to lock while it waits for mutual exclusion (clue's in the name) lock on mutex1. So it's paused.
Then you :
printf("Parent 1\n");
pthread_mutex_lock(&mutex2); <-- lock 2 is unleased but thread one is waiting on mutex1
printf("Parent 2\n");

Resources