/***************************************************************************** * SOURCE: This is a translation of a Pthread program from the Lawrence Livermore * Computing Center POSIX Threads Programming Exercise at: * https://computing.llnl.gov/tutorials/pthreads/exercise.html * SUPERSOURCE: Adapted from example code in "Pthreads Programming", B. Nichols * et al. O'Reilly and Associates. * FILE: bug1.cvl * DESCRIPTION: * This example has a bug. It is a variation on the condvar.cvl example. * Instead of just one thread waiting for the condition signal, there are * four threads waiting for the same signal causing a deadlock. * The solution program is bug1fix.cvl * Command line execution: * civl verify -inputNUM_THREADS=6 -inputTCOUNT=10 -inputCOUNT_LIMIT=12 bug1.cvl ******************************************************************************/ #include "pthread.cvh" #include #include #include $input int NUM_THREADS; //Changed definitions to input variables $input int TCOUNT; $input int COUNT_LIMIT; int count = 0; pthread_mutex_t count_mutex; pthread_cond_t count_threshold_cv; void *inc_count(void *idp) { int j,i; double result=0.0; long my_id = (long)*idp; // Changed to dereference for (i=0; i < TCOUNT; i++) { pthread_mutex_lock(&count_mutex); count++; /* Check the value of count and signal waiting thread when condition is reached. Note that this occurs while mutex is locked. */ if (count == COUNT_LIMIT) { pthread_cond_signal(&count_threshold_cv); printf("inc_count(): thread %d, count = %d Threshold reached.\n", my_id, count); //removed l from %ld } printf("inc_count(): thread %d, count = %d, unlocking mutex\n", my_id, count); //removed l from %ld pthread_mutex_unlock(&count_mutex); /* Do some work so threads can alternate on mutex lock */ //sleep(1); removed sleep, unnecessary } pthread_exit(NULL, false, NULL, 0); } void *watch_count(void *idp) { long my_id = (long)*idp; printf("Starting watch_count(): thread %d\n", my_id); /* Lock mutex and wait for signal. Note that the pthread_cond_wait routine will automatically and atomically unlock mutex while it waits. Also, note that if COUNT_LIMIT is reached before this routine is run by the waiting thread, the loop will be skipped to prevent pthread_cond_wait from never returning. */ pthread_mutex_lock(&count_mutex); printf("***Before cond_wait: thread %d\n", my_id); pthread_cond_wait(&count_threshold_cv, &count_mutex); printf("***Thread %d Condition signal received.\n", my_id); pthread_mutex_unlock(&count_mutex); pthread_exit(NULL, false, NULL, 0); //Different parameters } int main(void) { int i, rc; pthread_t threads[6]; pthread_attr_t attr; /* Initialize mutex and condition variable objects */ pthread_mutex_init(&count_mutex, 0); pthread_cond_init (&count_threshold_cv, NULL); /* For portability, explicitly create threads in a joinable state Created variables for casting as we are unable to currently cast raw integer values as void pointers. */ int zero = 0; int one = 1; int two = 2; int three = 3; int four = 4; int five = 5; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(&threads[2], &attr, watch_count, &two); pthread_create(&threads[3], &attr, watch_count, &three); pthread_create(&threads[4], &attr, watch_count, &four); pthread_create(&threads[5], &attr, watch_count, &five); pthread_create(&threads[0], &attr, inc_count, &zero); pthread_create(&threads[1], &attr, inc_count, &one); pthread_attr_destroy(&attr); /* Wait for all threads to complete */ for (i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS); /* Clean up and exit */ pthread_mutex_destroy(&count_mutex); pthread_cond_destroy(&count_threshold_cv); pthread_exit (NULL, true, NULL, 0); //Different parameters return 0; }