Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

posix

macos

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 c and no questions that ask about deprecated system calls — only programs.)

like image 803
Jonathan Leffler Avatar asked Jan 02 '15 02:01

Jonathan Leffler


People also ask

What is Sem_init?

The sem_init() function initializes an unnamed semaphore and sets its initial value. The maximum value of the semaphore is set to SEM_VALUE_MAX. The title for the semaphore is set to the character representation of the address of the semaphore.

How do you destroy semaphores?

NOTES top. An unnamed semaphore should be destroyed with sem_destroy() before the memory in which it is located is deallocated. Failure to do this can result in resource leaks on some implementations.

What is semaphore H?

h> header defines the sem_t type, used in performing semaphore operations. The semaphore can be implemented using a file descriptor, in which case applications are able to open up at least a total of {OPEN_MAX} files and semaphores. The symbol SEM_FAILED is defined (see sem_open(3C)). Inclusion of the <semaphore.

How are named semaphores used?

Two processes can operate on the same named semaphore by passing the same name to sem_open(3). The sem_open(3) function creates a new named semaphore or opens an existing named semaphore. After the semaphore has been opened, it can be operated on using sem_post(3) and sem_wait(3).


1 Answers

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.

like image 130
dho Avatar answered Sep 21 '22 05:09

dho