This is a version of the conc.c example program with most of the code that prints messages stripped out. Some other "extras" were removed too -- nothing important to what the program does. You may wish to study this version before sifting through conc.c.

Latest Revision: 11/08/99
 11/08/99 -- correction to the include directives
 11/08/99 -- added casts to parameters of cthread_fork()
 11/08/99 -- fixed typo that was preventing the program from terminating.

#include <stdio.h> 
#include <mach/cthreads.h>
#include "sem.h"

extern sim_semaphore create_sim_sem() ;
extern void wait_sem() ;
extern void signal_sem() ;

int  checking ;      /* Set this to 1 if you want lots of
			"debug printf's". */
		     
mutex_t stdoutLock ;    /* When debugging, we need to use this
			   lock to get intelligible printouts
			   of what the various threads are
			   doing.  Warning:  Don't change how
			   this is done until you've thought a
			   WHOLE lot about the consequences. */

int 		count;		/* number of child threads active */ 
sim_semaphore   countSem ;      /* For synchronization. */
sim_semaphore finished ; 	/* To provide a condition for the 
				   mother to wait on. */

extern long random(void);

void init() 
{ 

  checking = 0 ;    /* JUST FOR DEBUGGING: change to
                       1 if you want messages. */
  		       
  stdoutLock = mutex_alloc() ;

  count = 0;        /* counter:  current number
                       of children. */ 
  countSem = create_sim_sem(1) ;  /* initialize the semaphore
                                     for access to counter */
  finished = create_sim_sem(0) ;  /* initialize "finished" to 0 
				     to force a block if no signal
				     has been done first. */
  srandom(time((int *) 0));       /* initialize random
                                     number generator */ 
}

/*
 * Each child just counts up to its argument, yielding the 
 * processor on each iteration.  When it's finished, it 
 * decrements the global count and signals that it's done.
 */ 
void child(int n) 
   {
	int i, temp ;

	for (i = 0; i < n; i += 1) 
	{
		cthread_yield(); 
        }

	mutex_lock (stdoutLock) ;
        printf("Child %d has finished his work ", cthread_self());
        printf("of %d cycles.\n", n);
	fflush(stdout) ;
	mutex_unlock(stdoutLock) ;
	
 	/*
	 * If any thread wants to access the count variable, it
         * first waits on countSem to insure exclusive access.
	 */ 

	wait_sem(countSem); 

	count -= 1 ;			

	/* signal mother to exit if last thread is done */ 
	if (count == 0) 
	   {
	      signal_sem(finished);	
           }
 	signal_sem(countSem); 

	mutex_lock (stdoutLock) ;
	printf("Child %d EXITS.\n", cthread_self());
        fflush(stdout) ;
	mutex_unlock(stdoutLock) ;

	cthread_exit(0); 
}

/*
 * The mother spawns a given number of children and then waits 
 * for them all to finish.  
 */ 
void mother(int nchildren) 
{ 
  int i, cnt_cpy;

  mutex_lock (stdoutLock) ;  
  printf("Mother will spawn %d children.\n", nchildren); 
  fflush(stdout) ;
  mutex_unlock(stdoutLock) ;
  
  for (i = 1; i <= nchildren; i += 1) 
  {
    wait_sem(countSem); 

		/* Increment count with the creation of each child
 			   thread.  */ 
    count += 1;

		/* Fork a child and detach it, since the mother never
 		   joins it individually.  */ 

    cthread_detach(cthread_fork(   (cthread_fn_t) child, 
                                   (any_t)        (random() % 1000))); 

    signal_sem(countSem); 
  } 
	/*
	 * Mother thread loops waiting on the semaphore "finished".  
	 * When a child signals on "finished", the mother thread  
 	 * tests the count for a value of zero.  
	 */ 
  do   
  {

    wait_sem(countSem) ;

    cnt_cpy = count ;

    signal_sem(countSem) ;

    if (cnt_cpy != 0)
    {

      wait_sem(finished) ;

    }
  }
  while (cnt_cpy != 0) ;
  mutex_lock (stdoutLock) ;
  printf("All %d children have finished.\n", nchildren); 
  printf("Mother %d now EXITS.\n", cthread_self() ); 
  fflush(stdout) ;	  	
  mutex_unlock(stdoutLock) ; 
  cthread_exit(0); 
}

main() 
{ 
  init(); 
    
      /* create mother thread and up to 15 children */ 
  mother((int) random() % 16);	
}