From d70383944a28777ea679b1e1b4be38c2a42b3960 Mon Sep 17 00:00:00 2001 From: das Date: Mon, 21 Aug 2006 01:08:03 +0000 Subject: * macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is already running (e.g. if Tcl_WaitForEvent was called recursively), re-run it in a custom run loop mode containing only the source for the notifier thread, otherwise wakeups from other sources added to the common run loop modes might get lost. * unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin, pthread_cond_timedwait() appears to have a bug that causes it to wait forever when passed an absolute time which has already been exceeded by the system time; as a workaround, when given a very brief timeout, just do a poll on that platform. [Bug 1457797] --- ChangeLog | 22 ++++++++++++++++++++++ macosx/tclMacOSXNotify.c | 26 ++++++++++++++++++++++++-- unix/tclUnixNotfy.c | 14 ++++++++++++-- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3debe51..662137d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2006-08-21 Daniel Steffen + + * macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is + already running (e.g. if Tcl_WaitForEvent was called recursively), + re-run it in a custom run loop mode containing only the source for the + notifier thread, otherwise wakeups from other sources added to the + common run loop modes might get lost. + + * unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin, + pthread_cond_timedwait() appears to have a bug that causes it to wait + forever when passed an absolute time which has already been exceeded by + the system time; as a workaround, when given a very brief timeout, just + do a poll on that platform. [Bug 1457797] + + * generic/tclClock.c (ClockClicksObjCmd): add support for Darwin + * generic/tclCmdMZ.c (Tcl_TimeObjCmd): nanosecond resolution timer + * generic/tclInt.h: to [clock clicks] and [time] + * unix/configure.in (Darwin): when TCL_WIDE_CLICKS defined. + * unix/tclUnixTime.c (TclpGetWideClicks, TclpWideClicksToNanoseconds): + * unix/configure: autoconf-2.59 + * unix/tclConfig.h.in: autoheader-2.59 + 2006-08-18 Daniel Steffen * unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c index 6dfb379..73b1c92 100644 --- a/macosx/tclMacOSXNotify.c +++ b/macosx/tclMacOSXNotify.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.9 2006/08/10 12:15:32 dkf Exp $ + * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.10 2006/08/21 01:08:03 das Exp $ */ #include "tclInt.h" @@ -237,6 +237,14 @@ static OSSpinLock notifierLock = 0; static pthread_t notifierThread; /* + * Custom run loop mode containing only the run loop source for the + * notifier thread. + */ + +static const CFStringRef tclEventsOnlyRunLoopMode = + CFSTR("com.tcltk.tclEventsOnlyRunLoopMode"); + +/* * Static routines defined in this file. */ @@ -304,6 +312,7 @@ Tcl_InitNotifier(void) Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource"); } CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes); + CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode); tsdPtr->runLoopSource = runLoopSource; tsdPtr->runLoop = runLoop; } @@ -897,14 +906,27 @@ Tcl_WaitForEvent( if (!tsdPtr->eventReady) { CFTimeInterval waitTime; + CFStringRef runLoopMode; if (myTimePtr == NULL) { waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */ } else { waitTime = myTimePtr->sec + 1.0e-6 * myTimePtr->usec; } + /* + * If the run loop is already running (e.g. if Tcl_WaitForEvent was + * called recursively), re-run it in a custom run loop mode containing + * only the source for the notifier thread, otherwise wakeups from other + * sources added to the common run loop modes might get lost. + */ + if ((runLoopMode = CFRunLoopCopyCurrentMode(tsdPtr->runLoop))) { + CFRelease(runLoopMode); + runLoopMode = tclEventsOnlyRunLoopMode; + } else { + runLoopMode = kCFRunLoopDefaultMode; + } UNLOCK_NOTIFIER; - CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, TRUE); + CFRunLoopRunInMode(runLoopMode, waitTime, TRUE); LOCK_NOTIFIER; } tsdPtr->eventReady = 0; diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index 0a405ce..2574015 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixNotfy.c,v 1.31 2006/08/10 12:15:32 dkf Exp $ + * RCS: @(#) $Id: tclUnixNotfy.c,v 1.32 2006/08/21 01:08:03 das Exp $ */ #include "tclInt.h" @@ -740,7 +740,17 @@ Tcl_WaitForEvent( Tcl_MutexLock(¬ifierMutex); waitForFiles = (tsdPtr->numFdBits > 0); - if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) { + if (myTimePtr != NULL && myTimePtr->sec == 0 && (myTimePtr->usec == 0 +#if defined(__APPLE__) && defined(__LP64__) + /* + * On 64-bit Darwin, pthread_cond_timedwait() appears to have a bug + * that causes it to wait forever when passed an absolute time which + * has already been exceeded by the system time; as a workaround, + * when given a very brief timeout, just do a poll. [Bug 1457797] + */ + || myTimePtr->usec < 10 +#endif + )) { /* * Cannot emulate a polling select with a polling condition variable. * Instead, pretend to wait for files and tell the notifier thread -- cgit v0.12