Revision: 82 http://trac.macosforge.org/projects/libdispatch/changeset/82 Author: robert@fledge.watson.org Date: 2009-11-02 03:19:15 -0800 (Mon, 02 Nov 2009) Log Message: ----------- Rework configure and conditional compilation logic for OS-provided semaphores: generate USE_MACH_SEM and USE_POSIX_SEM definitions so that precedence is selected in configure.ac rather than in the source code. This makes the policy of "use Mach semaphores even if POSIX semaphoresare available" explicit in the configuration process rather than implicit in the ifdefs. While here, migrate to defining a value of '1' rather than a simple define, as suggested by Kevin Van Vechten. In the future, we might want to add a --enable-posix-sem to allow forcing the use of POSIX semaphores on Mac OS X. Modified Paths: -------------- trunk/configure.ac trunk/src/internal.h trunk/src/legacy.h trunk/src/queue.c trunk/src/semaphore.c trunk/src/semaphore_internal.h Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/configure.ac 2009-11-02 11:19:15 UTC (rev 82) @@ -137,10 +137,10 @@ # AC_CHECK_HEADER([mach/mach.h], [AC_DEFINE(HAVE_MACH,,Define if mach is present) - use_mig=true], - [use_mig=false] + have_mach=true], + [have_mach=false] ) -AM_CONDITIONAL(USE_MIG, $use_mig) +AM_CONDITIONAL(USE_MIG, $have_mach) # # We use the availability of pthread_workqueue.h to decide whether to compile @@ -160,8 +160,27 @@ AC_CHECK_DECLS([FD_COPY], [], [], [[#include <sys/select.h>]]) AC_CHECK_DECLS([SIGEMT], [], [], [[#include <signal.h>]]) AC_CHECK_DECLS([VQ_UPDATE, VQ_VERYLOWDISK], [], [], [[#include <sys/mount.h>]]) -AC_CHECK_FUNCS([pthread_key_init_np pthread_main_np mach_absolute_time malloc_create_zone sem_init]) +AC_CHECK_FUNCS([pthread_key_init_np pthread_main_np mach_absolute_time malloc_create_zone]) +AC_CHECK_FUNC([sem_init], + [have_sem_init=true], + [have_sem_init=false] +) + +# +# We support both Mach semaphores and POSIX semaphores; if the former are +# available, prefer them. +# +AC_MSG_CHECKING([what semaphore type to use]); +AS_IF([test "x$have_mach" = "xtrue"], + [AC_DEFINE(USE_MACH_SEM,1,[Define to use Mach semaphores]) + AC_MSG_RESULT([Mach semaphores])], + [test "x$have_sem_init" = "xtrue"], + [AC_DEFINE(USE_POSIX_SEM,1,[Define to use POSIX semaphores]) + AC_MSG_RESULT([POSIX semaphores])], + [AC_MSG_ERROR([no supported semaphore type])] +) + AC_CHECK_HEADERS([sys/cdefs.h], [], [], [#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> Modified: trunk/src/internal.h =================================================================== --- trunk/src/internal.h 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/src/internal.h 2009-11-02 11:19:15 UTC (rev 82) @@ -105,7 +105,7 @@ #include <fcntl.h> #include <limits.h> #include <search.h> -#if !defined(HAVE_MACH) && defined(HAVE_SEM_INIT) +#if USE_POSIX_SEM #include <semaphore.h> #endif #include <signal.h> Modified: trunk/src/legacy.h =================================================================== --- trunk/src/legacy.h 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/src/legacy.h 2009-11-02 11:19:15 UTC (rev 82) @@ -51,9 +51,12 @@ struct dispatch_item_s *volatile di_next; dispatch_queue_t di_cback_q; uint32_t di_flags; -#ifdef HAVE_MACH +#if USE_MACH_SEM semaphore_t di_semaphore; #endif +#if USE_POSIX_SEM + /* Legacy API not supported except with Mach semaphores. */ +#endif void * di_work_func; void * di_work_ctxt; void * di_cback_func; Modified: trunk/src/queue.c =================================================================== --- trunk/src/queue.c 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/src/queue.c 2009-11-02 11:19:15 UTC (rev 82) @@ -1110,9 +1110,10 @@ pthread_workqueue_attr_t pwq_attr; int r; #endif -#ifdef HAVE_MACH +#if USE_MACH_SEM kern_return_t kr; -#else +#endif +#if USE_POSIX_SEM int ret; #endif int i; @@ -1141,13 +1142,14 @@ dispatch_assume_zero(r); } #endif /* HAVE_PTHREAD_WORKQUEUES */ -#ifdef HAVE_MACH +#if USE_MACH_SEM // override the default FIFO behavior for the pool semaphores kr = semaphore_create(mach_task_self(), &_dispatch_thread_mediator[i].dsema_port, SYNC_POLICY_LIFO, 0); DISPATCH_VERIFY_MIG(kr); dispatch_assume_zero(kr); dispatch_assume(_dispatch_thread_mediator[i].dsema_port); -#else +#endif +#if USE_POSIX_SEM /* XXXRW: POSIX semaphores don't support LIFO? */ ret = sem_init(&_dispatch_thread_mediator[i].dsema_sem, 0, 0); dispatch_assume_zero(ret); Modified: trunk/src/semaphore.c =================================================================== --- trunk/src/semaphore.c 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/src/semaphore.c 2009-11-02 11:19:15 UTC (rev 82) @@ -21,13 +21,14 @@ #include "internal.h" // semaphores are too fundamental to use the dispatch_assume*() macros -#ifdef HAVE_MACH +#if USE_MACH_SEM #define DISPATCH_SEMAPHORE_VERIFY_KR(x) do { \ if (x) { \ DISPATCH_CRASH("flawed group/semaphore logic"); \ } \ } while (0) -#else +#endif +#if USE_POSIX_SEM #define DISPATCH_SEMAPHORE_VERIFY_RET(x) do { \ if ((x) == -1) { \ DISPATCH_CRASH("flawed group/semaphore logic"); \ @@ -108,7 +109,7 @@ return dsema; } -#ifdef HAVE_MACH +#if USE_MACH_SEM static void _dispatch_semaphore_create_port(semaphore_t *s4) { @@ -138,7 +139,8 @@ _dispatch_safe_fork = false; } -#else /* !HAVE_MACH */ +#endif +#if USE_POSIX_SEM static void _dispatch_posix_semaphore_create(sem_t *s4) { @@ -151,16 +153,17 @@ ret = sem_init(s4, 0, 0); dispatch_assume_zero(ret); } -#endif /* HAVE_MACH */ +#endif DISPATCH_NOINLINE static long _dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout) { -#ifdef HAVE_MACH +#if USE_MACH_SEM mach_timespec_t _timeout; kern_return_t kr; -#else +#endif +#if USE_POSIX_SEM struct timespec _timeout; int ret; #endif @@ -177,9 +180,10 @@ } } -#ifdef HAVE_MACH +#if USE_MACH_SEM _dispatch_semaphore_create_port(&dsema->dsema_port); -#else +#endif +#if USE_POSIX_SEM _dispatch_posix_semaphore_create(&dsema->dsema_sem); #endif @@ -193,7 +197,7 @@ switch (timeout) { default: -#ifdef HAVE_MACH +#if USE_MACH_SEM do { // timeout() already calculates relative time left nsec = _dispatch_timeout(timeout); @@ -206,7 +210,8 @@ DISPATCH_SEMAPHORE_VERIFY_KR(kr); break; } -#else /* !HAVE_MACH */ +#endif +#if USE_POSIX_SEM do { nsec = _dispatch_timeout(timeout); _timeout.tv_sec = (typeof(_timeout.tv_sec)) @@ -221,14 +226,15 @@ DISPATCH_SEMAPHORE_VERIFY_RET(ret); break; } -#endif /* HAVE_MACH */ +#endif // Fall through and try to undo what the fast path did to dsema->dsema_value case DISPATCH_TIME_NOW: while ((orig = dsema->dsema_value) < 0) { if (dispatch_atomic_cmpxchg(&dsema->dsema_value, orig, orig + 1)) { -#ifdef HAVE_MACH +#if USE_MACH_SEM return KERN_OPERATION_TIMED_OUT; -#else +#endif +#if USE_POSIX_SEM errno = ETIMEDOUT; return -1; #endif @@ -237,12 +243,13 @@ // Another thread called semaphore_signal(). // Fall through and drain the wakeup. case DISPATCH_TIME_FOREVER: -#ifdef HAVE_MACH +#if USE_MACH_SEM do { kr = semaphore_wait(dsema->dsema_port); } while (kr == KERN_ABORTED); DISPATCH_SEMAPHORE_VERIFY_KR(kr); -#else +#endif +#if USE_POSIX_SEM do { ret = sem_wait(&dsema->dsema_sem); } while (ret != 0); @@ -318,9 +325,10 @@ static long _dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema) { -#ifndef HAVE_MACH +#if USE_POSIX_SEM int ret; -#else +#endif +#if USE_MACH_SEM kern_return_t kr; _dispatch_semaphore_create_port(&dsema->dsema_port); @@ -335,10 +343,11 @@ dispatch_atomic_inc(&dsema->dsema_sent_ksignals); -#ifdef HAVE_MACH +#if USE_MACH_SEM kr = semaphore_signal(dsema->dsema_port); DISPATCH_SEMAPHORE_VERIFY_KR(kr); -#else +#endif +#if USE_POSIX_SEM ret = sem_post(&dsema->dsema_sem); #endif @@ -398,22 +407,24 @@ struct dispatch_sema_notify_s *tmp, *head = dispatch_atomic_xchg(&dsema->dsema_notify_head, NULL); long rval = dispatch_atomic_xchg(&dsema->dsema_group_waiters, 0); bool do_rel = head; -#ifdef HAVE_MACH +#if USE_MACH_SEM long kr; -#else +#endif +#if USE_POSIX_SEM int ret; #endif // wake any "group" waiter or notify blocks if (rval) { -#ifdef HAVE_MACH +#if USE_MACH_SEM _dispatch_semaphore_create_port(&dsema->dsema_waiter_port); do { kr = semaphore_signal(dsema->dsema_waiter_port); DISPATCH_SEMAPHORE_VERIFY_KR(kr); } while (--rval); -#else +#endif +#if USE_POSIX_SEM do { ret = sem_post(&dsema->dsema_sem); DISPATCH_SEMAPHORE_VERIFY_RET(ret); @@ -439,10 +450,11 @@ static long _dispatch_group_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout) { -#ifdef HAVE_MACH +#if USE_MACH_SEM mach_timespec_t _timeout; kern_return_t kr; -#else +#endif +#if USE_POSIX_SEM struct timespec _timeout; int ret; #endif @@ -463,7 +475,7 @@ return _dispatch_group_wake(dsema); } -#ifdef HAVE_MACH +#if USE_MACH_SEM _dispatch_semaphore_create_port(&dsema->dsema_waiter_port); #endif @@ -477,7 +489,7 @@ switch (timeout) { default: -#ifdef HAVE_MACH +#if USE_MACH_SEM do { nsec = _dispatch_timeout(timeout); _timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC); @@ -488,7 +500,8 @@ DISPATCH_SEMAPHORE_VERIFY_KR(kr); break; } -#else +#endif +#if USE_POSIX_SEM do { nsec = _dispatch_timeout(timeout); _timeout.tv_sec = (typeof(_timeout.tv_sec)) @@ -507,9 +520,10 @@ case DISPATCH_TIME_NOW: while ((orig = dsema->dsema_group_waiters)) { if (dispatch_atomic_cmpxchg(&dsema->dsema_group_waiters, orig, orig - 1)) { -#ifdef HAVE_MACH +#if USE_MACH_SEM return KERN_OPERATION_TIMED_OUT; -#else +#endif +#if USE_POSIX_SEM errno = ETIMEDOUT; return -1; #endif @@ -518,12 +532,13 @@ // Another thread called semaphore_signal(). // Fall through and drain the wakeup. case DISPATCH_TIME_FOREVER: -#ifdef HAVE_MACH +#if USE_MACH_SEM do { kr = semaphore_wait(dsema->dsema_waiter_port); } while (kr == KERN_ABORTED); DISPATCH_SEMAPHORE_VERIFY_KR(kr); -#else +#endif +#if USE_POSIX_SEM do { ret = sem_wait(&dsema->dsema_sem); } while (ret == -1 && errno == EINTR); @@ -544,9 +559,10 @@ return 0; } if (timeout == 0) { -#ifdef HAVE_MACH +#if USE_MACH_SEM return KERN_OPERATION_TIMED_OUT; -#else +#endif +#if USE_POSIX_SEM errno = ETIMEDOUT; return (-1); #endif @@ -594,9 +610,10 @@ void _dispatch_semaphore_dispose(dispatch_semaphore_t dsema) { -#ifdef HAVE_MACH +#if USE_MACH_SEM kern_return_t kr; -#else +#endif +#if USE_POSIX_SEM int ret; #endif @@ -604,7 +621,7 @@ DISPATCH_CLIENT_CRASH("Semaphore/group object deallocated while in use"); } -#ifdef HAVE_MACH +#if USE_MACH_SEM if (dsema->dsema_port) { kr = semaphore_destroy(mach_task_self(), dsema->dsema_port); DISPATCH_SEMAPHORE_VERIFY_KR(kr); @@ -613,7 +630,8 @@ kr = semaphore_destroy(mach_task_self(), dsema->dsema_waiter_port); DISPATCH_SEMAPHORE_VERIFY_KR(kr); } -#else +#endif +#if USE_POSIX_SEM ret = sem_destroy(&dsema->dsema_sem); DISPATCH_SEMAPHORE_VERIFY_RET(ret); #endif @@ -627,7 +645,7 @@ size_t offset = 0; offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dx_kind(dsema), dsema); offset += dispatch_object_debug_attr(dsema, &buf[offset], bufsiz - offset); -#ifdef HAVE_MACH +#if USE_MACH_SEM offset += snprintf(&buf[offset], bufsiz - offset, "port = 0x%u, ", dsema->dsema_port); #endif Modified: trunk/src/semaphore_internal.h =================================================================== --- trunk/src/semaphore_internal.h 2009-11-02 10:58:46 UTC (rev 81) +++ trunk/src/semaphore_internal.h 2009-11-02 11:19:15 UTC (rev 82) @@ -39,10 +39,12 @@ long dsema_value; long dsema_orig; size_t dsema_sent_ksignals; -#ifdef HAVE_MACH +#if USE_MACH_SEM && USE_POSIX_SEM +#error "Too many supported semaphore types" +#elif USE_MACH_SEM semaphore_t dsema_port; semaphore_t dsema_waiter_port; -#elif defined(HAVE_SEM_INIT) +#elif USE_POSIX_SEM sem_t dsema_sem; #else #error "No supported semaphore type"
participants (1)
-
source_changes@macosforge.org