#include <stdio.h>
#include <pthread.h>

#define MAGIC_NUM     3

void *task1( void *arg );
void *task2( void *arg );
void *task3( void *arg );
void *task4( void *arg );

int                mac_count = 0;
int                win_count = 0;
pthread_mutex_t    mac_count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t    win_count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t     mac_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t     win_cond = PTHREAD_COND_INITIALIZER;

main( int argc, char *argv[] )
{
     pthread_t     thread1;
     pthread_t     thread2;
     pthread_t     thread3;
     pthread_t     thread4;
    
     int           arg1 = 1;
     int           arg2 = 2;
     int           arg3 = 3;
     int           arg4 = 4;
     
     pthread_create( &thread1, NULL, ( void * ) task1, ( void * ) &arg1 );
     pthread_create( &thread2, NULL, ( void * ) task2, ( void * ) &arg2 );
     pthread_create( &thread3, NULL, ( void * ) task3, ( void * ) &arg3 );
     pthread_detach( thread3 );
     pthread_create( &thread4, NULL, ( void * ) task4, ( void * ) &arg4 );
     pthread_detach( thread4 );
     
     pthread_join( thread1, NULL );
     pthread_join( thread2, NULL );
     
     return;
}

void *task1( void *arg )
{
     int     i;
     
     for ( i = 0; i < 5; i++ ) {
          pthread_mutex_lock( &win_count_mutex );
          win_count++;
          printf( "Task 1:  Windows count = %d\n", win_count );
          if ( win_count == MAGIC_NUM )
               pthread_cond_signal( &win_cond );
          pthread_mutex_unlock( &win_count_mutex );
          sched_yield();
     }
     
     return;
}

void *task2( void *arg )
{
     int     i;
     
     for ( i = 0; i < 5; i++ ) {
          pthread_mutex_lock( &mac_count_mutex );
          mac_count++;
          printf( "Task 2:  Macintosh count = %d\n", mac_count );
          if ( mac_count == MAGIC_NUM )
               pthread_cond_signal( &mac_cond );
          pthread_mutex_unlock( &mac_count_mutex );
          sched_yield();
     }
     
     return;
}

void *task3( void *arg3 )
{
     pthread_mutex_lock( &mac_count_mutex );
     while ( mac_count < MAGIC_NUM ) {
          pthread_cond_wait( &mac_cond, &mac_count_mutex );
          printf( "Macs rule!\n" );
     }
     pthread_mutex_unlock( &mac_count_mutex );

     return;
}

void *task4( void *arg4 )
{
     pthread_mutex_lock( &win_count_mutex );
     while ( win_count < MAGIC_NUM ) {
          pthread_cond_wait( &win_cond, &win_count_mutex );
          printf( "Windows sucks!\n" );
     }
     pthread_mutex_unlock( &win_count_mutex );
     
     return;
}
