summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
Diffstat (limited to 'macosx')
-rw-r--r--macosx/tclMacOSXFCmd.c134
-rw-r--r--macosx/tclMacOSXNotify.c791
2 files changed, 468 insertions, 457 deletions
diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c
index c902a28..d1bab28 100644
--- a/macosx/tclMacOSXFCmd.c
+++ b/macosx/tclMacOSXFCmd.c
@@ -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: tclMacOSXFCmd.c,v 1.15 2008/10/26 18:50:06 dkf Exp $
+ * RCS: @(#) $Id: tclMacOSXFCmd.c,v 1.16 2009/01/09 11:21:46 dkf Exp $
*/
#include "tclInt.h"
@@ -27,19 +27,22 @@
#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
/* Support for weakly importing copyfile. */
#define WEAK_IMPORT_COPYFILE
-extern int copyfile(const char *from, const char *to, copyfile_state_t state,
- copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE;
+extern int copyfile(const char *from, const char *to,
+ copyfile_state_t state, copyfile_flags_t flags)
+ WEAK_IMPORT_ATTRIBUTE;
#endif /* HAVE_WEAK_IMPORT */
#else /* HAVE_COPYFILE_H */
-int copyfile(const char *from, const char *to, void *state, uint32_t flags);
+int copyfile(const char *from, const char *to,
+ void *state, uint32_t flags);
#define COPYFILE_ACL (1<<0)
#define COPYFILE_XATTR (1<<2)
#define COPYFILE_NOFOLLOW_SRC (1<<18)
#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
/* Support for weakly importing copyfile. */
#define WEAK_IMPORT_COPYFILE
-extern int copyfile(const char *from, const char *to, void *state,
- uint32_t flags) WEAK_IMPORT_ATTRIBUTE;
+extern int copyfile(const char *from, const char *to,
+ void *state, uint32_t flags)
+ WEAK_IMPORT_ATTRIBUTE;
#endif /* HAVE_WEAK_IMPORT */
#endif /* HAVE_COPYFILE_H */
#endif /* HAVE_COPYFILE */
@@ -391,75 +394,75 @@ TclMacOSXCopyFileAttributes(
if (copyfile != NULL) {
#endif
#ifdef HAVE_COPYFILE
- if (copyfile(src, dst, NULL, COPYFILE_XATTR |
- (S_ISLNK(statBufPtr->st_mode) ? COPYFILE_NOFOLLOW_SRC :
- COPYFILE_ACL)) < 0) {
- return TCL_ERROR;
- }
- return TCL_OK;
+ if (copyfile(src, dst, NULL, COPYFILE_XATTR |
+ (S_ISLNK(statBufPtr->st_mode)
+ ? COPYFILE_NOFOLLOW_SRC : COPYFILE_ACL)) < 0) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
#endif /* HAVE_COPYFILE */
#ifdef WEAK_IMPORT_COPYFILE
} else {
#endif
#if !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)
#ifdef HAVE_GETATTRLIST
- struct attrlist alist;
- fileinfobuf finfo;
- off_t *rsrcForkSize = (off_t *) &finfo.data;
-
- bzero(&alist, sizeof(struct attrlist));
- alist.bitmapcount = ATTR_BIT_MAP_COUNT;
- alist.commonattr = ATTR_CMN_FNDRINFO;
-
- if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
- return TCL_ERROR;
- }
+ struct attrlist alist;
+ fileinfobuf finfo;
+ off_t *rsrcForkSize = (off_t *) &finfo.data;
- if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
- return TCL_ERROR;
- }
-
- if (!S_ISDIR(statBufPtr->st_mode)) {
- /*
- * Only copy non-empty resource fork.
- */
-
- alist.commonattr = 0;
- alist.fileattr = ATTR_FILE_RSRCLENGTH;
+ bzero(&alist, sizeof(struct attrlist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ alist.commonattr = ATTR_CMN_FNDRINFO;
if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
return TCL_ERROR;
}
- if(*rsrcForkSize > 0) {
- int result;
- Tcl_DString ds_src, ds_dst;
+ if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
+ return TCL_ERROR;
+ }
+ if (!S_ISDIR(statBufPtr->st_mode)) {
/*
- * Construct paths to resource forks.
+ * Only copy non-empty resource fork.
*/
- Tcl_DStringInit(&ds_src);
- Tcl_DStringAppend(&ds_src, src, -1);
- Tcl_DStringAppend(&ds_src, _PATH_RSRCFORKSPEC, -1);
- Tcl_DStringInit(&ds_dst);
- Tcl_DStringAppend(&ds_dst, dst, -1);
- Tcl_DStringAppend(&ds_dst, _PATH_RSRCFORKSPEC, -1);
+ alist.commonattr = 0;
+ alist.fileattr = ATTR_FILE_RSRCLENGTH;
- result = TclUnixCopyFile(Tcl_DStringValue(&ds_src),
- Tcl_DStringValue(&ds_dst), statBufPtr, 1);
+ if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
+ return TCL_ERROR;
+ }
- Tcl_DStringFree(&ds_src);
- Tcl_DStringFree(&ds_dst);
+ if (*rsrcForkSize > 0) {
+ int result;
+ Tcl_DString ds_src, ds_dst;
- if (result != 0) {
- return TCL_ERROR;
+ /*
+ * Construct paths to resource forks.
+ */
+
+ Tcl_DStringInit(&ds_src);
+ Tcl_DStringAppend(&ds_src, src, -1);
+ Tcl_DStringAppend(&ds_src, _PATH_RSRCFORKSPEC, -1);
+ Tcl_DStringInit(&ds_dst);
+ Tcl_DStringAppend(&ds_dst, dst, -1);
+ Tcl_DStringAppend(&ds_dst, _PATH_RSRCFORKSPEC, -1);
+
+ result = TclUnixCopyFile(Tcl_DStringValue(&ds_src),
+ Tcl_DStringValue(&ds_dst), statBufPtr, 1);
+
+ Tcl_DStringFree(&ds_src);
+ Tcl_DStringFree(&ds_dst);
+
+ if (result != 0) {
+ return TCL_ERROR;
+ }
}
}
- }
- return TCL_OK;
+ return TCL_OK;
#else
- return TCL_ERROR;
+ return TCL_ERROR;
#endif /* HAVE_GETATTRLIST */
#endif /* !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) */
#ifdef WEAK_IMPORT_COPYFILE
@@ -472,13 +475,13 @@ TclMacOSXCopyFileAttributes(
*
* TclMacOSXMatchType --
*
- * This routine is used by the globbing code to check if a file
- * matches a given mac type and/or creator code.
+ * This routine is used by the globbing code to check if a file matches a
+ * given mac type and/or creator code.
*
* Results:
- * The return value is 1, 0 or -1 indicating whether the file
- * matches the given criteria, does not match them, or an error
- * occurred (in wich case an error is left in interp).
+ * The return value is 1, 0 or -1 indicating whether the file matches the
+ * given criteria, does not match them, or an error occurred (in wich
+ * case an error is left in interp).
*
* Side effects:
* None.
@@ -510,8 +513,12 @@ TclMacOSXMatchType(
!((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {
return 0;
}
- if (S_ISDIR(statBufPtr->st_mode) && (types->macType || types->macCreator)) {
- /* Directories don't support types or creators */
+ if (S_ISDIR(statBufPtr->st_mode)
+ && (types->macType || types->macCreator)) {
+ /*
+ * Directories don't support types or creators.
+ */
+
return 0;
}
if (types->macType) {
@@ -584,7 +591,8 @@ GetOSTypeFromObj(
static Tcl_Obj *
NewOSTypeObj(
- const OSType osType) /* OSType used to initialize the new object. */
+ const OSType osType) /* OSType used to initialize the new
+ * object. */
{
Tcl_Obj *objPtr;
@@ -631,8 +639,8 @@ SetOSTypeFromAny(
} else {
OSType osType;
char string[4] = {'\0','\0','\0','\0'};
- memcpy(string, Tcl_DStringValue(&ds),
- (size_t) Tcl_DStringLength(&ds));
+
+ memcpy(string, Tcl_DStringValue(&ds), (size_t)Tcl_DStringLength(&ds));
osType = (OSType) string[0] << 24 |
(OSType) string[1] << 16 |
(OSType) string[2] << 8 |
diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c
index b67ef3e..8edbda2 100644
--- a/macosx/tclMacOSXNotify.c
+++ b/macosx/tclMacOSXNotify.c
@@ -12,7 +12,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.21 2008/10/26 18:50:07 dkf Exp $
+ * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.22 2009/01/09 11:21:46 dkf Exp $
*/
#include "tclInt.h"
@@ -239,7 +239,7 @@ static OSSpinLock notifierLock = SPINLOCK_INIT;
* Debug version of SpinLockLock that logs the time spent waiting for the lock
*/
-#define SpinLockLockDbg(p) if(!SpinLockTry(p)) { \
+#define SpinLockLockDbg(p) if (!SpinLockTry(p)) { \
Tcl_WideInt s = TclpGetWideClicks(), e; \
SpinLockLock(p); e = TclpGetWideClicks(); \
fprintf(notifierLog, "tclMacOSXNotify.c:" \
@@ -313,8 +313,8 @@ static void AtForkChild(void);
#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
/* Support for weakly importing pthread_atfork. */
#define WEAK_IMPORT_PTHREAD_ATFORK
-extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
- void (*child)(void)) WEAK_IMPORT_ATTRIBUTE;
+extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
+ void (*child)(void)) WEAK_IMPORT_ATTRIBUTE;
#endif /* HAVE_WEAK_IMPORT */
/*
* On Darwin 9 and later, it is not possible to call CoreFoundation after
@@ -348,113 +348,112 @@ MODULE_SCOPE long tclMacOSXDarwinRelease;
ClientData
Tcl_InitNotifier(void)
{
+ ThreadSpecificData *tsdPtr;
+
if (tclNotifierHooks.initNotifierProc) {
return tclNotifierHooks.initNotifierProc();
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ }
- tsdPtr->eventReady = 0;
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ tsdPtr->eventReady = 0;
#ifdef WEAK_IMPORT_SPINLOCKLOCK
- /*
- * Initialize support for weakly imported spinlock API.
- */
- if (pthread_once(&spinLockLockInitControl, SpinLockLockInit)) {
- Tcl_Panic("Tcl_InitNotifier: pthread_once failed");
- }
+ /*
+ * Initialize support for weakly imported spinlock API.
+ */
+
+ if (pthread_once(&spinLockLockInitControl, SpinLockLockInit)) {
+ Tcl_Panic("Tcl_InitNotifier: pthread_once failed");
+ }
#endif
#ifndef __CONSTANT_CFSTRINGS__
- if (!tclEventsOnlyRunLoopMode) {
- tclEventsOnlyRunLoopMode = CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE);
- }
+ if (!tclEventsOnlyRunLoopMode) {
+ tclEventsOnlyRunLoopMode = CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE);
+ }
#endif
- /*
- * Initialize CFRunLoopSource and add it to CFRunLoop of this thread.
- */
+ /*
+ * Initialize CFRunLoopSource and add it to CFRunLoop of this thread.
+ */
- if (!tsdPtr->runLoop) {
- CFRunLoopRef runLoop = CFRunLoopGetCurrent();
- CFRunLoopSourceRef runLoopSource;
- CFRunLoopSourceContext runLoopSourceContext;
-
- bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
- runLoopSourceContext.info = tsdPtr;
- runLoopSource = CFRunLoopSourceCreate(NULL, 0,
- &runLoopSourceContext);
- if (!runLoopSource) {
- Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource");
- }
- CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
- CFRunLoopAddSource(runLoop, runLoopSource,
- tclEventsOnlyRunLoopMode);
- tsdPtr->runLoopSource = runLoopSource;
- tsdPtr->runLoop = runLoop;
+ if (!tsdPtr->runLoop) {
+ CFRunLoopRef runLoop = CFRunLoopGetCurrent();
+ CFRunLoopSourceRef runLoopSource;
+ CFRunLoopSourceContext runLoopSourceContext;
+
+ bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
+ runLoopSourceContext.info = tsdPtr;
+ runLoopSource = CFRunLoopSourceCreate(NULL, 0, &runLoopSourceContext);
+ if (!runLoopSource) {
+ Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource");
}
+ CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode);
+ tsdPtr->runLoopSource = runLoopSource;
+ tsdPtr->runLoop = runLoop;
+ }
- LOCK_NOTIFIER_INIT;
+ LOCK_NOTIFIER_INIT;
#ifdef HAVE_PTHREAD_ATFORK
- /*
- * Install pthread_atfork handlers to reinitialize the notifier in the
- * child of a fork.
- */
+ /*
+ * Install pthread_atfork handlers to reinitialize the notifier in the
+ * child of a fork.
+ */
- if (
+ if (
#ifdef WEAK_IMPORT_PTHREAD_ATFORK
- pthread_atfork != NULL &&
+ pthread_atfork != NULL &&
#endif
- !atForkInit) {
- int result = pthread_atfork(AtForkPrepare, AtForkParent,
- AtForkChild);
+ !atForkInit) {
+ int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);
- if (result) {
- Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
- }
- atForkInit = 1;
+ if (result) {
+ Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
}
+ atForkInit = 1;
+ }
#endif
- if (notifierCount == 0) {
- int fds[2], status;
+ if (notifierCount == 0) {
+ int fds[2], status;
- /*
- * Initialize trigger pipe.
- */
+ /*
+ * Initialize trigger pipe.
+ */
- if (pipe(fds) != 0) {
- Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe");
- }
+ if (pipe(fds) != 0) {
+ Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe");
+ }
- status = fcntl(fds[0], F_GETFL);
- status |= O_NONBLOCK;
- if (fcntl(fds[0], F_SETFL, status) < 0) {
- Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non blocking");
- }
- status = fcntl(fds[1], F_GETFL);
- status |= O_NONBLOCK;
- if (fcntl(fds[1], F_SETFL, status) < 0) {
- Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non blocking");
- }
+ status = fcntl(fds[0], F_GETFL);
+ status |= O_NONBLOCK;
+ if (fcntl(fds[0], F_SETFL, status) < 0) {
+ Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non blocking");
+ }
+ status = fcntl(fds[1], F_GETFL);
+ status |= O_NONBLOCK;
+ if (fcntl(fds[1], F_SETFL, status) < 0) {
+ Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non blocking");
+ }
- receivePipe = fds[0];
- triggerPipe = fds[1];
+ receivePipe = fds[0];
+ triggerPipe = fds[1];
- /*
- * Create notifier thread lazily in Tcl_WaitForEvent() to avoid
- * interfering with fork() followed immediately by execve()
- * (cannot execve() when more than one thread is present).
- */
+ /*
+ * Create notifier thread lazily in Tcl_WaitForEvent() to avoid
+ * interfering with fork() followed immediately by execve() (we cannot
+ * execve() when more than one thread is present).
+ */
- notifierThread = 0;
+ notifierThread = 0;
#ifdef TCL_MAC_DEBUG_NOTIFIER
- OPEN_NOTIFIER_LOG;
+ OPEN_NOTIFIER_LOG;
#endif
- }
- notifierCount++;
- UNLOCK_NOTIFIER_INIT;
-
- return (ClientData) tsdPtr;
}
+ notifierCount++;
+ UNLOCK_NOTIFIER_INIT;
+
+ return (ClientData) tsdPtr;
}
/*
@@ -479,71 +478,72 @@ void
Tcl_FinalizeNotifier(
ClientData clientData) /* Not used. */
{
+ ThreadSpecificData *tsdPtr;
+
if (tclNotifierHooks.finalizeNotifierProc) {
tclNotifierHooks.finalizeNotifierProc(clientData);
return;
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ }
- LOCK_NOTIFIER_INIT;
- notifierCount--;
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ LOCK_NOTIFIER_INIT;
+ notifierCount--;
- /*
- * If this is the last thread to use the notifier, close the notifier
- * pipe and wait for the background thread to terminate.
- */
+ /*
+ * If this is the last thread to use the notifier, close the notifier pipe
+ * and wait for the background thread to terminate.
+ */
- if (notifierCount == 0) {
- int result;
+ if (notifierCount == 0) {
+ int result;
- if (triggerPipe < 0) {
- Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
- }
+ if (triggerPipe < 0) {
+ Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
+ }
- /*
- * Send "q" message to the notifier thread so that it will
- * terminate. The notifier will return from its call to select()
- * and notice that a "q" message has arrived, it will then close
- * its side of the pipe and terminate its thread. Note the we can
- * not just close the pipe and check for EOF in the notifier thread
- * because if a background child process was created with exec,
- * select() would not register the EOF on the pipe until the child
- * processes had terminated. [Bug: 4139] [Bug: 1222872]
- */
+ /*
+ * Send "q" message to the notifier thread so that it will terminate.
+ * The notifier will return from its call to select() and notice that
+ * a "q" message has arrived, it will then close its side of the pipe
+ * and terminate its thread. Note the we can not just close the pipe
+ * and check for EOF in the notifier thread because if a background
+ * child process was created with exec, select() would not register
+ * the EOF on the pipe until the child processes had terminated. [Bug:
+ * 4139] [Bug: 1222872]
+ */
- write(triggerPipe, "q", 1);
- close(triggerPipe);
+ write(triggerPipe, "q", 1);
+ close(triggerPipe);
- if (notifierThread) {
- result = pthread_join(notifierThread, NULL);
- if (result) {
- Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread");
- }
- notifierThread = 0;
+ if (notifierThread) {
+ result = pthread_join(notifierThread, NULL);
+ if (result) {
+ Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread");
}
+ notifierThread = 0;
+ }
- close(receivePipe);
- triggerPipe = -1;
+ close(receivePipe);
+ triggerPipe = -1;
#ifdef TCL_MAC_DEBUG_NOTIFIER
- CLOSE_NOTIFIER_LOG;
+ CLOSE_NOTIFIER_LOG;
#endif
- }
- UNLOCK_NOTIFIER_INIT;
+ }
+ UNLOCK_NOTIFIER_INIT;
- LOCK_NOTIFIER; /* for concurrency with Tcl_AlertNotifier */
- if (tsdPtr->runLoop) {
- tsdPtr->runLoop = NULL;
+ LOCK_NOTIFIER; /* For concurrency with Tcl_AlertNotifier */
+ if (tsdPtr->runLoop) {
+ tsdPtr->runLoop = NULL;
- /*
- * Remove runLoopSource from all CFRunLoops and release it.
- */
+ /*
+ * Remove runLoopSource from all CFRunLoops and release it.
+ */
- CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
- CFRelease(tsdPtr->runLoopSource);
- tsdPtr->runLoopSource = NULL;
- }
- UNLOCK_NOTIFIER;
+ CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
+ CFRelease(tsdPtr->runLoopSource);
+ tsdPtr->runLoopSource = NULL;
}
+ UNLOCK_NOTIFIER;
}
/*
@@ -569,20 +569,20 @@ void
Tcl_AlertNotifier(
ClientData clientData)
{
+ ThreadSpecificData *tsdPtr = clientData;
+
if (tclNotifierHooks.alertNotifierProc) {
tclNotifierHooks.alertNotifierProc(clientData);
return;
- } else {
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
+ }
- LOCK_NOTIFIER;
- if (tsdPtr->runLoop) {
- tsdPtr->eventReady = 1;
- CFRunLoopSourceSignal(tsdPtr->runLoopSource);
- CFRunLoopWakeUp(tsdPtr->runLoop);
- }
- UNLOCK_NOTIFIER;
+ LOCK_NOTIFIER;
+ if (tsdPtr->runLoop) {
+ tsdPtr->eventReady = 1;
+ CFRunLoopSourceSignal(tsdPtr->runLoopSource);
+ CFRunLoopWakeUp(tsdPtr->runLoop);
}
+ UNLOCK_NOTIFIER;
}
/*
@@ -610,13 +610,13 @@ Tcl_SetTimer(
if (tclNotifierHooks.setTimerProc) {
tclNotifierHooks.setTimerProc(timePtr);
return;
- } else {
- /*
- * The interval timer doesn't do anything in this implementation,
- * because the only event loop is via Tcl_DoOneEvent, which passes
- * timeout values to Tcl_WaitForEvent.
- */
}
+
+ /*
+ * The interval timer doesn't do anything in this implementation, because
+ * the only event loop is via Tcl_DoOneEvent, which passes timeout values
+ * to Tcl_WaitForEvent.
+ */
}
/*
@@ -675,52 +675,54 @@ Tcl_CreateFileHandler(
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
+ ThreadSpecificData *tsdPtr;
+ FileHandler *filePtr;
+
if (tclNotifierHooks.createFileHandlerProc) {
tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
return;
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- FileHandler *filePtr;
+ }
- for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
- if (filePtr->fd == fd) {
- break;
- }
- }
- if (filePtr == NULL) {
- filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
- filePtr->fd = fd;
- filePtr->readyMask = 0;
- filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
- tsdPtr->firstFileHandlerPtr = filePtr;
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd == fd) {
+ break;
}
- filePtr->proc = proc;
- filePtr->clientData = clientData;
- filePtr->mask = mask;
+ }
+ if (filePtr == NULL) {
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Update the check masks for this file.
+ */
- if (mask & TCL_READABLE) {
- FD_SET(fd, &(tsdPtr->checkMasks.readable));
- } else {
- FD_CLR(fd, &(tsdPtr->checkMasks.readable));
- }
- if (mask & TCL_WRITABLE) {
- FD_SET(fd, &(tsdPtr->checkMasks.writable));
- } else {
- FD_CLR(fd, &(tsdPtr->checkMasks.writable));
- }
- if (mask & TCL_EXCEPTION) {
- FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
- } else {
- FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
- }
- if (tsdPtr->numFdBits <= fd) {
- tsdPtr->numFdBits = fd+1;
- }
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &(tsdPtr->checkMasks.readable));
+ } else {
+ FD_CLR(fd, &(tsdPtr->checkMasks.readable));
+ }
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &(tsdPtr->checkMasks.writable));
+ } else {
+ FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+ }
+ if (mask & TCL_EXCEPTION) {
+ FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
+ } else {
+ FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+ }
+ if (tsdPtr->numFdBits <= fd) {
+ tsdPtr->numFdBits = fd+1;
}
}
@@ -745,69 +747,71 @@ Tcl_DeleteFileHandler(
int fd) /* Stream id for which to remove callback
* function. */
{
+ FileHandler *filePtr, *prevPtr;
+ int i;
+ ThreadSpecificData *tsdPtr;
+
if (tclNotifierHooks.deleteFileHandlerProc) {
tclNotifierHooks.deleteFileHandlerProc(fd);
return;
- } else {
- FileHandler *filePtr, *prevPtr;
- int i;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- /*
- * Find the entry for the given file (and return if there isn't one).
- */
+ }
- for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
- prevPtr = filePtr, filePtr = filePtr->nextPtr) {
- if (filePtr == NULL) {
- return;
- }
- if (filePtr->fd == fd) {
- break;
- }
- }
+ tsdPtr = TCL_TSD_INIT(&dataKey);
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
- if (filePtr->mask & TCL_READABLE) {
- FD_CLR(fd, &(tsdPtr->checkMasks.readable));
- }
- if (filePtr->mask & TCL_WRITABLE) {
- FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+ for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return;
}
- if (filePtr->mask & TCL_EXCEPTION) {
- FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+ if (filePtr->fd == fd) {
+ break;
}
+ }
- /*
- * Find current max fd.
- */
+ /*
+ * Update the check masks for this file.
+ */
- if (fd+1 == tsdPtr->numFdBits) {
- tsdPtr->numFdBits = 0;
- for (i = fd-1; i >= 0; i--) {
- if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
- || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
- || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
- tsdPtr->numFdBits = i+1;
- break;
- }
+ if (filePtr->mask & TCL_READABLE) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.readable));
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+ }
+ if (filePtr->mask & TCL_EXCEPTION) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+ }
+
+ /*
+ * Find current max fd.
+ */
+
+ if (fd+1 == tsdPtr->numFdBits) {
+ tsdPtr->numFdBits = 0;
+ for (i = fd-1; i >= 0; i--) {
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+ || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+ || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
+ tsdPtr->numFdBits = i+1;
+ break;
}
}
+ }
- /*
- * Clean up information in the callback record.
- */
+ /*
+ * Clean up information in the callback record.
+ */
- if (prevPtr == NULL) {
- tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
- } else {
- prevPtr->nextPtr = filePtr->nextPtr;
- }
- ckfree((char *) filePtr);
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
}
+ ckfree((char *) filePtr);
}
/*
@@ -905,203 +909,202 @@ int
Tcl_WaitForEvent(
const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
+ FileHandler *filePtr;
+ FileHandlerEvent *fileEvPtr;
+ int mask, waitForFiles;
+ Tcl_Time myTime, *myTimePtr;
+ ThreadSpecificData *tsdPtr;
+
if (tclNotifierHooks.waitForEventProc) {
return tclNotifierHooks.waitForEventProc(timePtr);
- } else {
- FileHandler *filePtr;
- FileHandlerEvent *fileEvPtr;
- int mask;
- Tcl_Time myTime;
- int waitForFiles;
- Tcl_Time *myTimePtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ }
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ /*
+ * Set up the timeout structure. Note that if there are no events to check
+ * for, we return with a negative result rather than blocking forever.
+ */
+
+ if (timePtr != NULL) {
/*
- * Set up the timeout structure. Note that if there are no events to
- * check for, we return with a negative result rather than blocking
- * forever.
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
*/
- if (timePtr != NULL) {
- /*
- * TIP #233 (Virtualized Time). Is virtual time in effect? And do
- * we actually have something to scale? If yes to both then we call
- * the handler to do this scaling.
- */
+ myTime.sec = timePtr->sec;
+ myTime.usec = timePtr->usec;
- myTime.sec = timePtr->sec;
- myTime.usec = timePtr->usec;
+ if (myTime.sec != 0 || myTime.usec != 0) {
+ tclScaleTimeProcPtr(&myTime, tclTimeClientData);
+ }
- if (myTime.sec != 0 || myTime.usec != 0) {
- tclScaleTimeProcPtr(&myTime, tclTimeClientData);
- }
+ myTimePtr = &myTime;
+ } else {
+ myTimePtr = NULL;
+ }
- myTimePtr = &myTime;
- } else {
- myTimePtr = NULL;
+ /*
+ * Start notifier thread if necessary.
+ */
+
+ LOCK_NOTIFIER_INIT;
+ if (!notifierCount) {
+ Tcl_Panic("Tcl_WaitForEvent: notifier not initialized");
+ }
+ if (!notifierThread) {
+ int result;
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_attr_setstacksize(&attr, 60 * 1024);
+ result = pthread_create(&notifierThread, &attr,
+ (void * (*)(void *))NotifierThreadProc, NULL);
+ pthread_attr_destroy(&attr);
+ if (result || !notifierThread) {
+ Tcl_Panic("Tcl_WaitForEvent: unable to start notifier thread");
}
+ }
+ UNLOCK_NOTIFIER_INIT;
+
+ /*
+ * Place this thread on the list of interested threads, signal the
+ * notifier thread, and wait for a response or a timeout.
+ */
+ 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) {
/*
- * Start notifier thread if necessary.
+ * Cannot emulate a polling select with a polling condition variable.
+ * Instead, pretend to wait for files and tell the notifier thread
+ * what we are doing. The notifier thread makes sure it goes through
+ * select with its select mask in the same state as ours currently is.
+ * We block until that happens.
*/
- LOCK_NOTIFIER_INIT;
- if (!notifierCount) {
- Tcl_Panic("Tcl_WaitForEvent: notifier not initialized");
- }
- if (!notifierThread) {
- int result;
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setstacksize(&attr, 60 * 1024);
- result = pthread_create(&notifierThread, &attr,
- (void * (*)(void *))NotifierThreadProc, NULL);
- pthread_attr_destroy(&attr);
- if (result || !notifierThread) {
- Tcl_Panic("Tcl_WaitForEvent: unable to start notifier thread");
- }
- }
- UNLOCK_NOTIFIER_INIT;
+ waitForFiles = 1;
+ tsdPtr->pollState = POLL_WANT;
+ myTimePtr = NULL;
+ } else {
+ tsdPtr->pollState = 0;
+ }
+ if (waitForFiles) {
/*
- * Place this thread on the list of interested threads, signal the
- * notifier thread, and wait for a response or a timeout.
+ * Add the ThreadSpecificData structure of this thread to the list of
+ * ThreadSpecificData structures of all threads that are waiting on
+ * file events.
*/
- 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) {
- /*
- * Cannot emulate a polling select with a polling condition
- * variable. Instead, pretend to wait for files and tell the
- * notifier thread what we are doing. The notifier thread makes
- * sure it goes through select with its select mask in the same
- * state as ours currently is. We block until that happens.
- */
-
- waitForFiles = 1;
- tsdPtr->pollState = POLL_WANT;
- myTimePtr = NULL;
- } else {
- tsdPtr->pollState = 0;
+ tsdPtr->nextPtr = waitingListPtr;
+ if (waitingListPtr) {
+ waitingListPtr->prevPtr = tsdPtr;
}
+ tsdPtr->prevPtr = 0;
+ waitingListPtr = tsdPtr;
+ tsdPtr->onList = 1;
- if (waitForFiles) {
- /*
- * Add the ThreadSpecificData structure of this thread to the list
- * of ThreadSpecificData structures of all threads that are waiting
- * on file events.
- */
-
- tsdPtr->nextPtr = waitingListPtr;
- if (waitingListPtr) {
- waitingListPtr->prevPtr = tsdPtr;
- }
- tsdPtr->prevPtr = 0;
- waitingListPtr = tsdPtr;
- tsdPtr->onList = 1;
-
- write(triggerPipe, "", 1);
- }
+ write(triggerPipe, "", 1);
+ }
- FD_ZERO(&(tsdPtr->readyMasks.readable));
- FD_ZERO(&(tsdPtr->readyMasks.writable));
- FD_ZERO(&(tsdPtr->readyMasks.exceptional));
+ FD_ZERO(&(tsdPtr->readyMasks.readable));
+ FD_ZERO(&(tsdPtr->readyMasks.writable));
+ FD_ZERO(&(tsdPtr->readyMasks.exceptional));
- if (!tsdPtr->eventReady) {
- CFTimeInterval waitTime;
- CFStringRef runLoopMode;
+ 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(runLoopMode, waitTime, TRUE);
- LOCK_NOTIFIER;
+ if (myTimePtr == NULL) {
+ waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */
+ } else {
+ waitTime = myTimePtr->sec + 1.0e-6 * myTimePtr->usec;
}
- tsdPtr->eventReady = 0;
- if (waitForFiles && tsdPtr->onList) {
- /*
- * Remove the ThreadSpecificData structure of this thread from the
- * waiting list. Alert the notifier thread to recompute its select
- * masks - skipping this caused a hang when trying to close a pipe
- * which the notifier thread was still doing a select on.
- */
+ /*
+ * 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 (tsdPtr->prevPtr) {
- tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
- } else {
- waitingListPtr = tsdPtr->nextPtr;
- }
- if (tsdPtr->nextPtr) {
- tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
- }
- tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
- tsdPtr->onList = 0;
- write(triggerPipe, "", 1);
+ if ((runLoopMode = CFRunLoopCopyCurrentMode(tsdPtr->runLoop))) {
+ CFRelease(runLoopMode);
+ runLoopMode = tclEventsOnlyRunLoopMode;
+ } else {
+ runLoopMode = kCFRunLoopDefaultMode;
}
+ UNLOCK_NOTIFIER;
+ CFRunLoopRunInMode(runLoopMode, waitTime, TRUE);
+ LOCK_NOTIFIER;
+ }
+ tsdPtr->eventReady = 0;
+ if (waitForFiles && tsdPtr->onList) {
/*
- * Queue all detected file events before returning.
+ * Remove the ThreadSpecificData structure of this thread from the
+ * waiting list. Alert the notifier thread to recompute its select
+ * masks; skipping this caused a hang when trying to close a pipe
+ * which the notifier thread was still doing a select on.
*/
- for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
- filePtr = filePtr->nextPtr) {
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ }
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ tsdPtr->onList = 0;
+ write(triggerPipe, "", 1);
+ }
- mask = 0;
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
- mask |= TCL_READABLE;
- }
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
- mask |= TCL_WRITABLE;
- }
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
- mask |= TCL_EXCEPTION;
- }
+ /*
+ * Queue all detected file events before returning.
+ */
- if (!mask) {
- continue;
- }
+ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
+ filePtr = filePtr->nextPtr) {
+ mask = 0;
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
+ mask |= TCL_READABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
+ mask |= TCL_WRITABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
+ mask |= TCL_EXCEPTION;
+ }
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
+ if (!mask) {
+ continue;
+ }
- if (filePtr->readyMask == 0) {
- fileEvPtr = (FileHandlerEvent *)
- ckalloc(sizeof(FileHandlerEvent));
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- }
- filePtr->readyMask = mask;
+ /*
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
- UNLOCK_NOTIFIER;
- return 0;
+ filePtr->readyMask = mask;
}
+ UNLOCK_NOTIFIER;
+ return 0;
}
/*
@@ -1233,9 +1236,9 @@ NotifierThreadProc(
if (tsdPtr->onList) {
/*
* Remove the ThreadSpecificData structure of this thread
- * from the waiting list. This prevents us from
- * continuously spining on select until the other threads
- * runs and services the file event.
+ * from the waiting list. This prevents us from spinning
+ * continuously on select until the other threads runs and
+ * services the file event.
*/
if (tsdPtr->prevPtr) {