From 5e46f127214e62bad14a33d4d4be75a51589fa57 Mon Sep 17 00:00:00 2001 From: das Date: Wed, 7 Mar 2007 23:43:13 +0000 Subject: * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks. * macosx/Tcl.xcodeproj/project.pbxproj: ensure gcc version used by * macosx/Tcl.xcodeproj/default.pbxuser: Xcode and configure/make are * macosx/Tcl-Common.xcconfig: consistent and independent of gcc_select default and CC env var; fixes for Xcode 3.0. * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check. * unix/configure: autoconf-2.59 --- ChangeLog | 14 ++++++- macosx/Tcl-Common.xcconfig | 9 +++-- macosx/Tcl.xcodeproj/default.pbxuser | 1 + macosx/Tcl.xcodeproj/project.pbxproj | 2 +- macosx/tclMacOSXNotify.c | 78 +++++++++++++++++++++++++++++++----- unix/configure | 2 +- unix/tcl.m4 | 2 +- 7 files changed, 90 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 780657e..20756da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-03-07 Daniel Steffen + + * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks. + + * macosx/Tcl.xcodeproj/project.pbxproj: ensure gcc version used by + * macosx/Tcl.xcodeproj/default.pbxuser: Xcode and configure/make are + * macosx/Tcl-Common.xcconfig: consistent and independent of + gcc_select default and CC env var; fixes for Xcode 3.0. + + * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check. + * unix/configure: autoconf-2.59 + 2007-03-07 Don Porter * generic/tclCmdIL.c (TclLindex*): Rewrites to make efficient private @@ -2863,7 +2875,7 @@ of a real windows service shell. ****************************************************************** - *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2005" *** + *** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005" *** *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" *** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** diff --git a/macosx/Tcl-Common.xcconfig b/macosx/Tcl-Common.xcconfig index 64c77e0..abc1792 100644 --- a/macosx/Tcl-Common.xcconfig +++ b/macosx/Tcl-Common.xcconfig @@ -9,7 +9,7 @@ // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// RCS: @(#) $Id: Tcl-Common.xcconfig,v 1.1 2007/01/28 01:42:05 das Exp $ +// RCS: @(#) $Id: Tcl-Common.xcconfig,v 1.2 2007/03/07 23:43:13 das Exp $ // HEADER_SEARCH_PATHS = $(DERIVED_FILE_DIR)/tcl $(HEADER_SEARCH_PATHS) @@ -19,8 +19,11 @@ GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tcl/tclConfig.h GCC_GENERATE_DEBUGGING_SYMBOLS = YES GCC_NO_COMMON_BLOCKS = YES GCC_DYNAMIC_NO_PIC = YES -WARNING_CFLAGS_GCC3 = -Wall -Wno-implicit-int -Wno-unused-parameter -Wno-deprecated-declarations $(WARNING_CFLAGS) -WARNING_CFLAGS = -Wextra -Wno-missing-field-initializers $(WARNING_CFLAGS_GCC3) +GCC = /usr/bin/gcc +GCC_VERSION = 4.0 +CC = $(GCC)-$(GCC_VERSION) +WARNING_CFLAGS_GCC3 = -Wall -Wno-implicit-int -Wno-unused-parameter -Wno-deprecated-declarations +WARNING_CFLAGS = -Wextra -Wno-missing-field-initializers $(WARNING_CFLAGS_GCC3) $(WARNING_CFLAGS) BINDIR = $(PREFIX)/bin CFLAGS = $(CFLAGS) CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS) diff --git a/macosx/Tcl.xcodeproj/default.pbxuser b/macosx/Tcl.xcodeproj/default.pbxuser index 2f2b53a..960d3d6 100644 --- a/macosx/Tcl.xcodeproj/default.pbxuser +++ b/macosx/Tcl.xcodeproj/default.pbxuser @@ -16,6 +16,7 @@ }; sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */; userBuildSettings = { + GCC = /usr/bin/gcc; SYMROOT = "${SRCROOT}/../../build/tcl"; }; }; diff --git a/macosx/Tcl.xcodeproj/project.pbxproj b/macosx/Tcl.xcodeproj/project.pbxproj index b578176..37e921e 100644 --- a/macosx/Tcl.xcodeproj/project.pbxproj +++ b/macosx/Tcl.xcodeproj/project.pbxproj @@ -2409,6 +2409,7 @@ F9DB621F0B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = { isa = XCBuildConfiguration; buildSettings = { + LDFLAGS = "-force_cpusubtype_ALL $(LDFLAGS)"; PRODUCT_NAME = tclsh; }; name = ReleasePPC10.3.9SDK; @@ -2452,7 +2453,6 @@ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = ppc; - CC = "$(CC)-$(GCC_VERSION)"; CFLAGS = "$(PER_ARCH_CFLAGS_ppc) -fconstant-cfstrings $(CFLAGS)"; CPPFLAGS = "-arch ppc -D__CONSTANT_CFSTRINGS__ -DMAC_OS_X_VERSION_MIN_REQUIRED=1020 -nostdinc -isystem $(SDKROOT)/usr/include/gcc/darwin/$(GCC_VERSION) -isystem $(SDKROOT)/usr/include -F$(SDKROOT)/System/Library/Frameworks"; DEBUG_INFORMATION_FORMAT = stabs; diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c index af2fa65..ecd78ae 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.12 2007/01/19 01:03:59 das Exp $ + * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.13 2007/03/07 23:43:13 das Exp $ */ #include "tclInt.h" @@ -149,11 +149,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) @@ -173,27 +174,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 /* @@ -201,10 +212,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 */ @@ -212,8 +226,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 @@ -224,6 +238,37 @@ static OSSpinLock notifierLock = 0; #define LOCK_NOTIFIER SpinLockLock(¬ifierLock) #define UNLOCK_NOTIFIER SpinLockUnlock(¬ifierLock) +#ifdef TCL_MAC_DEBUG_NOTIFIER +/* + * Debug version of SpinLockLock that logs the time spent waiting for the lock + */ + +#define SpinLockLockDbg(p) if(!SpinLockTry(p)) { \ + Tcl_WideInt s = TclpGetWideClicks(), e; \ + SpinLockLock(p); e = TclpGetWideClicks(); \ + fprintf(notifierLog, "tclMacOSXNotify.c:" \ + "%4d: thread %10p waited on %s for " \ + "%8llu ns\n", __LINE__, pthread_self(), \ + #p, TclpWideClicksToNanoseconds(e-s)); \ + fflush(notifierLog); \ + } +#undef LOCK_NOTIFIER_INIT +#define LOCK_NOTIFIER_INIT SpinLockLockDbg(¬ifierInitLock) +#undef LOCK_NOTIFIER +#define LOCK_NOTIFIER SpinLockLockDbg(¬ifierLock) +static FILE *notifierLog = stderr; +#ifndef NOTIFIER_LOG +#define NOTIFIER_LOG "/tmp/tclMacOSXNotify.log" +#endif +#define OPEN_NOTIFIER_LOG if (notifierLog == stderr) { \ + notifierLog = fopen(NOTIFIER_LOG, "a"); \ + } +#define CLOSE_NOTIFIER_LOG if (notifierLog != stderr) { \ + fclose(notifierLog); \ + notifierLog = stderr; \ + } +#endif /* TCL_MAC_DEBUG_NOTIFIER */ + /* * The pollState bits * POLL_WANT is set by each thread before it waits on its condition @@ -386,6 +431,9 @@ Tcl_InitNotifier(void) */ notifierThread = 0; +#ifdef TCL_MAC_DEBUG_NOTIFIER + OPEN_NOTIFIER_LOG; +#endif } notifierCount++; UNLOCK_NOTIFIER_INIT; @@ -456,6 +504,9 @@ Tcl_FinalizeNotifier( close(receivePipe); triggerPipe = -1; +#ifdef TCL_MAC_DEBUG_NOTIFIER + CLOSE_NOTIFIER_LOG; +#endif } UNLOCK_NOTIFIER_INIT; @@ -859,6 +910,9 @@ Tcl_WaitForEvent( */ LOCK_NOTIFIER_INIT; + if (!notifierCount) { + Tcl_Panic("Tcl_WaitForEvent: notifier not initialized"); + } if (!notifierThread) { int result; pthread_attr_t attr; @@ -882,7 +936,9 @@ Tcl_WaitForEvent( */ LOCK_NOTIFIER; - + if (!tsdPtr->runLoop) { + Tcl_Panic("Tcl_WaitForEvent: CFRunLoop not initialized"); + } waitForFiles = (tsdPtr->numFdBits > 0); if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) { /* diff --git a/unix/configure b/unix/configure index 5cc036e..de0c514 100755 --- a/unix/configure +++ b/unix/configure @@ -7662,7 +7662,7 @@ echo "${ECHO_T}$tcl_cv_ld_single_module" >&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 "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5 diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 1ca5af3..d2e82c6 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1656,7 +1656,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