Why are sem_init(), sem_getvalue(), sem_destroy() deprecated on Mac OS X — and what replaces them?
Asked Answered
V

2

51

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.)

Vibrio answered 2/1, 2015 at 2:8 Comment(5)
Related to https://mcmap.net/q/295442/-sem_init-on-os-x and #16655653?Geometrician
@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.Vibrio
Another and perhaps more canonical source of an answer may be found via devforums.apple.com in the "Core OS" subsection of "Mac Development".Izettaizhevsk
@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.Endurable
Does this answer your question? sem_init on OS XSeverini
N
55

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 (Grand Central Dispatch) 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, this 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.

Nylons answered 8/1, 2015 at 18:30 Comment(3)
I think I'd want to add the destroy function to the set, but that's a useful starting point. Thank you.Vibrio
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.Eyeshade
Appendix 9 of the Single UNIX Specification states they are not mandatory interfaces Welcome to IEEE Std 1003.1-2008: "The <semaphore.h> header is moved from the Semaphores option to the Base." Yes, that's from 2008 - the excuse was outdated when it was written...Incorporeal
T
0

Just to add add some color here, sem_init on OS X claims that the compiler reports "deprecated" but the implementation is literally to just set errno and return -1.

Shameful really. You have no choice but to baloon your code if you want simple semaphores on Mac.

Tillietillinger answered 2/4, 2024 at 17:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.