summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authordas <das>2007-03-07 23:43:13 (GMT)
committerdas <das>2007-03-07 23:43:13 (GMT)
commit5e46f127214e62bad14a33d4d4be75a51589fa57 (patch)
tree4730bde23b742f938f59329a6f4313eba9e3e660 /macosx
parent29a248eec39dd3387355e3b63efa17b1d3edec69 (diff)
downloadtcl-5e46f127214e62bad14a33d4d4be75a51589fa57.zip
tcl-5e46f127214e62bad14a33d4d4be75a51589fa57.tar.gz
tcl-5e46f127214e62bad14a33d4d4be75a51589fa57.tar.bz2
* 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
Diffstat (limited to 'macosx')
-rw-r--r--macosx/Tcl-Common.xcconfig9
-rw-r--r--macosx/Tcl.xcodeproj/default.pbxuser1
-rw-r--r--macosx/Tcl.xcodeproj/project.pbxproj2
-rw-r--r--macosx/tclMacOSXNotify.c78
4 files changed, 75 insertions, 15 deletions
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(&notifierLock)
#define UNLOCK_NOTIFIER SpinLockUnlock(&notifierLock)
+#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(&notifierInitLock)
+#undef LOCK_NOTIFIER
+#define LOCK_NOTIFIER SpinLockLockDbg(&notifierLock)
+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) {
/*