title: can pthread_cond_signal make more than one thread to wake up?
body: <p>I'm studying on condition variables of Pthread. When I'm reading the explanation of <code>pthread_cond_signal</code>, I see the following.</p>
  
  <blockquote>
    <p>The <code>pthread_cond_signal()</code> function shall unblock <strong>at least one</strong> of
    the
           threads that are blocked on the specified condition variable cond (if
           any threads are blocked on <code>cond</code>).</p>
  </blockquote>
  
  <p>Till now I knew <code>pthread_cond_signal()</code> would make only one thread to wake up at a time. But, the quoted explanation says <em>at least one</em>. What does it mean? Can it make more than one thread wake up? If yes, why is there <code>pthread_cond_broadcast()</code>?</p>
  
  <hr>
  
  <p>En passant, I wish the following code taken from <a href="https://www.oreilly.com/library/view/unixtm-systems-programming/0130424110/" rel="nofollow noreferrer">UNIX Systems Programming book of Robbins</a> is also related to my question. Is there any reason the author's <code>pthread_cond_broadcast()</code> usage instead of <code>pthread_cond_signal()</code> in <em>waitbarrier</em> function? <em>As a minor point, why is <strong><code>!berror</code></strong> checking needed too as a part of the predicate?</em>  When I try both of them by changing, I cannot see any difference. </p>
  
  <pre><code>/*
  
   The program implements a thread-safe barrier by using condition variables. The limit
   variable specifies how many threads must arrive at the barrier (execute the
   waitbarrier)  before the threads are released from the barrier.
   The count variable specifies how many threads are currently waiting at the barrier.
   Both variables are declared with the static attribute to force access through
   initbarrier and waitbarrier. If successful, the initbarrier and waitbarrier
   functions return 0. If unsuccessful, these functions return a nonzero error code.
  
   */
  
  #include &lt;errno.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;stdio.h&gt;
  
  static pthread_cond_t bcond = PTHREAD_COND_INITIALIZER;
  static pthread_mutex_t bmutex = PTHREAD_MUTEX_INITIALIZER;
  static int count = 0;
  static int limit = 0;
  
  int initbarrier(int n) {              /* initialize the barrier to be size n */
      int error;
  
      if (error = pthread_mutex_lock(&amp;bmutex))        /* couldn't lock, give up */
          return error;
      if (limit != 0) {                 /* barrier can only be initialized once */
          pthread_mutex_unlock(&amp;bmutex);
          return EINVAL;
      }
      limit = n;
      return pthread_mutex_unlock(&amp;bmutex);
  }
  
  int waitbarrier(void) {    /* wait at the barrier until all n threads arrive */
      int berror = 0;
      int error;
  
      if (error = pthread_mutex_lock(&amp;bmutex))        /* couldn't lock, give up */
          return error;
      if (limit &lt;=  0) {                       /* make sure barrier initialized */
          pthread_mutex_unlock(&amp;bmutex);
          return EINVAL;
      }
      count++;
      while ((count &lt; limit) &amp;&amp; !berror)
          berror =  pthread_cond_wait(&amp;bcond, &amp;bmutex);
      if (!berror) {
          fprintf(stderr,"soner %d\n",
                  (int)pthread_self());
          berror = pthread_cond_broadcast(&amp;bcond);           /* wake up everyone */
          }
      error = pthread_mutex_unlock(&amp;bmutex);
      if (berror)
          return berror;
      return error;
  }
  
  /* ARGSUSED */
  static void *printthread(void *arg) {
      fprintf(stderr,"This is the first print of thread %d\n",
              (int)pthread_self());
      waitbarrier();
      fprintf(stderr,"This is the second print of thread %d\n",
              (int)pthread_self());
      return NULL;
  }
  
  int main(void) {
      pthread_t t0,t1,t2;
  
      if (initbarrier(3)) {
          fprintf(stderr,"Error initilizing barrier\n");
          return 1;
      }
      if (pthread_create(&amp;t0,NULL,printthread,NULL))
          fprintf(stderr,"Error creating thread 0.\n");
      if (pthread_create(&amp;t1,NULL,printthread,NULL))
          fprintf(stderr,"Error creating thread 1.\n");
      if (pthread_create(&amp;t2,NULL,printthread,NULL))
          fprintf(stderr,"Error creating thread 2.\n");
      if (pthread_join(t0,NULL))
          fprintf(stderr,"Error joining thread 0.\n");
      if (pthread_join(t1,NULL))
          fprintf(stderr,"Error joining thread 1.\n");
      if (pthread_join(t2,NULL))
          fprintf(stderr,"Error joining thread 2.\n");
      fprintf(stderr,"All threads complete.\n");
      return 0;
  }
  </code></pre>