yohhoyの日記

技術的メモをしていきたい日記

macOSはPOSIX無名セマフォをサポートしない

macOS(旧Mac OS X)では POSIX無名(unnamed)セマフォ を意図的にサポートしない。
無名セマフォ生成sem_initや破壊sem_destroy関数呼び出しはerrno=ENOSYS(function not supported)/戻り値-1で常に失敗する。(おまけ:sem_getvalue関数も非サポート)

名前無しセマフォDispatchSemaphore で代替可能。一般的にはObjective-CやSwiftから呼び出す GCD(Grand Central Dispatch)ランタイム の一部だが、C言語APIとして提供されるためネイティブC/C++コードからも利用できる。
実装例:https://github.com/yohhoy/yamc/blob/master/include/gcd_semaphore.hpp

2009年4月頃のTerry Lambert氏*1メールより一部引用。

They aren't required for UNIX conformance because they are not mandatory interfaces per Appendix 9 of the Single UNIX Specification, and there are lots of alternatives, most of them with better overall semantics, which this tread has amply demonstrated. Most portable and historical software uses System V semaphores, since POSIX semaphores are relatively new, so there's little software portability incentive. The software which does like to use them is typically based on GNU autoconf/automake which typically uses linkage tests to find interfaces and blows it by doing that and ignoring <unistd.h> contents, since historical conformance with older versions of the specification permitted stub functions which errored out, and the linkage tests only check linkability rather than functionality. So basically the software that wants them usually fails to conform to the standards which would have allowed them to be used safely and reliably in the first place.

Then there is the little problem of binary backward compatibility for POSIX named semaphores, if the error or success returns don't happen to match the standard once testing of a full implementation became possible.

As a Mac OS X implementation detail, sem_t is the required data type for both POSIX named semaphores and POSIX unnamed semaphores according to the standard. The sem_t definition has historically been a 32 bit value containing an fd cast to a pointer, which is problematic for maintaining binary and source backward compatibility (hint: think symbol decoration) for named semaphores while at the same time permitting typical usage of unnamed semaphores. Specifically, typical usage of unnamed semaphores is to use them as an IPC synchronization mechanism between otherwise unrelated programs by allocating a shared memory region shared between them of sizeof(sem_t) *number_of_semaphores_desired, and the casting the base address of that memory region to a (sem_t *) and indexing off that to get a semaphore index in the range 0..(number_of_semaphores_desired - 1).

The implementation problems should now be obvious. They are not insurmountable; I sometimes pose how to resolve the conflicting goals involved as an interview question. 8-). But there isn't really a very obvious fix I'd call elegant, either.

https://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html

関連URL

*1:同氏はMac OS Xカーネルの6%を書いたとのこと。https://www.quora.com/profile/Terry-Lambert