title: [Thread sync]Make a print thread wait for n threads to finish a single cycle of execution, then signal the n threads to complete another cycle, repeat
body: <p>How can I have a single thread wait for n threads to complete a single execution cycle, then repeat this for i cycles. The solution needs to use semaphores to signal the single thread that all n threads have completed an execution cycle. The single thread should then signal ALL n threads that they can carry on with one more execution, ...repeat.</p>
  <p>Some challenges I can't fix:</p>
  <ul>
  <li>Controlling the semaphores so that one of the n threads doesn't eat up more than one cycle (semaphore post/wait).</li>
  <li>The n number of workers is only known at run time, so we can't initialize a sem_t array[n].</li>
  </ul>
  <p>:</p>
  <pre><code>//these would have been read in at run time
  int n = 4;
  int control = 4;
  
  void *worker(void* args){
      int num = (int)args;
      printf(&quot;Worker id: %d\n&quot;, num);
      int proceed = 5; // simulates &quot;5&quot; jobs in this workers queue
      while(proceed &gt; 0){
          sem_wait(&amp;execute);
          printf(&quot;Report from: %d\n&quot;, num);
          sem_post(&amp;reports);
          proceed--;
      }
      control--;
  } 
  
  void *print(){
      while(control &gt; 0){
          for(int i = 0; i &lt; n; i++) {
              sem_wait(&amp;reports);
          }
          printf(&quot;All reported\n&quot;);
          for(int i = 0; i &lt; n; i++) {
              sem_post(&amp;execute);
          }
      }
  }
  
  void main(){
      // control/n would have been scanned and passed to threads, the global control var 
      would be set after reading in n
      sem_init(&amp;execute,0,n);    //initialization of the first semaphore
      sem_init(&amp;reports,0,0);    //initialization of the second semaphore
  
      pthread_t printer;
      pthread_create(&amp;printer,NULL, &amp;print,NULL);
  
      pthread_t workers[n];
      for(int i = 0; i &lt; n; i++) {
          int* num = malloc(sizeof(int));
          num = i;
          pthread_create(&amp;(workers[i]),NULL, &amp;worker, (void*)num);
      }
      for(int i = 0; i &lt; n; i++) {
          pthread_join(workers[i],NULL);
      }
  
      pthread_join(printer,NULL);
  }
  </code></pre>
  <p>Output:</p>
  <pre><code>[rnitz]$ gcc -Wall -Werror -w -g example2.c -std=gnu99 -lpthread 
  [rnitz]$ ./a.out
  Worker id: 0
  Worker id: 3
  Report from: 3
  Report from: 3
  Worker id: 2
  Worker id: 1
  Report from: 3
  Report from: 0
  All reported
  Report from: 1
  Report from: 0
  Report from: 2
  Report from: 3
  All reported
  Report from: 0
  Report from: 1
  Report from: 3
  Report from: 2
  All reported
  Report from: 0
  Report from: 0
  Report from: 1
  Report from: 2
  All reported
  Report from: 2
  Report from: 1
  Report from: 1
  Report from: 2
  All reported
  [rnitz]$ 
  </code></pre>
  <p>Pretty obvious issue where some workers are eating up all the available &quot;cycle&quot; room in the semaphore.</p>
  <p>Note: This question is based on simulating a cpu, where n is the number of cpu threads that will work on an their own independent job queue; while a single print thread handles printing the current job being processed for a given cpu cycle. The print thread will:</p>
  <ol>
  <li>Wait for all cpus to finish a cycle</li>
  <li>Print the current job on each cpu</li>
  <li>Signal the n cpus to complete another cycle.</li>
  </ol>