50

When I compile a program using the POSIX sem_init() function, I get a compilation warning (error because I normally use -Werror) that the function has been deprecated when I compile on Mac OS X 10.10.1 (Yosemite) with GCC 4.9.1 or the version of Clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)) from XCode 6.1.1. A quick look at /usr/include/sys/semaphore.h shows that the function does indeed have a __deprecated tag after its declaration, as do sem_getvalue() and sem_destroy().

Questions:

  1. Given that there is no hint of deprecation in the POSIX specification, why are these three functions singled out as deprecated on Mac OS X?

  2. Given that they are deprecated, what is the replacement, and why is the replacement preferred?

(I did check Ask Different first; there are no questions tagged and no questions that ask about deprecated system calls — only programs.)

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    Related to http://stackoverflow.com/questions/1413785/sem-init-on-os-x and http://stackoverflow.com/questions/16655153/sem-getvalue-dysfunctionality-in-mac-os-x-c/16655541#16655541? – Iskar Jarak Jan 02 '15 at 02:14
  • 1
    @IskarJarak: The first of those two seems to cover my problem in practice, though there still "why" (as in "why doesn't Mac OS X support unnamed semaphores?) that is unresolved. But that's probably the least easily answered part. Since my code wasn't compiling, I wasn't getting to the point of an ENOSYS error from the `sem_init()` function. – Jonathan Leffler Jan 02 '15 at 02:23
  • Another and perhaps more canonical source of an answer may be found via https://devforums.apple.com in the "Core OS" subsection of "Mac Development". – Alex Reynolds Jan 02 '15 at 07:47
  • 2
    @JonathanLeffler, implementing control structures in shared memory between processes is a considerable overhead as well in development as in execution. They probably just don't want to incur that for an interface that has not much use in a world of threads. Their way of dealing with this is in fact very annoying, providing an interface that just returns you an error. That shows, again, that their adherence to POSIX is just on the surface. They are not really commited to provide an open environment. – Jens Gustedt Jan 02 '15 at 10:33
  • Does this answer your question? [sem\_init on OS X](https://stackoverflow.com/questions/1413785/sem-init-on-os-x) – G Huxley Mar 31 '22 at 02:34

1 Answers1

51

I ran into this problem myself when trying to port a library I was working on to OS X. I searched for a while without finding a great answer. When I did find the answer, I was a bit perturbed: the answer is effectively "if Apple implemented POSIX unnamed semaphores, how many X Serves would you buy?".

To summarize the points of why they are deprecated and why some of the functionality remains unimplemented:

  • Appendix 9 of the Single UNIX Specification states they are not mandatory interfaces
  • "Most portable code" uses SYSV semaphores
  • Backwards compatibility with POSIX named semaphores, which share the sem_t type is difficult

As for what to do instead, I went with GCD semaphores. As to why the replacement is preferred: it's the only native unnamed semaphore interface available on vanilla OS X. Apparently GCD helped them sell more X Serves. I fear there's not a better answer.

However, hopefully some code will be helpful. The upshot of all of this is that you effectively have to implement your own portable semaphore interface:

#ifdef __APPLE__
#include <dispatch/dispatch.h>
#else
#include <semaphore.h>
#endif

struct rk_sema {
#ifdef __APPLE__
    dispatch_semaphore_t    sem;
#else
    sem_t                   sem;
#endif
};


static inline void
rk_sema_init(struct rk_sema *s, uint32_t value)
{
#ifdef __APPLE__
    dispatch_semaphore_t *sem = &s->sem;

    *sem = dispatch_semaphore_create(value);
#else
    sem_init(&s->sem, 0, value);
#endif
}

static inline void
rk_sema_wait(struct rk_sema *s)
{

#ifdef __APPLE__
    dispatch_semaphore_wait(s->sem, DISPATCH_TIME_FOREVER);
#else
    int r;

    do {
            r = sem_wait(&s->sem);
    } while (r == -1 && errno == EINTR);
#endif
}

static inline void
rk_sema_post(struct rk_sema *s)
{

#ifdef __APPLE__
    dispatch_semaphore_signal(s->sem);
#else
    sem_post(&s->sem);
#endif
}

This was the minimal set of functionality I cared about; your needs may vary. Hopefully this is helpful.

dho
  • 2,310
  • 18
  • 20
  • 4
    I think I'd want to add the destroy function to the set, but that's a useful starting point. Thank you. – Jonathan Leffler Jan 08 '15 at 18:53
  • Excellent, you provided what I need. It really should be an error if Apple did not implement unnamed semaphores. Anyway, after I changed the code as per what you provided, it now runs well. – Yongwei Wu Dec 22 '19 at 15:01