The race condition in your code is:
Prod sends a signal without checking whether Con is waiting for it. If Con is not yet waiting for the signal, then the signal has no effect (from the man page - "The pthread_cond_broadcast() and pthread_cond_signal() functions shall have no effect if there are no threads currently blocked on cond.").
And then you have both Con and Prod wait for each other. Hence the deadlock.
See if the following code works:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
char word1[10] = "Hello";
char word2[10] = "world";
int con_started = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // mutual exclusion lock for prod
pthread_cond_t addToQ = PTHREAD_COND_INITIALIZER;
void * prod(void *arg) {
printf("PROD: Entering prod \n");
fflush(stdout);
int i = 0;
int j = 1;
while (i < 5) {
printf("PROD adding line: %c \n", word1[i]);
fflush(stdout);
i++;
if (i % 2 == 0)
{
pthread_mutex_lock(&mutex);
while(!con_started)
{
pthread_mutex_unlock(&mutex);
sched_yield();
printf("PROD: Waiting for CON to wait.\n");
fflush(stdout);
pthread_mutex_lock(&mutex);
}
printf("PROD: Sending signal %d\n\n", j);
fflush(stdout);
pthread_cond_signal(&addToQ);
printf("PROD: Will wait now \n\n");
fflush(stdout);
pthread_cond_wait(&addToQ, &mutex);
printf("PROD received signal %d\n\n", j);
fflush(stdout);
pthread_mutex_unlock(&mutex);
j++;
}
}
sched_yield();
sleep(1);
printf("PROD: Sending signal %d\n\n", j);
fflush(stdout);
pthread_cond_signal(&addToQ);
pthread_exit(NULL);
}
void * con(void *arg)
{
int i = 0;
int j=1;
printf("CON: Entering con \n");
fflush(stdout);
pthread_mutex_lock(&mutex);
con_started = 1;
printf("CON: Will wait now\n \n");
fflush(stdout);
pthread_cond_wait(&addToQ, &mutex);
printf("CON received first signal\n\n");
fflush(stdout);
while (i < 5)
{
printf ("CON adding line: %c \n", word2[i]);
fflush(stdout);
if (i % 2 != 0)
{
//pthread_mutex_unlock(&mutex);
printf("CON: Sending signal %d\n\n", j);
fflush(stdout);
pthread_cond_signal(&addToQ);
j++;
printf("CON: Will wait now \n\n");
fflush(stdout);
pthread_cond_wait(&addToQ, &mutex);
printf("CON received signal %d\n\n", j);
fflush(stdout);
pthread_mutex_unlock(&mutex);
}
i++;
}
pthread_exit(NULL);
}
int main()
{
pthread_t threadp1; // Thread objects
pthread_t threadc1;
pthread_create(&threadp1, NULL, prod, NULL); // start first producer thread
pthread_create(&threadc1, NULL, con, NULL); // start consumer thread
pthread_join(threadp1, NULL);
printf("MAIN: threadp1 completed.\n");
fflush(stdout);
pthread_join(threadc1, NULL);
printf("MAIN: threadc1 completed.\n");
fflush(stdout);
}