Revision: 131 http://trac.macosforge.org/projects/libdispatch/changeset/131 Author: robert@fledge.watson.org Date: 2009-11-04 13:15:54 -0800 (Wed, 04 Nov 2009) Log Message: ----------- Fixes for POSIX semaphores: POSIX semaphores take an absolute, CLOCK_REALTIME-based timespec as their timeout argument, not a relative timestamp. When using POSIX semaphores, we now keep all absolute timestamps in CLOCK_REALTIME, and for now, are unable to use POSIX semaphores while using Mach timekeeping. Add a missing DISPATCH_SEMAPHORE_VERIFY_RET() when calling sem_post(). #error out if we try to use POSIX semaphores with mach_absolute_time() for now. Modified Paths: -------------- trunk/configure.ac trunk/src/internal.h trunk/src/semaphore.c trunk/src/shims/time.h trunk/src/time.c Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-11-04 20:31:55 UTC (rev 130) +++ trunk/configure.ac 2009-11-04 21:15:54 UTC (rev 131) @@ -177,8 +177,7 @@ # # Find functions and declarations we care about. # -AC_CHECK_DECLS([CLOCK_UPTIME, CLOCK_MONOTONIC], [], [], - [[#include <time.h>]]) +AC_CHECK_DECLS([CLOCK_REALTIME], [], [], [[#include <time.h>]]) AC_CHECK_DECLS([EVFILT_SESSION, NOTE_NONE, NOTE_REAP, NOTE_SIGNAL], [], [], [[#include <sys/event.h>]]) AC_CHECK_DECLS([FD_COPY], [], [], [[#include <sys/select.h>]]) Modified: trunk/src/internal.h =================================================================== --- trunk/src/internal.h 2009-11-04 20:31:55 UTC (rev 130) +++ trunk/src/internal.h 2009-11-04 21:15:54 UTC (rev 131) @@ -254,6 +254,9 @@ bool _dispatch_source_testcancel(dispatch_source_t); uint64_t _dispatch_timeout(dispatch_time_t when); +#if USE_POSIX_SEM +struct timespec _dispatch_timeout_ts(dispatch_time_t when); +#endif __private_extern__ bool _dispatch_safe_fork; Modified: trunk/src/semaphore.c =================================================================== --- trunk/src/semaphore.c 2009-11-04 20:31:55 UTC (rev 130) +++ trunk/src/semaphore.c 2009-11-04 21:15:54 UTC (rev 131) @@ -203,11 +203,7 @@ #endif #if USE_POSIX_SEM do { - nsec = _dispatch_timeout(timeout); - _timeout.tv_sec = (typeof(_timeout.tv_sec)) - (nsec / NSEC_PER_SEC); - _timeout.tv_nsec = (typeof(_timeout.tv_nsec)) - (nsec % NSEC_PER_SEC); + _timeout = _dispatch_timeout_ts(timeout); ret = slowpath(sem_timedwait(&dsema->dsema_sem, &_timeout)); } while (ret == -1 && errno == EINTR); @@ -339,6 +335,7 @@ #endif #if USE_POSIX_SEM ret = sem_post(&dsema->dsema_sem); + DISPATCH_SEMAPHORE_VERIFY_RET(ret); #endif _dispatch_release(dsema); @@ -493,11 +490,7 @@ #endif #if USE_POSIX_SEM do { - nsec = _dispatch_timeout(timeout); - _timeout.tv_sec = (typeof(_timeout.tv_sec)) - (nsec / NSEC_PER_SEC); - _timeout.tv_nsec = (typeof(_timeout.tv_nsec)) - (nsec % NSEC_PER_SEC); + _timeout = _dispatch_timeout_ts(timeout); ret = slowpath(sem_timedwait(&dsema->dsema_sem, &_timeout)); } while (ret == -1 && errno == EINTR); Modified: trunk/src/shims/time.h =================================================================== --- trunk/src/shims/time.h 2009-11-04 20:31:55 UTC (rev 130) +++ trunk/src/shims/time.h 2009-11-04 21:15:54 UTC (rev 131) @@ -43,13 +43,7 @@ struct timespec ts; int ret; -#if HAVE_DECL_CLOCK_UPTIME - ret = clock_gettime(CLOCK_UPTIME, &ts); -#elif HAVE_DECL_CLOCK_MONOTONIC - ret = clock_gettime(CLOCK_MONOTONIC, &ts); -#else -#error "clock_gettime: no supported absolute time clock" -#endif + ret = clock_gettime(CLOCK_REALTIME, &ts); (void)dispatch_assume_zero(ret); /* XXXRW: Some kind of overflow detection needed? */ Modified: trunk/src/time.c =================================================================== --- trunk/src/time.c 2009-11-04 20:31:55 UTC (rev 130) +++ trunk/src/time.c 2009-11-04 21:15:54 UTC (rev 131) @@ -182,3 +182,46 @@ now = _dispatch_absolute_time(); return now >= when ? 0 : _dispatch_time_mach2nano(when - now); } + +#if USE_POSIX_SEM +#ifdef HAVE_MACH_ABSOLUTE_TIME +#error "Cannot currently use USE_POSIX_SEM and HAVE_MACH_ABSOLUTE_TIME together" +#endif +/* + * Unlike Mach semaphores, POSIX semaphores take an absolute, real time as an + * argument to sem_timedwait(). This routine converts from dispatch_time_t + * but assumes the caller has already handled the possibility of + * DISPATCH_TIME_FOREVER. + * + * XXXRW: Does not currently with with mach_absolute_time()/ + */ +struct timespec +_dispatch_timeout_ts(dispatch_time_t when) +{ + struct timespec ts; + int ret; + + if (when == 0) { + when = _dispatch_absolute_time(); + ts.tv_sec = when / NSEC_PER_SEC; + ts.tv_nsec = when % NSEC_PER_SEC; + return (ts); + } + if ((int64_t)when < 0) { + when = -(int64_t)when + _dispatch_absolute_time(); + ts.tv_sec = when / NSEC_PER_SEC; + ts.tv_nsec = when % NSEC_PER_SEC; + return (ts); + } + + /* + * XXXRW: This code assumes that dispatch_time_t absolute times are + * with respect to CLOCK_REALTIME. If we want to support + * USE_POSIX_SEM with mach_absolute_time(), a conversion is required + * here. + */ + ts.tv_sec = when / NSEC_PER_SEC; + ts.tv_nsec = when % NSEC_PER_SEC; + return (ts); +} +#endif