'POSIX semaphores on macos

I am trying to create a semaphore and practicing by using this simple program, though I am getting a bunch of deprecated warnings when compiling on macos. I have been looking and having trouble finding a solution to get the semaphore to work for macos.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>

#define THREAD_NUM 4

sem_t semaphore;

void* routine(void* args) {
    sem_wait(&semaphore);
    sleep(1);
    printf("Hello from thread %d\n", *(int*)args);
    sem_post(&semaphore);
    free(args);
}

int main(int argc, char *argv[]) {
    pthread_t th[THREAD_NUM];
    sem_init(&semaphore, 0, 1);
    int i;
    for (i = 0; i < THREAD_NUM; i++) {
        int* a = malloc(sizeof(int));
        *a = i;
        if (pthread_create(&th[i], NULL, &routine, a) != 0) {
            perror("Failed to create thread");
        }
    }

    for (i = 0; i < THREAD_NUM; i++) {
        if (pthread_join(th[i], NULL) != 0) {
            perror("Failed to join thread");
        }
    }
    sem_destroy(&semaphore);
    return 0;
}

I am expecting the threads to be created for the routine function where 4 threads exist for 4 void* routine(). It should printf("Hello from thread") every second starting from thread 0 and going to 3. What is actually happening is all the printf statements get outputed to the console after 1 second at the same time.

Output:

Hello from thread 0

Hello from thread 1

Hello from thread 2

Hello from thread 3

Compiler information:

test.c:18:1: warning: non-void function does not return a value [-Wreturn-type]
}
^

test.c:22:5: warning: 'sem_init' is deprecated [-Wdeprecated-declarations]
    sem_init(&semaphore, 0, 4);
    ^

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:55:42: note: 'sem_init' has been explicitly marked deprecated here
int sem_init(sem_t *, int, unsigned int) __deprecated;
                                         ^

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^

test.c:37:5: warning: 'sem_destroy' is deprecated [-Wdeprecated-declarations]
    sem_destroy(&semaphore);
    ^

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:53:26: note: 'sem_destroy' has been explicitly marked deprecated here
int sem_destroy(sem_t *) __deprecated;
                         ^

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^

3 warnings generated.


Solution 1:[1]

I am expecting the threads to be created for the routine function where 4 threads exist for 4 void* routine(). It should printf("Hello from thread") every second starting from thread 0 and going to 3.

I would expect that, too, on any machine that provides POSIX-conforming pthreads, POSIX semaphores, and sleep(). Especially if you resolve the first of the warnings -- for example, by adding return NULL; at the end of function routine().

My expectation is fulfilled on my Linux test machine. However, there are comments around various parts of the web suggesting that MacOS does not support unnamed semaphores, which is what you are trying to use by calling sem_init(). As I understand it, this is the significance of the deprecation warnings you report -- the functions are there, but (I guess) they don't actually work.

If indeed MacOS's sem_init() is non-functional, then calls to it should return an error code. You don't know whether that's happening, because you don't check for it. Always check your functions' error indicators if in fact you care whether they succeeded (and here, you certainly do).

One possible workaround that does not require abandoning POSIX interfaces would be to switch to named semaphores instead of unnamed ones. That would involve using sem_open() and sem_close() instead of sem_init() and sem_destroy().

What is actually happening is all the printf statements get outputed to the console after 1 second at the same time.

That certainly sounds like the semaphore is not working. Your threads are working, because you get the output at all, and they are running in parallel, because their sleep()s all expire at about the same time. Again, check the error indicators of your function calls (their return values for all library functions in the example code), as this will often clue you in when something does not work as you expect, whether because of something wrong with your code or because erroneous data or runtime environment.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 John Bollinger