Program using Semaphores runs fine on Linux...unexpected results on Mac osX

19,303

Solution 1

Check the error return on the sem_init calls; I bet you'll find the OS X version returning a "Function not implemented" error.

This is because unnamed POSIX semaphores are not implemented on OS X. You need to use named semaphores, or pthread mutex/condition variables.

Solution 2

Just for completeness, here's a working Mac OS X version using sem_open() and sem_unlink() instead of sem_init() and sem_destroy().

/*
cat semtest.c

source:
"Program using Semaphores runs fine on Linux...unexpected results on Mac osX",
http://stackoverflow.com/questions/4136181/program-using-semaphores-runs-fine-on-linux-unexpected-results-on-mac-osx

compiled on Mac OS X 10.6.8 with:
gcc -ansi -pedantic -std=gnu99 -Os -Wall -Wextra -Wshadow -l pthread -o semtest semtest.c

./semtest

*/


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

void* function1();
void* function2();

// shared values
volatile int X;
volatile int Y;

// declare semaphores
//sem_t s1;
//sem_t s2;
sem_t *s1;
sem_t *s2;
static const char *semname1 = "Semaphore1";
static const char *semname2 = "Semaphore2";

int main(void)
{

   void* status;

   pthread_t thread1;
   pthread_t thread2;
   srand(time(NULL));

   /*
   // initialize semaphores to zero
   sem_init(&s1, 0, 0);
   sem_init(&s2, 0, 0);
   */

   s1 = sem_open(semname1, O_CREAT, 0777, 0);
   if (s1 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
      exit(EXIT_FAILURE);
   }

   s2 = sem_open(semname2, O_CREAT, 0777, 0);
   if (s2 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
      exit(EXIT_FAILURE);
   }


   pthread_create(&thread1, NULL, function1, NULL);
   pthread_create(&thread2, NULL, function2, NULL);

   pthread_join(thread1, &status);
   pthread_join(thread2, &status);

   //sem_destroy(&s1);
   //sem_destroy(&s2);
   sem_unlink(semname1);
   sem_unlink(semname2);

   return 0;

}

void* function1()
{
   while(1)
   {
   X = rand()%1000; // write 
   printf("After thread ID A writes to X, X = %d\n", X);
   //sem_post(&s1); // signal
   //sem_wait(&s2); // wait
   sem_post(s1); // signal
   sem_wait(s2); // wait
   printf("After thread ID A reads from Y, Y = %d\n", Y); // read
   sleep(3);
   }   
}

void* function2()
{
   while(1)
   {
    //sem_wait(&s1); // wait
    sem_wait(s1); // wait
    printf("After thread ID B reads from X, X = %d\n", X); // read
    Y = rand()%1000; // write
    printf("After thread ID B write to Y, Y = %d\n", Y);
    //sem_post(&s2); // signal
    sem_post(s2); // signal
    sleep(3);
   }
}
Share:
19,303
Adam Soffer
Author by

Adam Soffer

Updated on July 24, 2022

Comments

  • Adam Soffer
    Adam Soffer almost 2 years

    I wrote a simple program solving the Readers-Writers problem using semaphores. It runs perfectly on Linux os, but when I run it on my Mac osX I get unexpected results and I can't figure out why.

    My Program:

    #include <semaphore.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void* function1(void* val);
    void* function2(void* val);
    
    // shared values
    volatile int X;
    volatile int Y;
    
    // declare semaphores
    sem_t s1;
    sem_t s2;
    
    main()
    {
    void* status;
    
    pthread_t thread1;
    pthread_t thread2;
    srand(time(NULL));
    
    // initialize semaphores to zero
    sem_init(&s1, 0, 0);
    sem_init(&s2, 0, 0);
    
    pthread_create(&thread1, NULL, function1, NULL);
    pthread_create(&thread2, NULL, function2, NULL);
    
    pthread_join(thread1, &status);
    pthread_join(thread2, &status);
    
    sem_destroy(&s1);
    sem_destroy(&s2);
    
    }
    
    void* function1(void* val)
    {
       while(1)
       {
       X = rand()%1000; // write 
       printf("After thread ID A writes to X, X = %d\n", X);
       sem_post(&s1); // signal
       sem_wait(&s2); // wait
       printf("After thread ID A reads from Y, Y = %d\n", Y); // read
       sleep(3);
       }   
    }
    
    void* function2(void* val)
    {
       while(1)
       {
        sem_wait(&s1); // wait
        printf("After thread ID B reads from X, X = %d\n", X); // read
        Y = rand()%1000; // write
        printf("After thread ID B write to Y, Y = %d\n", Y);
        sem_post(&s2); // signal
        sleep(3);
       }
    }
    

    The output I receive on Linux (what it's supposed to look like):

    After thread ID A writes to X, X = 100
    After thread ID B reads from X, X = 100
    After thread ID B write to Y, Y = 234
    After thread ID A reads from Y, Y = 234
    ...
    

    The output on Mac osX (unexpected):

    After thread ID A writes to X, X = 253
    After thread ID A reads from Y, Y = 0
    After thread ID B reads from X, X = 253
    After thread ID B write to Y, Y = 728
    ...
    
  • Adam Soffer
    Adam Soffer over 13 years
    Thanks so much. I was unaware of that.
  • Clay Ellis
    Clay Ellis over 8 years
    You have saved my life. Not really but basically. I couldn't find anything about how to initialize semaphores on Mac OS X. I can't believe they don't support unnamed semaphores...