summaryrefslogtreecommitdiffstats
path: root/macosx/tclMacOSXNotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tclMacOSXNotify.c')
-rw-r--r--macosx/tclMacOSXNotify.c41
1 files changed, 30 insertions, 11 deletions
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) {
/*