From 3550b2068c9275350ca9f9ab2536ff8bf09ec1fe Mon Sep 17 00:00:00 2001 From: das Date: Wed, 7 Mar 2007 23:44:32 +0000 Subject: * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks. * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check. * unix/configure: autoconf-2.13 --- ChangeLog | 7 +++++++ macosx/tclMacOSXNotify.c | 41 ++++++++++++++++++++++++++++++----------- unix/configure | 2 +- unix/tcl.m4 | 2 +- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e8a2d0..e82d508 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-03-07 Daniel Steffen + + * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks. + + * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check. + * unix/configure: autoconf-2.13 + 2007-03-01 Donal K. Fellows * generic/tclCompCmds.c (TclCompileForeachCmd): Prevent an unexpected diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c index 3c89d20..8a5fe0f 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.1.2.10 2007/01/19 01:05:50 das Exp $ + * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.1.2.11 2007/03/07 23:44:33 das Exp $ */ #include "tclInt.h" @@ -150,11 +150,12 @@ static int triggerPipe = -1; static int receivePipe = -1; /* Output end of triggerPipe */ /* - * We use Darwin-native spinlocks instead of pthread mutexes for notifier - * locking: this radically simplifies the implementation and lowers overhead. - * Note that these are not pure spinlocks, they employ various strategies to - * back off, making them immune to most priority-inversion livelocks (c.f. man - * 3 OSSpinLockLock). + * We use the Darwin-native spinlock API rather than pthread mutexes for + * notifier locking: this radically simplifies the implementation and lowers + * overhead. Note that these are not pure spinlocks, they employ various + * strategies to back off and relinquish the processor, making them immune to + * most priority-inversion livelocks (c.f. 'man 3 OSSpinLockLock' and Darwin + * sources: xnu/osfmk/{ppc,i386}/commpage/spinlocks.s). */ #if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK) @@ -174,27 +175,37 @@ static int receivePipe = -1; /* Output end of triggerPipe */ #else #define VOLATILE #endif +#ifndef bool +#define bool int +#endif extern void OSSpinLockLock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void OSSpinLockUnlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; +extern bool OSSpinLockTry(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void _spin_lock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void _spin_unlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; +extern bool _spin_lock_try(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; static void (* lockLock)(VOLATILE OSSpinLock *lock) = NULL; static void (* lockUnlock)(VOLATILE OSSpinLock *lock) = NULL; +static bool (* lockTry)(VOLATILE OSSpinLock *lock) = NULL; #undef VOLATILE static pthread_once_t spinLockLockInitControl = PTHREAD_ONCE_INIT; static void SpinLockLockInit(void) { lockLock = OSSpinLockLock != NULL ? OSSpinLockLock : _spin_lock; lockUnlock = OSSpinLockUnlock != NULL ? OSSpinLockUnlock : _spin_unlock; + lockTry = OSSpinLockTry != NULL ? OSSpinLockTry : _spin_lock_try; if (lockLock == NULL || lockUnlock == NULL) { Tcl_Panic("SpinLockLockInit: no spinlock API available"); } } #define SpinLockLock(p) lockLock(p) #define SpinLockUnlock(p) lockUnlock(p) +#define SpinLockTry(p) lockTry(p) #else #define SpinLockLock(p) OSSpinLockLock(p) #define SpinLockUnlock(p) OSSpinLockUnlock(p) +#define SpinLockTry(p) OSSpinLockTry(p) #endif /* HAVE_WEAK_IMPORT */ +#define SPINLOCK_INIT OS_SPINLOCK_INIT #else /* @@ -202,10 +213,13 @@ static void SpinLockLockInit(void) { */ typedef uint32_t OSSpinLock; -extern void _spin_lock(OSSpinLock *lock); -extern void _spin_unlock(OSSpinLock *lock); +extern void _spin_lock(OSSpinLock *lock); +extern void _spin_unlock(OSSpinLock *lock); +extern int _spin_lock_try(OSSpinLock *lock); #define SpinLockLock(p) _spin_lock(p) #define SpinLockUnlock(p) _spin_unlock(p) +#define SpinLockTry(p) _spin_lock_try(p) +#define SPINLOCK_INIT 0 #endif /* HAVE_LIBKERN_OSATOMIC_H && HAVE_OSSPINLOCKLOCK */ @@ -213,8 +227,8 @@ extern void _spin_unlock(OSSpinLock *lock); * These spinlocks lock access to the global notifier state. */ -static OSSpinLock notifierInitLock = 0; -static OSSpinLock notifierLock = 0; +static OSSpinLock notifierInitLock = SPINLOCK_INIT; +static OSSpinLock notifierLock = SPINLOCK_INIT; /* * Macros abstracting notifier locking/unlocking @@ -839,6 +853,9 @@ Tcl_WaitForEvent(timePtr) */ LOCK_NOTIFIER_INIT; + if (!notifierCount) { + Tcl_Panic("Tcl_WaitForEvent: notifier not initialized"); + } if (!notifierThread) { int result; pthread_attr_t attr; @@ -862,7 +879,9 @@ Tcl_WaitForEvent(timePtr) */ LOCK_NOTIFIER; - + if (!tsdPtr->runLoop) { + Tcl_Panic("Tcl_WaitForEvent: CFRunLoop not initialized"); + } waitForFiles = (tsdPtr->numFdBits > 0); if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) { /* diff --git a/unix/configure b/unix/configure index 317eb2a..0ae6764 100755 --- a/unix/configure +++ b/unix/configure @@ -3588,7 +3588,7 @@ echo "$ac_t""$tcl_cv_ld_single_module" 1>&6 DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ - "`echo "${CFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4 && \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4 && \ LDFLAGS="$LDFLAGS -prebind" LDFLAGS="$LDFLAGS -headerpad_max_install_names" echo $ac_n "checking if ld accepts -search_paths_first flag""... $ac_c" 1>&6 diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 24a0899..cf27917 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1622,7 +1622,7 @@ dnl AC_CHECK_TOOL(AR, ar) DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ - "`echo "${CFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4 && \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4 && \ LDFLAGS="$LDFLAGS -prebind" LDFLAGS="$LDFLAGS -headerpad_max_install_names" AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [ -- cgit v0.12