Hi all

I was trying to understand pthread cond and signal api functionality. So from online tutorials, I found that when a thread is want to wait for any condition to satisfy, it will go into wait mode and if some other thread fulfill that condition, it will send signal.
Below is the test code. I try to debug but it was fluctuating between functions. I have below understanding and also some doubts which I want you guys help to understand.

Doubt 1:

When a thread T1 calls pthread_cond_wait(&count_threshold_cv, &count_mutex); , it means that mutex which was locked by T1 thread will be released . The release mutex is used by T2 thread and it accuire locks and once done, send signal to T1 thread and T2release the mutex.
T1 then wake up and it again accuire lock ( this is automatically done ) and process further and then release the mutex. So the steps which happen are as below in sequence:

a) T1 accuqire lock
b) T1 check condition and go to wait mode
c) T1 release the mutex
d) T2 accuqire mutex lock
e) T2 perform action
f) T2 send signal to T1
g) T1 wake up but wait for Mutex
h) T2 complete the work and release Mutex
i) T1 get the lock and proceed further.


Is the above sequence correct?


Doubt 2:

Is count_threshold_cv variable is also released when Thread T1 goes to wait condition? I beleive it is released and I have used that in in_test() function. Am I correct?

Doubt 3:

I have read on net, that always prefer while loop rather than if condition? What's the basic behind this?

doubt 4:

When we do cond_signal_broadcast(), is there any sequence the thread will wake up. I read somewhere that thread which wait first, will wake up first. I have tested that too in my code and that was true.
Is this correct?



Code:
 #include <stdio.h>
 #include <stdlib.h>
 #include <pthread.h>

 #define NUM_THREADS  4
 #define TCOUNT 10
 #define COUNT_LIMIT 12
 int     count = 0;
 pthread_mutex_t count_mutex;
 pthread_cond_t count_threshold_cv;


 void *in_test(void *t)
 {
    long my_id = (long)t;

    pthread_mutex_lock(&count_mutex);


    while ( count < COUNT_LIMIT )
    {

       printf("\n Will Wait for signal %d\n",  my_id );
       pthread_cond_wait(&count_threshold_cv, &count_mutex);

       printf("\n Recieved Signal in Test\n");


    }

      pthread_mutex_unlock(&count_mutex);
      printf ( "\n Test Successful for Thread %d\n",my_id );

      pthread_exit(NULL);


 }

 void *inc_count(void *t)
 {
   int i;
   long my_id = (long)t;
   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) {
           printf("inc_count(): thread %ld, count = %d  Threshold reached. ",
                  my_id, count);
           //pthread_cond_signal(&count_threshold_cv);

           pthread_cond_broadcast(&count_threshold_cv);

           printf("Just sent signal.\n");
      }

       printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
                      my_id, count);

      pthread_mutex_unlock(&count_mutex);
      sleep(1);
     }
        pthread_exit(NULL);
 }

    void *watch_count(void *t)
    {
      long my_id = (long)t;
      printf("Starting watch_count(): thread %ld\n", my_id);
   
      pthread_mutex_lock(&count_mutex);


      while (count < COUNT_LIMIT) {
       printf("watch_count(): thread %ld Count= %d. Going into wait...\n", my_id,count);
       pthread_cond_wait(&count_threshold_cv, &count_mutex);
       printf("watch_count(): thread %ld Condition signal received. Count= %d\n", my_id,count);
       printf("watch_count(): thread %ld Updating the value of count...\n", my_id,count);
       count += 125;
       printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
     }
       printf("watch_count(): thread %ld Unlocking mutex.\n", my_id);
       pthread_mutex_unlock(&count_mutex);
       pthread_exit(NULL);
     }






 int main(int argc, char *argv[])
 {
   int i, rc;
   long t1=1, t2=2, t3=3,t4=4;
   pthread_t threads[4];
   pthread_attr_t attr;

   /* Initialize mutex and condition variable objects */
     pthread_mutex_init(&count_mutex, NULL);
     pthread_cond_init (&count_threshold_cv, NULL);

   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    rc =  pthread_create(&threads[0], &attr, watch_count, (void *)t1);
    if ( rc != 0 )
        printf("\n Error In Thread Creation");

    rc = pthread_create(&threads[1], &attr, inc_count, (void *)t2);

    if ( rc != 0 )
        printf("\n Error In Thread Creation");


   rc = pthread_create(&threads[2], &attr, inc_count, (void *)t3);

   if ( rc != 0 )
       printf("\n Error In Thread Creation");

   rc = pthread_create(&threads[3], &attr, in_test, (void *)t4);

   if ( rc != 0 )
       printf("\n Error In Thread Creation");

     for (i = 0; i < NUM_THREADS; i++) {
       pthread_join(threads[i], NULL);
     }

     /* Clean up and exit */
     pthread_attr_destroy(&attr);
     pthread_mutex_destroy(&count_mutex);
     pthread_cond_destroy(&count_threshold_cv);
     pthread_exit (NULL);

  }