[libdispatch-changes] [192] trunk/src
source_changes at macosforge.org
source_changes at macosforge.org
Sun Oct 24 01:25:55 PDT 2010
Revision: 192
http://trac.macosforge.org/projects/libdispatch/changeset/192
Author: kvv at apple.com
Date: 2010-10-24 01:25:52 -0700 (Sun, 24 Oct 2010)
Log Message:
-----------
Support for time and semaphores on Win32.
Modified Paths:
--------------
trunk/src/internal.h
trunk/src/queue.c
trunk/src/semaphore.c
trunk/src/semaphore_internal.h
trunk/src/shims/time.c
trunk/src/shims/time.h
trunk/src/time.c
Modified: trunk/src/internal.h
===================================================================
--- trunk/src/internal.h 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/internal.h 2010-10-24 08:25:52 UTC (rev 192)
@@ -29,6 +29,37 @@
#include "config/config.h"
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
+#if TARGET_OS_WIN32
+// Include Win32 headers early in order to minimize the
+// likelihood of name pollution from dispatch headers.
+
+#ifndef WINVER
+#define WINVER 0x502
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x502
+#endif
+
+#ifndef _MSC_VER
+#define _MSC_VER 1400
+#pragma warning(disable:4159)
+#endif
+
+#define WIN32_LEAN_AND_MEAN 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_WARNINGS 1
+
+#define BOOL WINBOOL
+#include <Windows.h>
+#undef BOOL
+
+#endif /* TARGET_OS_WIN32 */
+
#define __DISPATCH_BUILDING_DISPATCH__
#define __DISPATCH_INDIRECT__
@@ -96,6 +127,9 @@
#include <netinet/in.h>
#ifdef __BLOCKS__
+#if TARGET_OS_WIN32
+#define BLOCK_EXPORT extern "C" __declspec(dllexport)
+#endif /* TARGET_OS_WIN32 */
#include <Block_private.h>
#include <Block.h>
#endif /* __BLOCKS__ */
Modified: trunk/src/queue.c
===================================================================
--- trunk/src/queue.c 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/queue.c 2010-10-24 08:25:52 UTC (rev 192)
@@ -1200,6 +1200,10 @@
ret = sem_init(&_dispatch_thread_mediator[i].dsema_sem, 0, 0);
(void)dispatch_assume_zero(ret);
#endif
+#if USE_WIN32_SEM
+ _dispatch_thread_mediator[i].dsema_handle = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+ dispatch_assume(_dispatch_thread_mediator[i].dsema_handle);
+#endif
#if HAVE_PTHREAD_WORKQUEUES
} else {
dispatch_assume(_dispatch_root_queue_contexts[i].dgq_kworkqueue);
Modified: trunk/src/semaphore.c
===================================================================
--- trunk/src/semaphore.c 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/semaphore.c 2010-10-24 08:25:52 UTC (rev 192)
@@ -56,7 +56,7 @@
{
dispatch_semaphore_t dsema;
- dsema = fastpath(_dispatch_thread_getspecific(dispatch_sema4_key));
+ dsema = (dispatch_semaphore_t)fastpath(_dispatch_thread_getspecific(dispatch_sema4_key));
if (!dsema) {
while (!(dsema = dispatch_semaphore_create(0))) {
sleep(1);
@@ -69,7 +69,7 @@
void
_dispatch_put_thread_semaphore(dispatch_semaphore_t dsema)
{
- dispatch_semaphore_t old_sema = _dispatch_thread_getspecific(dispatch_sema4_key);
+ dispatch_semaphore_t old_sema = (dispatch_semaphore_t)_dispatch_thread_getspecific(dispatch_sema4_key);
_dispatch_thread_setspecific(dispatch_sema4_key, dsema);
if (old_sema) {
dispatch_release(old_sema);
@@ -97,11 +97,11 @@
return NULL;
}
- dsema = calloc(1, sizeof(struct dispatch_semaphore_s));
+ dsema = (dispatch_semaphore_t)calloc(1, sizeof(struct dispatch_semaphore_s));
if (fastpath(dsema)) {
dsema->do_vtable = &_dispatch_semaphore_vtable;
- dsema->do_next = DISPATCH_OBJECT_LISTLESS;
+ dsema->do_next = (dispatch_semaphore_t)DISPATCH_OBJECT_LISTLESS;
dsema->do_ref_cnt = 1;
dsema->do_xref_cnt = 1;
dsema->do_targetq = dispatch_get_global_queue(0, 0);
@@ -148,6 +148,28 @@
}
#endif
+#if USE_WIN32_SEM
+static void
+_dispatch_semaphore_create_handle(HANDLE *s4)
+{
+ HANDLE tmp;
+
+ if (*s4) {
+ return;
+ }
+
+ // lazily allocate the semaphore port
+
+ while (dispatch_assume(tmp = CreateSemaphore(NULL, 0, LONG_MAX, NULL)) == NULL) {
+ sleep(1);
+ }
+
+ if (!dispatch_atomic_cmpxchg(s4, 0, tmp)) {
+ CloseHandle(tmp);
+ }
+}
+#endif /* USE_WIN32_SEM */
+
DISPATCH_NOINLINE
static long
_dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout)
@@ -155,10 +177,11 @@
#if USE_MACH_SEM
mach_timespec_t _timeout;
kern_return_t kr;
- uint64_t nsec;
#endif
#if USE_POSIX_SEM
struct timespec _timeout;
+#endif
+#if USE_POSIX_SEM || USE_WIN32_SEM
int ret;
#endif
long orig;
@@ -176,6 +199,9 @@
#if USE_MACH_SEM
_dispatch_semaphore_create_port(&dsema->dsema_port);
#endif
+#if USE_WIN32_SEM
+ _dispatch_semaphore_create_handle(&dsema->dsema_handle);
+#endif
// From xnu/osfmk/kern/sync_sema.c:
// wait_semaphore->count = -1; /* we don't keep an actual count */
@@ -189,6 +215,7 @@
default:
#if USE_MACH_SEM
do {
+ uint64_t nsec;
// timeout() already calculates relative time left
nsec = _dispatch_timeout(timeout);
_timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC);
@@ -213,6 +240,18 @@
break;
}
#endif
+#if USE_WIN32_SEM
+ do {
+ uint64_t nsec;
+ DWORD msec;
+ nsec = _dispatch_timeout(timeout);
+ msec = (DWORD)(nsec / (uint64_t)1000000);
+ ret = WaitForSingleObject(dsema->dsema_handle, msec);
+ } while (ret != WAIT_OBJECT_0 && ret != WAIT_TIMEOUT);
+ if (ret != WAIT_TIMEOUT) {
+ break;
+ }
+#endif /* USE_WIN32_SEM */
// 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) {
@@ -220,7 +259,7 @@
#if USE_MACH_SEM
return KERN_OPERATION_TIMED_OUT;
#endif
-#if USE_POSIX_SEM
+#if USE_POSIX_SEM || USE_WIN32_SEM
errno = ETIMEDOUT;
return -1;
#endif
@@ -241,6 +280,11 @@
} while (ret != 0);
DISPATCH_SEMAPHORE_VERIFY_RET(ret);
#endif
+#if USE_WIN32_SEM
+ do {
+ ret = WaitForSingleObject(dsema->dsema_handle, INFINITE);
+ } while (ret != WAIT_OBJECT_0);
+#endif
break;
}
@@ -311,7 +355,7 @@
static long
_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
{
-#if USE_POSIX_SEM
+#if USE_POSIX_SEM || USE_WIN32_SEM
int ret;
#endif
#if USE_MACH_SEM
@@ -319,6 +363,9 @@
_dispatch_semaphore_create_port(&dsema->dsema_port);
#endif
+#if USE_WIN32_SEM
+ _dispatch_semaphore_create_handle(&dsema->dsema_handle);
+#endif
// Before dsema_sent_ksignals is incremented we can rely on the reference
// held by the waiter. However, once this value is incremented the waiter
@@ -337,6 +384,10 @@
ret = sem_post(&dsema->dsema_sem);
DISPATCH_SEMAPHORE_VERIFY_RET(ret);
#endif
+#if USE_WIN32_SEM
+ // Signal the semaphore.
+ ret = ReleaseSemaphore(dsema->dsema_handle, 1, NULL);
+#endif
_dispatch_release(dsema);
@@ -391,13 +442,14 @@
long
_dispatch_group_wake(dispatch_semaphore_t dsema)
{
- 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;
+ struct dispatch_sema_notify_s *tmp;
+ struct dispatch_sema_notify_s *head = (struct dispatch_sema_notify_s *)dispatch_atomic_xchg(&dsema->dsema_notify_head, NULL);
+ long rval = (long)dispatch_atomic_xchg(&dsema->dsema_group_waiters, 0);
+ bool do_rel = (head != NULL);
#if USE_MACH_SEM
long kr;
#endif
-#if USE_POSIX_SEM
+#if USE_POSIX_SEM || USE_WIN32_SEM
int ret;
#endif
@@ -417,6 +469,11 @@
DISPATCH_SEMAPHORE_VERIFY_RET(ret);
} while (--rval);
#endif
+#if USE_WIN32_SEM
+ // Signal the semaphore.
+ ret = ReleaseSemaphore(dsema->dsema_waiter_handle, 1, NULL);
+ dispatch_assume(ret);
+#endif
}
while (head) {
dispatch_async_f(head->dsn_queue, head->dsn_ctxt, head->dsn_func);
@@ -440,10 +497,11 @@
#if USE_MACH_SEM
mach_timespec_t _timeout;
kern_return_t kr;
- uint64_t nsec;
#endif
#if USE_POSIX_SEM
struct timespec _timeout;
+#endif
+#if USE_POSIX_SEM || USE_WIN32_SEM
int ret;
#endif
long orig;
@@ -456,7 +514,7 @@
// Mach semaphores appear to sometimes spuriously wake up. Therefore,
// we keep a parallel count of the number of times a Mach semaphore is
// signaled (6880961).
- dispatch_atomic_inc(&dsema->dsema_group_waiters);
+ (void)dispatch_atomic_inc(&dsema->dsema_group_waiters);
// check the values again in case we need to wake any threads
if (dsema->dsema_value == dsema->dsema_orig) {
return _dispatch_group_wake(dsema);
@@ -478,6 +536,7 @@
default:
#if USE_MACH_SEM
do {
+ uint64_t nsec;
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);
@@ -500,6 +559,18 @@
break;
}
#endif
+#if USE_WIN32_SEM
+ do {
+ uint64_t nsec;
+ DWORD msec;
+ nsec = _dispatch_timeout(timeout);
+ msec = (DWORD)(nsec / (uint64_t)1000000);
+ ret = WaitForSingleObject(dsema->dsema_waiter_handle, msec);
+ } while (ret != WAIT_OBJECT_0 && ret != WAIT_TIMEOUT);
+ if (ret == WAIT_TIMEOUT) {
+ break;
+ }
+#endif /* USE_WIN32_SEM */
// Fall through and try to undo the earlier change to dsema->dsema_group_waiters
case DISPATCH_TIME_NOW:
while ((orig = dsema->dsema_group_waiters)) {
@@ -507,7 +578,7 @@
#if USE_MACH_SEM
return KERN_OPERATION_TIMED_OUT;
#endif
-#if USE_POSIX_SEM
+#if USE_POSIX_SEM || USE_WIN32_SEM
errno = ETIMEDOUT;
return -1;
#endif
@@ -528,6 +599,12 @@
} while (ret == -1 && errno == EINTR);
DISPATCH_SEMAPHORE_VERIFY_RET(ret);
#endif
+#if USE_WIN32_SEM
+ do {
+ ret = WaitForSingleObject(dsema->dsema_waiter_handle, INFINITE);
+ } while (ret != WAIT_OBJECT_0);
+#endif
+
break;
}
@@ -546,7 +623,7 @@
#if USE_MACH_SEM
return KERN_OPERATION_TIMED_OUT;
#endif
-#if USE_POSIX_SEM
+#if USE_POSIX_SEM || USE_WIN32_SEM
errno = ETIMEDOUT;
return (-1);
#endif
@@ -569,7 +646,7 @@
struct dispatch_sema_notify_s *dsn, *prev;
// FIXME -- this should be updated to use the continuation cache
- while (!(dsn = malloc(sizeof(*dsn)))) {
+ while (!(dsn = (struct dispatch_sema_notify_s *)malloc(sizeof(*dsn)))) {
sleep(1);
}
@@ -579,7 +656,7 @@
dsn->dsn_func = func;
_dispatch_retain(dq);
- prev = dispatch_atomic_xchg(&dsema->dsema_notify_tail, dsn);
+ prev = (struct dispatch_sema_notify_s *)dispatch_atomic_xchg(&dsema->dsema_notify_tail, dsn);
if (fastpath(prev)) {
prev->dsn_next = dsn;
} else {
@@ -619,7 +696,15 @@
ret = sem_destroy(&dsema->dsema_sem);
DISPATCH_SEMAPHORE_VERIFY_RET(ret);
#endif
-
+#if USE_WIN32_SEM
+ if (dsema->dsema_handle) {
+ CloseHandle(dsema->dsema_handle);
+ }
+ if (dsema->dsema_waiter_handle) {
+ CloseHandle(dsema->dsema_waiter_handle);
+ }
+#endif
+
_dispatch_dispose(dsema);
}
@@ -655,7 +740,10 @@
_dispatch_retain(dg);
dispatch_group_enter(dg);
- dc = _dispatch_continuation_alloc_cacheonly() ?: _dispatch_continuation_alloc_from_heap();
+ dc = _dispatch_continuation_alloc_cacheonly();
+ if (dc == NULL) {
+ dc = _dispatch_continuation_alloc_from_heap();
+ }
dc->do_vtable = (void *)(DISPATCH_OBJ_ASYNC_BIT|DISPATCH_OBJ_GROUP_BIT);
dc->dc_func = func;
Modified: trunk/src/semaphore_internal.h
===================================================================
--- trunk/src/semaphore_internal.h 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/semaphore_internal.h 2010-10-24 08:25:52 UTC (rev 192)
@@ -39,13 +39,16 @@
long dsema_value;
long dsema_orig;
size_t dsema_sent_ksignals;
-#if USE_MACH_SEM && USE_POSIX_SEM
+#if (USE_MACH_SEM + USE_POSIX_SEM + USE_WIN32_SEM) > 1
#error "Too many supported semaphore types"
#elif USE_MACH_SEM
semaphore_t dsema_port;
semaphore_t dsema_waiter_port;
#elif USE_POSIX_SEM
sem_t dsema_sem;
+#elif USE_WIN32_SEM
+ HANDLE dsema_handle;
+ HANDLE dsema_waiter_handle;
#else
#error "No supported semaphore type"
#endif
Modified: trunk/src/shims/time.c
===================================================================
--- trunk/src/shims/time.c 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/shims/time.c 2010-10-24 08:25:52 UTC (rev 192)
@@ -20,17 +20,23 @@
#include "internal.h"
-// for architectures that don't always return mach_absolute_time() in nanoseconds
-#if !(defined(__i386__) || defined(__x86_64__) || !defined(HAVE_MACH_ABSOLUTE_TIME))
+#if !(defined(__i386__) || defined(__x86_64__)) || !HAVE_MACH_ABSOLUTE_TIME
_dispatch_host_time_data_s _dispatch_host_time_data;
void
_dispatch_get_host_time_init(void *context __attribute__((unused)))
{
+#if HAVE_MACH_ABSOLUTE_TIME
mach_timebase_info_data_t tbi;
(void)dispatch_assume_zero(mach_timebase_info(&tbi));
_dispatch_host_time_data.frac = tbi.numer;
_dispatch_host_time_data.frac /= tbi.denom;
_dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom);
+#elif TARGET_OS_WIN32
+ LARGE_INTEGER freq;
+ dispatch_assume(QueryPerformanceFrequency(&freq));
+ _dispatch_host_time_data.frac = (long double)NSEC_PER_SEC / (long double)freq.QuadPart;
+ _dispatch_host_time_data.ratio_1_to_1 = (freq.QuadPart == 1);
+#endif /* TARGET_OS_WIN32 */
}
#endif
Modified: trunk/src/shims/time.h
===================================================================
--- trunk/src/shims/time.h 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/shims/time.h 2010-10-24 08:25:52 UTC (rev 192)
@@ -31,8 +31,19 @@
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#endif
-#if defined(__i386__) || defined(__x86_64__) || !defined(HAVE_MACH_ABSOLUTE_TIME)
-// these architectures always return mach_absolute_time() in nanoseconds
+uint64_t _dispatch_get_nanoseconds(void);
+
+#if TARGET_OS_WIN32
+static inline unsigned int
+sleep(unsigned int seconds)
+{
+ Sleep(seconds * 1000); // milliseconds
+ return 0;
+}
+#endif
+
+#if (defined(__i386__) || defined(__x86_64__)) && HAVE_MACH_ABSOLUTE_TIME
+// x86 currently implements mach time in nanoseconds; this is NOT likely to change
#define _dispatch_time_mach2nano(x) (x)
#define _dispatch_time_nano2mach(x) (x)
#else
@@ -84,6 +95,12 @@
{
#if HAVE_MACH_ABSOLUTE_TIME
return mach_absolute_time();
+#elif TARGET_OS_WIN32
+ LARGE_INTEGER now;
+ if (!QueryPerformanceCounter(&now)) {
+ return 0;
+ }
+ return now.QuadPart;
#else
struct timespec ts;
int ret;
Modified: trunk/src/time.c
===================================================================
--- trunk/src/time.c 2010-10-24 07:29:08 UTC (rev 191)
+++ trunk/src/time.c 2010-10-24 08:25:52 UTC (rev 192)
@@ -23,12 +23,22 @@
uint64_t
_dispatch_get_nanoseconds(void)
{
+#if !TARGET_OS_WIN32
struct timeval now;
int r = gettimeofday(&now, NULL);
dispatch_assert_zero(r);
dispatch_assert(sizeof(NSEC_PER_SEC) == 8);
dispatch_assert(sizeof(NSEC_PER_USEC) == 8);
return now.tv_sec * NSEC_PER_SEC + now.tv_usec * NSEC_PER_USEC;
+#else /* TARGET_OS_WIN32 */
+ // FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC).
+ FILETIME ft;
+ ULARGE_INTEGER li;
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ return li.QuadPart * 100ull;
+#endif /* TARGET_OS_WIN32 */
}
dispatch_time_t
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20101024/295df262/attachment-0001.html>
More information about the libdispatch-changes
mailing list