Problem in communication of three threads in C language (deadlock occurs) - c

I am creating a program in which i have 3 linked lists and I am trying to update or remove the nodes from these linked lists in these three threads. But the deadlock is occurring
The insertion and deletion is working fine. Here the three variables var1InUse,var2InUse and var3InUse are indicating that whether the 3 linked lists are in use or not(Not all three are use in the all threads). I am putting the threads on waiting based on var1InUse,var2InUse and var3InUse as you can see in the code. Sometimes this works fine but sometimes deadlock happens. I have searched for the solution on the internet but could find it.
Am I using the wait and signal methods correctly?
pthread variables declaration
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t t1cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t t2cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t t3cond = PTHREAD_COND_INITIALIZER;
int var1InUse=0,var2InUse=0,var3InUse=0;
THREAD 1
void* thread1(void* args){
while(var1InUse || var2InUse ) {
pthread_cond_wait(&t1cond,&myMutex);}
var1InUse=1,var2InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code about adding and removing from
linkedlist
*/
var1InUse=0,var2InUse=0;
pthread_cond_signal(&t2cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);}
}
THREAD 2
void* thread2(void* args){
while(var1InUse || var2InUse || var3InUse) {
pthread_cond_wait(&t2cond,&myMutex);}
var1InUse=1,var2InUse=1,var3InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code adding and removing from linkedlist
*/
var1InUse=0,var2InUse=0,var3InUse=0;
pthread_cond_signal(&t1cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);}
}
THREAD 3
void* thread3(void* args){
while(var1InUse || var3InUse ) {
pthread_cond_wait(&t3cond,&myMutex);}
var1InUse=1,var3InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code adding and removing from linkedlist
*/
var1InUse=0,var3InUse=0;
pthread_cond_signal(&t1cond);
pthread_cond_signal(&t2cond);
pthread_mutex_unlock(&myMutex);}
}
MAIN METHOD
int main(){
pthread_t t1,t2,t3,t4;
pthread_mutex_init(&myMutex,0);
pthread_create(&t1,NULL,thread1,NULL);
pthread_create(&t2,NULL,thread2,NULL);
pthread_create(&t3,NULL,thread3,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_join(t3,NULL);
pthread_mutex_destroy(&myMutex);
return 0
}
I want the deadlock to be removed.

The mutex used by pthread_cond_wait() needs to locked before the function is called. Here is an extract from the man page:
The pthread_cond_timedwait() and pthread_cond_wait() functions shall block on a condition variable. The application shall ensure that these functions are called with mutex locked by the calling thread; otherwise, an error (for PTHREAD_MUTEX_ERRORCHECK and robust mutexes) or undefined behavior (for other mutexes) results.
Although pthread_cond_wait() unlocks the mutex internally, it is locked again before the function returns successfully:
Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.
Additionally, you should access the shared variables var1InUse, var2InUse and var3InUse with the mutex locked.
Here is a modified version of your thread1() that follows these rules. The modifications to the other thread start routines should be similar:
void* thread1(void* args){
pthread_mutex_lock(&myMutex);
while(var1InUse || var2InUse ) {
pthread_cond_wait(&t1cond,&myMutex);
}
var1InUse=1,var2InUse=1;
pthread_mutex_unlock(&myMutex);
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code about adding and removing from linkedlist
*/
var1InUse=0,var2InUse=0;
pthread_cond_signal(&t2cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);
}
return NULL;
}
(I'm not entirely sure that the above is correct, because it's not entirely clear from the original code what the while(1) loop is supposed to do.)

Related

How to safely modify string from another thread in C with pthreads?

I am trying to create a simple CLI music player in C. I have created a second thread aside from the main thread which is responsible for playing the music. The second thread receives an argument like so (I have tried with and without the volatile keyword):
typedef struct AUDIO_S
{
volatile char audio_path[MAX_PATH];
volatile int play_state;
} audio_t;
The main thread may update both the audio path (current file) and the play state (playing/paused). The job of the second thread is to detect this change and act accordingly by changing, playing, or pausing the song.
I have an issue where what (I assume) is happening is that the second thread reads this data at the same time as it is being written to by the main thread, which is producing garbled output. I tried implementing a conditional variable but I'm still getting bad output.
Here is the code where I write the data:
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;
pthread_mutex_lock(&mutex);
strcpy(audio->audio_path, state->cur_play_dir);
strcat(audio->audio_path, "/");
strcat(audio->audio_path, state->cur_play_file);
audio->play_state = MUSIC_PLAY;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
And here is the code where I read it:
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;
while (1)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
char *new_audio_path = audio->audio_path;
if (strcmp(new_audio_path, cur_audio_path))
{
cur_audio_path = realloc(cur_audio_path,
strlen(new_audio_path) + 1);
strcpy(cur_audio_path, audio->audio_path);
printw("PATH: %s\n", cur_audio_path);
}
pthread_mutex_unlock(&mutex);
}
The mutex and the condition are declared as global variables like so:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
I'm fairly new to parallel programming so I suspect I'm doing something glaringly obvious and stupid.
After sleeping on the issue I realised my mistake. As it turns out there was actually no issue at all with the data stored in the path string.
In the second thread I was printing the value of the path to stdout purely to check that the value was valid (so I forgot to lock anything). However, in the main thread, I was also printing other data to stdout.
With two threads both writing to stdout the data appeared garbled when printed when in reality there was no issue with the data stored in memory. I verified this by instead writing to a text file in the second thread while the first thread wrote to stdout. The data written to the text file had no issues.

unexpected behavior when using conditional variables (c, gcc)

I am trying to learn how to use conditional variables properly in C.
As an exercise for myself I am trying to make a small program with 2 threads that print "Ping" followed by "Pong" in an endless loop.
I have written a small program:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
sleep(0.5);
printf("ping\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
pthread_cond_wait(&cond,&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_cond_wait(&cond,&lock);
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pong\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
while(1){
sleep(1);
i++;
}
return EXIT_SUCCESS;
}
And when running this program the output I get is:
main
thread 1 started
thread 2 started
ping
Any idea what is the reason the program does not execute as expected?
Thanks in advance.
sleep takes an integer, not a floating point. Not sure what sleep(0) does on your system, but it might be one of your problems.
You need to hold the mutex while calling pthread_cond_wait.
Naked condition variables (that is condition variables that don't indicate that there is a condition to read somewhere else) are almost always wrong. A condition variable indicates that something we are waiting for might be ready to be consumed, they are not for signalling (not because it's illegal, but because it's pretty hard to get them right for pure signalling). So in general a condition will look like this:
/* consumer here */
pthread_mutex_lock(&something_mutex);
while (something == 0) {
pthread_cond_wait(&something_cond, &something_mutex);
}
consume(something);
pthread_mutex_unlock(&something_mutex);
/* ... */
/* producer here. */
pthread_mutex_lock(&something_mutex);
something = 4711;
pthread_cond_signal(&something_cond, &something_mutex);
pthread_mutex_unlock(&something_mutex);
It's a bad idea to sleep while holding locks.
T1 and T2 are not valid functions to use as functions to pthread_create they are supposed to take arguments. Do it right.
You are racing yourself in each thread between cond_signal and cond_wait, so it's not implausible that each thread might just signal itself all the time. (correctly holding the mutex in the calls to pthread_cond_wait may help here, or it may not, that's why I said that getting naked condition variables right is hard, because it is).
First of all you should never use sleep() to synchronize threads (use nanosleep() if you need to reduce output speed). You may need (it's a common use) a shared variable ready to let each thread know that he can print the message. Before you make a pthread_cond_wait() you must acquire the lock because the pthread_cond_wait() function shall block on a condition variable. It shall be called with mutex locked by the calling thread or undefined behavior results.
Steps are:
Acquire the lock
Use wait in a while with a shared variable in guard[*]
Do stuffs
Change the value of shared variable for synchronize (if you've one) and signal/broadcast that you finished to work
Release the lock
Steps 4 and 5 can be reversed.
[*]You use pthread_cond_wait() to release the mutex and block the thread on the condition variable and 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 because spurious wakeups may occur. watch more here
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 1){
pthread_cond_wait(&cond,&lock);
}
printf("ping\n");
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 0){
pthread_cond_wait(&cond,&lock);
}
printf("pong\n");
ready = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return EXIT_SUCCESS;
}
You should also use pthread_join() in main instead of a while(1)

Using different mutex locks in threads

I have written the following program to implement two threads in POSIX. There is a global shared variable sum, which is being accessed by two different threads simultaneously. I have used mutex lock and unlock inside each thread while accessing the shared variable. I have a question. Here I have used the samed mutex lock (pthread_mutex_lock(&mutex))inside the two threads. What will Happen if I use two different mutex lock and unlock inside the threads (such as pthread_mutex_lock(&mutex)) in thread1 and pthread_mutex_lock(&mutex1) in thread2. I have commented out the line of confusion in the code.
My sample code fragment:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex1=PTHREAD_MUTEX_INITIALIZER;
int sum=0;
void * threadFunc1(void * arg)
{
int i;
for(i=1;i<100;i++)
{
printf("%s\n",(char*)arg);
pthread_mutex_lock(&mutex)
sum++;
pthread_mutex_unlock(&mutex)
sleep(1);
}
}
void * threadFunc2(void * arg)
{
int i;
for(i=1;i<100;i++)
{
printf("%s\n",(char*)arg);
pthread_mutex_lock(&mutex) //what will happen if I use mutex1 here
sum--;
pthread_mutex_lock(&mutex) //what will happen if I use mutex1 here
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_t thread2;
char * message1 = "i am thread 1";
char * message2 = "i am thread 2";
pthread_create(&thread1,NULL,threadFunc1,(void*)message1 );
pthread_create(&thread2,NULL,threadFunc2,(void*)message2 );
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
What is the basic difference between using the same mutex locks and different mutex lock in accessing a shared variable?
The purpose of the mutex is to prevent one thread from accessing the shared variable while another thread is, or might be, modifying it. The semantics of a mutex are that two threads cannot lock the same mutex at the same time. If you use two different mutexes, you don't prevent one thread from accessing the shared variable while another thread is modifying it, since threads can hold different mutexes at the same time. So the code will no longer be guaranteed to work.

My Posix Thread wakes up without a signal

I'm trying to implement a blocking queue using POSIX threads. Important code segments are shown below. I tried to run this program. The thread trying to remove an element from the queue goes to sleep when there are no elements in the queue and wakes up again without any signal from the thread that adds an element into the queue (This I conclude because I did not start any thread that adds an element into the queue). The thread woke up again goes to sleep and this process repeats. What am I doing wrong? Please some one tell me what I am missing here?
struct rqueue
{
int qsize;
int capacity;
pthread_mutex_t lock;
pthread_cond_t not_empty;
pthread_cond_t not_full;
};
remove_element_method:
pthread_mutex_lock(&rq->lock);
while(rq->qsize == 0){
perror("Q size is zero going to sleep");
pthread_cond_wait(&rq->not_empty);
perror("woke up");
}
// some code
pthread_cond_signal(&rq->not_full);
pthread_mutex_unlock(&rq->lock);
add_element_method:
pthread_mutex_lock(&rq->lock);
if(rq->capacity != -1 ){
while(rq->qsize == rq->capacity){
pthread_cond_wait(&rq->not_full);
}
}
//some code
pthread_cond_signal(&rq->not_empty);
pthread_mutex_unlock(&rq->lock);
pthread_cond_wait() takes two arguments -- the second is the mutex you're holding. You're only passing it one argument.
Also, did you initialize the mutex and condition variables using pthread_mutex_init() and pthread_cond_init()?

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