/* threadsem.c - Same was threadmutex.c, but now using posix semaphores,
	not mutexes.
	compile with gcc -Wall threadmutex.c -o threadmutex -lpthread
 */

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>
#define THREADSCOUNT 3

static pthread_t ts[THREADSCOUNT];

static sem_t semaphore;

static struct { int x;
         int y;} foo;     /*This is a global data structure shared by threads*/

static void moo(int * a);

int main(void)
{
   int    i;
   int    *  who;

   /* Create a mutex */
   if (sem_init(&semaphore, 0, 1)) {
      perror("sem_init");
      exit(1);}

   /* Create threads */
   for (i=0; i<THREADSCOUNT; i++) {
     if((who = (int *)malloc(sizeof(int))) == NULL) {
       perror("malloc");
       exit(1);}
     *who = i;
     if (pthread_create(&(ts[i]), NULL, (void *)moo, who) != 0) {
       perror("pthread_create");
       exit(1);
     }
   }

   /* Wait for created threads to die */
   for (i=0; i<THREADSCOUNT; i++) {
     pthread_join(ts[i], NULL);
     printf("Thread %d has terminated\n", i);
   }
   return 0;
 }

void moo(int * a) {
  unsigned int interval;
  int i;

  for (i=0; i < 16; i++) {
      sem_wait(&semaphore);
      printf("I am thread %d before sleep; x=%d, y=%d\n", *a, foo.x, foo.y);
      foo.x = foo.y = *a;
      interval = 2;
      sleep(interval);
      printf("I am thread %d after sleep; x=%d, y=%d\n", *a, foo.x, foo.y);
      sem_post(&semaphore);
      /* Here is a small delay to give the other thread a chance to run */
      interval = 1000000;
      usleep(interval);
    }
}


