diff options
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tclMacOSXBundle.c | 153 | ||||
-rw-r--r-- | macosx/tclMacOSXFCmd.c | 152 | ||||
-rw-r--r-- | macosx/tclMacOSXNotify.c | 331 |
3 files changed, 342 insertions, 294 deletions
diff --git a/macosx/tclMacOSXBundle.c b/macosx/tclMacOSXBundle.c index 97124cf..1748ee3 100644 --- a/macosx/tclMacOSXBundle.c +++ b/macosx/tclMacOSXBundle.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacOSXBundle.c,v 1.16 2009/10/05 02:41:07 das Exp $ + * RCS: @(#) $Id: tclMacOSXBundle.c,v 1.17 2010/03/25 14:02:11 dkf Exp $ */ #include "tclPort.h" @@ -27,7 +27,7 @@ # else # define TCL_DYLD_USE_DLFCN 0 # endif -#endif +#endif /* TCL_DYLD_USE_DLFCN */ #ifndef TCL_DYLD_USE_NSMODULE /* @@ -38,7 +38,7 @@ # else # define TCL_DYLD_USE_NSMODULE 0 # endif -#endif +#endif /* TCL_DYLD_USE_NSMODULE */ #if TCL_DYLD_USE_DLFCN #include <dlfcn.h> @@ -46,10 +46,11 @@ /* * Support for weakly importing dlfcn API. */ -extern void *dlsym(void *handle, const char *symbol) WEAK_IMPORT_ATTRIBUTE; -extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE; -#endif +extern void * dlsym(void *handle, const char *symbol) + WEAK_IMPORT_ATTRIBUTE; +extern char * dlerror(void) WEAK_IMPORT_ATTRIBUTE; #endif +#endif /* TCL_DYLD_USE_DLFCN */ #if TCL_DYLD_USE_NSMODULE #include <mach-o/dyld.h> @@ -57,21 +58,89 @@ extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE; #if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \ (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) -MODULE_SCOPE long tclMacOSXDarwinRelease; +MODULE_SCOPE long tclMacOSXDarwinRelease; #endif #ifdef TCL_DEBUG_LOAD -#define TclLoadDbgMsg(m, ...) do { \ - fprintf(stderr, "%s:%d: %s(): " m ".\n", \ - strrchr(__FILE__, '/')+1, __LINE__, __func__, ##__VA_ARGS__); \ - } while (0) +#define TclLoadDbgMsg(m, ...) \ + do { \ + fprintf(stderr, "%s:%d: %s(): " m ".\n", \ + strrchr(__FILE__, '/')+1, __LINE__, __func__, \ + ##__VA_ARGS__); \ + } while (0) #else #define TclLoadDbgMsg(m, ...) -#endif +#endif /* TCL_DEBUG_LOAD */ #endif /* HAVE_COREFOUNDATION */ /* + * Forward declaration of functions defined in this file: + */ + +static short OpenResourceMap(CFBundleRef bundleRef); + +/* + *---------------------------------------------------------------------- + * + * OpenResourceMap -- + * + * Wrapper that dynamically acquires the address for the function + * CFBundleOpenBundleResourceMap before calling it, since it is only + * present in full CoreFoundation on Mac OS X and not in CFLite on pure + * Darwin. Factored out because it is moderately ugly code. + * + *---------------------------------------------------------------------- + */ + +static short +OpenResourceMap( + CFBundleRef bundleRef) +{ + static int initialized = FALSE; + static short (*openresourcemap)(CFBundleRef) = NULL; + + if (!initialized) { +#if TCL_DYLD_USE_DLFCN +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + if (tclMacOSXDarwinRelease >= 8) +#endif + { + openresourcemap = dlsym(RTLD_NEXT, + "CFBundleOpenBundleResourceMap"); +#ifdef TCL_DEBUG_LOAD + if (!openresourcemap) { + const char *errMsg = dlerror(); + + TclLoadDbgMsg("dlsym() failed: %s", errMsg); + } +#endif /* TCL_DEBUG_LOAD */ + } + if (!openresourcemap) +#endif /* TCL_DYLD_USE_DLFCN */ + { +#if TCL_DYLD_USE_NSMODULE + if (NSIsSymbolNameDefinedWithHint( + "_CFBundleOpenBundleResourceMap", "CoreFoundation")) { + NSSymbol nsSymbol = NSLookupAndBindSymbolWithHint( + "_CFBundleOpenBundleResourceMap", "CoreFoundation"); + + if (nsSymbol) { + openresourcemap = NSAddressOfSymbol(nsSymbol); + } + } +#endif /* TCL_DYLD_USE_NSMODULE */ + } + initialized = TRUE; + } + + if (openresourcemap) { + return openresourcemap(bundleRef); + } + return -1; +} + +/* *---------------------------------------------------------------------- * * Tcl_MacOSXOpenBundleResources -- @@ -99,8 +168,8 @@ Tcl_MacOSXOpenBundleResources( int maxPathLen, char *libraryPath) { - return Tcl_MacOSXOpenVersionedBundleResources(interp, bundleName, - NULL, hasResourceFile, maxPathLen, libraryPath); + return Tcl_MacOSXOpenVersionedBundleResources(interp, bundleName, NULL, + hasResourceFile, maxPathLen, libraryPath); } /* @@ -195,54 +264,7 @@ Tcl_MacOSXOpenVersionedBundleResources( if (bundleRef) { if (hasResourceFile) { - /* - * Dynamically acquire address for CFBundleOpenBundleResourceMap - * symbol, since it is only present in full CoreFoundation on Mac - * OS X and not in CFLite on pure Darwin. - */ - - static int initialized = FALSE; - static short (*openresourcemap)(CFBundleRef) = NULL; - - if (!initialized) { -#if TCL_DYLD_USE_DLFCN -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 - if (tclMacOSXDarwinRelease >= 8) -#endif - { - const char *errMsg = nil; - openresourcemap = dlsym(RTLD_NEXT, - "CFBundleOpenBundleResourceMap"); - if (!openresourcemap) { - errMsg = dlerror(); - TclLoadDbgMsg("dlsym() failed: %s", errMsg); - } - } - if (!openresourcemap) -#endif - { -#if TCL_DYLD_USE_NSMODULE - NSSymbol nsSymbol = NULL; - if (NSIsSymbolNameDefinedWithHint( - "_CFBundleOpenBundleResourceMap", - "CoreFoundation")) { - nsSymbol = NSLookupAndBindSymbolWithHint( - "_CFBundleOpenBundleResourceMap", - "CoreFoundation"); - if (nsSymbol) { - openresourcemap = NSAddressOfSymbol(nsSymbol); - } - } -#endif - } - initialized = TRUE; - } - - if (openresourcemap) { - short refNum; - - refNum = openresourcemap(bundleRef); - } + (void) OpenResourceMap(bundleRef); } libURL = CFBundleCopyResourceURL(bundleRef, CFSTR("Scripts"), @@ -255,7 +277,7 @@ Tcl_MacOSXOpenVersionedBundleResources( */ CFURLGetFileSystemRepresentation(libURL, TRUE, - (unsigned char*) libraryPath, maxPathLen); + (unsigned char *) libraryPath, maxPathLen); CFRelease(libURL); } if (versionedBundleRef) { @@ -271,12 +293,9 @@ Tcl_MacOSXOpenVersionedBundleResources( if (libraryPath[0]) { return TCL_OK; - } else { - return TCL_ERROR; } -#else /* HAVE_COREFOUNDATION */ - return TCL_ERROR; #endif /* HAVE_COREFOUNDATION */ + return TCL_ERROR; } /* diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c index 7b80a9d..818b91d 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.18 2010/03/05 14:34:04 dkf Exp $ + * RCS: @(#) $Id: tclMacOSXFCmd.c,v 1.19 2010/03/25 14:02:11 dkf Exp $ */ #include "tclInt.h" @@ -24,7 +24,7 @@ #ifdef HAVE_COPYFILE #ifdef HAVE_COPYFILE_H #include <copyfile.h> -#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +#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, @@ -34,10 +34,10 @@ extern int copyfile(const char *from, const char *to, #else /* HAVE_COPYFILE_H */ 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 +#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, @@ -47,6 +47,14 @@ extern int copyfile(const char *from, const char *to, #endif /* HAVE_COPYFILE_H */ #endif /* HAVE_COPYFILE */ +#ifdef WEAK_IMPORT_COPYFILE +#define MayUseCopyFile() (copyfile != NULL) +#elif defined(HAVE_COPYFILE) +#define MayUseCopyFile() (1) +#else +#define MayUseCopyFile() (0) +#endif + #include <libkern/OSByteOrder.h> /* @@ -86,7 +94,7 @@ static const Tcl_ObjType tclOSTypeType = { }; enum { - kIsInvisible = 0x4000, + kIsInvisible = 0x4000, }; #define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible)) @@ -142,8 +150,8 @@ TclMacOSXGetFileAttribute( result = TclpObjStat(fileName, &statBuf); if (result != 0) { - Tcl_AppendResult(interp, "could not read \"", - TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); + Tcl_AppendResult(interp, "could not read \"", TclGetString(fileName), + "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } @@ -234,8 +242,8 @@ TclMacOSXSetFileAttribute( result = TclpObjStat(fileName, &statBuf); if (result != 0) { - Tcl_AppendResult(interp, "could not read \"", - TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); + Tcl_AppendResult(interp, "could not read \"", TclGetString(fileName), + "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } @@ -300,8 +308,8 @@ TclMacOSXSetFileAttribute( if (result != 0) { Tcl_AppendResult(interp, "could not set attributes of \"", - TclGetString(fileName), "\": ", - Tcl_PosixError(interp), NULL); + TclGetString(fileName), "\": ", Tcl_PosixError(interp), + NULL); return TCL_ERROR; } } else { @@ -320,7 +328,7 @@ TclMacOSXSetFileAttribute( * supported. */ - if(newRsrcForkSize != 0) { + if (newRsrcForkSize != 0) { Tcl_AppendResult(interp, "setting nonzero rsrclength not supported", NULL); return TCL_ERROR; @@ -337,11 +345,13 @@ TclMacOSXSetFileAttribute( result = truncate(Tcl_DStringValue(&ds), (off_t)0); if (result != 0) { /* - * truncate() on a valid resource fork path may fail with - * a permission error in some OS releases, try truncating - * with open() instead: + * truncate() on a valid resource fork path may fail with a + * permission error in some OS releases, try truncating with + * open() instead: */ + int fd = open(Tcl_DStringValue(&ds), O_WRONLY | O_TRUNC); + if (fd > 0) { result = close(fd); } @@ -390,25 +400,21 @@ TclMacOSXCopyFileAttributes( const Tcl_StatBuf *statBufPtr) /* Stat info for source file */ { -#ifdef WEAK_IMPORT_COPYFILE - if (copyfile != NULL) { -#endif + if (MayUseCopyFile()) { #ifdef HAVE_COPYFILE - if (copyfile(src, dst, NULL, COPYFILE_XATTR | - (S_ISLNK(statBufPtr->st_mode) - ? COPYFILE_NOFOLLOW_SRC : COPYFILE_ACL)) < 0) { - return TCL_ERROR; + if (0 == copyfile(src, dst, NULL, (S_ISLNK(statBufPtr->st_mode) + ? COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC + : COPYFILE_XATTR | COPYFILE_ACL))) { + return TCL_OK; } - return TCL_OK; #endif /* HAVE_COPYFILE */ -#ifdef WEAK_IMPORT_COPYFILE } else { -#endif -#if !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) -#ifdef HAVE_GETATTRLIST +#if (!defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)) && defined(HAVE_GETATTRLIST) struct attrlist alist; fileinfobuf finfo; off_t *rsrcForkSize = (off_t *) &finfo.data; + Tcl_DString srcBuf, dstBuf; + int result; bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; @@ -417,57 +423,56 @@ TclMacOSXCopyFileAttributes( if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { return TCL_ERROR; } - 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; + /* + * If we're a directory, we're done as they never have resource forks. + */ - if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { - return TCL_ERROR; - } + if (S_ISDIR(statBufPtr->st_mode)) { + return TCL_OK; + } - if (*rsrcForkSize > 0) { - int result; - Tcl_DString ds_src, ds_dst; + /* + * We only copy a non-empty resource fork, so determine if that's the + * case first. + */ - /* - * Construct paths to resource forks. - */ + alist.commonattr = 0; + alist.fileattr = ATTR_FILE_RSRCLENGTH; + if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { + return TCL_ERROR; + } else if (*rsrcForkSize == 0) { + return TCL_OK; + } - 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); + /* + * Construct paths to resource forks. + */ - result = TclUnixCopyFile(Tcl_DStringValue(&ds_src), - Tcl_DStringValue(&ds_dst), statBufPtr, 1); + Tcl_DStringInit(&srcBuf); + Tcl_DStringAppend(&srcBuf, src, -1); + Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, -1); + Tcl_DStringInit(&dstBuf); + Tcl_DStringAppend(&dstBuf, dst, -1); + Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, -1); - Tcl_DStringFree(&ds_src); - Tcl_DStringFree(&ds_dst); + /* + * Do the copy. + */ - if (result != 0) { - return TCL_ERROR; - } - } + result = TclUnixCopyFile(Tcl_DStringValue(&srcBuf), + Tcl_DStringValue(&dstBuf), statBufPtr, 1); + Tcl_DStringFree(&srcBuf); + Tcl_DStringFree(&dstBuf); + if (result == 0) { + return TCL_OK; } - return TCL_OK; -#else - return TCL_ERROR; -#endif /* HAVE_GETATTRLIST */ -#endif /* !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) */ -#ifdef WEAK_IMPORT_COPYFILE +#endif /* (!HAVE_COPYFILE || WEAK_IMPORT_COPYFILE) && HAVE_GETATTRLIST */ } -#endif + return TCL_ERROR; } /* @@ -491,11 +496,11 @@ TclMacOSXCopyFileAttributes( int TclMacOSXMatchType( - Tcl_Interp *interp, /* Interpreter to receive errors. */ - const char *pathName, /* Native path to check. */ - const char *fileName, /* Native filename to check. */ - Tcl_StatBuf *statBufPtr, /* Stat info for file to check */ - Tcl_GlobTypeData *types) /* Type description to match against. */ + Tcl_Interp *interp, /* Interpreter to receive errors. */ + const char *pathName, /* Native path to check. */ + const char *fileName, /* Native filename to check. */ + Tcl_StatBuf *statBufPtr, /* Stat info for file to check */ + Tcl_GlobTypeData *types) /* Type description to match against. */ { #ifdef HAVE_GETATTRLIST struct attrlist alist; @@ -676,7 +681,8 @@ SetOSTypeFromAny( static void UpdateStringOfOSType( - register Tcl_Obj *objPtr) /* OSType object whose string rep to update. */ + register Tcl_Obj *objPtr) /* OSType object whose string rep to + * update. */ { char string[5]; OSType osType = (OSType) objPtr->internalRep.longValue; diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c index 2fae4b6..f65f6e6 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.28 2009/08/24 00:27:47 das Exp $ + * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.29 2010/03/25 14:02:12 dkf Exp $ */ #include "tclInt.h" @@ -48,22 +48,30 @@ #define VOLATILE volatile #else #define VOLATILE -#endif +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 */ #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; +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) { +static void +SpinLockLockInit(void) +{ lockLock = OSSpinLockLock != NULL ? OSSpinLockLock : _spin_lock; lockUnlock = OSSpinLockUnlock != NULL ? OSSpinLockUnlock : _spin_unlock; lockTry = OSSpinLockTry != NULL ? OSSpinLockTry : _spin_lock_try; @@ -73,13 +81,13 @@ static void SpinLockLockInit(void) { } #define SpinLockLock(p) lockLock(p) #define SpinLockUnlock(p) lockUnlock(p) -#define SpinLockTry(p) lockTry(p) +#define SpinLockTry(p) lockTry(p) #else #define SpinLockLock(p) OSSpinLockLock(p) #define SpinLockUnlock(p) OSSpinLockUnlock(p) -#define SpinLockTry(p) OSSpinLockTry(p) +#define SpinLockTry(p) OSSpinLockTry(p) #endif /* HAVE_WEAK_IMPORT */ -#define SPINLOCK_INIT OS_SPINLOCK_INIT +#define SPINLOCK_INIT OS_SPINLOCK_INIT #else /* @@ -87,13 +95,13 @@ static void SpinLockLockInit(void) { */ typedef uint32_t OSSpinLock; -extern void _spin_lock(OSSpinLock *lock); -extern void _spin_unlock(OSSpinLock *lock); -extern int _spin_lock_try(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 +#define SpinLockTry(p) _spin_lock_try(p) +#define SPINLOCK_INIT 0 #endif /* HAVE_LIBKERN_OSATOMIC_H && HAVE_OSSPINLOCKLOCK */ @@ -116,23 +124,27 @@ static OSSpinLock notifierLock = SPINLOCK_INIT; #define UNLOCK_NOTIFIER_TSD SpinLockUnlock(&tsdPtr->tsdLock) #ifdef TCL_MAC_DEBUG_NOTIFIER -#define TclMacOSXNotifierDbgMsg(m, ...) do { \ - fprintf(notifierLog?notifierLog:stderr, "tclMacOSXNotify.c:%d: " \ - "%s() pid %5d thread %10p: " m "\n", __LINE__, __func__, \ - getpid(), pthread_self(), ##__VA_ARGS__); \ - fflush(notifierLog?notifierLog:stderr); \ - } while (0) +#define TclMacOSXNotifierDbgMsg(m, ...) \ + do { \ + fprintf(notifierLog?notifierLog:stderr, "tclMacOSXNotify.c:%d: " \ + "%s() pid %5d thread %10p: " m "\n", __LINE__, __func__, \ + getpid(), pthread_self(), ##__VA_ARGS__); \ + fflush(notifierLog?notifierLog:stderr); \ + } while (0) /* * 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(); \ - TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns", \ - #p, TclpWideClicksToNanoseconds(e-s)); \ - } +#define SpinLockLockDbg(p) \ + if (!SpinLockTry(p)) { \ + Tcl_WideInt s = TclpGetWideClicks(), e; \ + \ + SpinLockLock(p); \ + e = TclpGetWideClicks(); \ + TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns", \ + #p, TclpWideClicksToNanoseconds(e-s)); \ + } #undef LOCK_NOTIFIER_INIT #define LOCK_NOTIFIER_INIT SpinLockLockDbg(¬ifierInitLock) #undef LOCK_NOTIFIER @@ -144,42 +156,44 @@ static FILE *notifierLog = NULL; #ifndef NOTIFIER_LOG #define NOTIFIER_LOG "/tmp/tclMacOSXNotify.log" #endif -#define OPEN_NOTIFIER_LOG if (!notifierLog) { \ - notifierLog = fopen(NOTIFIER_LOG, "a"); \ - /*TclMacOSXNotifierDbgMsg("open log"); \ - asl_set_filter(NULL, \ - ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ - asl_add_log_file(NULL, \ - fileno(notifierLog));*/ \ - } -#define CLOSE_NOTIFIER_LOG if (notifierLog) { \ - /*asl_remove_log_file(NULL, \ - fileno(notifierLog)); \ - TclMacOSXNotifierDbgMsg("close log");*/ \ - fclose(notifierLog); \ - notifierLog = NULL; \ - } -#define ENABLE_ASL if (notifierLog) { \ - /*tsdPtr->asl = asl_open(NULL, "com.apple.console", ASL_OPT_NO_REMOTE); \ - asl_set_filter(tsdPtr->asl, \ - ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ - asl_add_log_file(tsdPtr->asl, \ - fileno(notifierLog));*/ \ - } -#define DISABLE_ASL /*if (tsdPtr->asl) { \ - if (notifierLog) { \ - asl_remove_log_file(tsdPtr->asl, \ - fileno(notifierLog)); \ - } \ - asl_close(tsdPtr->asl); \ - }*/ -#define ASLCLIENT /*aslclient asl*/ +#define OPEN_NOTIFIER_LOG \ + if (!notifierLog) { \ + notifierLog = fopen(NOTIFIER_LOG, "a"); \ + /*TclMacOSXNotifierDbgMsg("open log"); \ + *asl_set_filter(NULL, \ + * ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ + *asl_add_log_file(NULL, fileno(notifierLog));*/ \ + } +#define CLOSE_NOTIFIER_LOG \ + if (notifierLog) { \ + /*asl_remove_log_file(NULL, fileno(notifierLog)); \ + *TclMacOSXNotifierDbgMsg("close log");*/ \ + fclose(notifierLog); \ + notifierLog = NULL; \ + } +#define ENABLE_ASL \ + if (notifierLog) { \ + /*tsdPtr->asl = asl_open(NULL, "com.apple.console", \ + * ASL_OPT_NO_REMOTE); \ + *asl_set_filter(tsdPtr->asl, \ + * ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ + *asl_add_log_file(tsdPtr->asl, fileno(notifierLog));*/ \ + } +#define DISABLE_ASL \ + /*if (tsdPtr->asl) { \ + * if (notifierLog) { \ + * asl_remove_log_file(tsdPtr->asl, fileno(notifierLog)); \ + * } \ + * asl_close(tsdPtr->asl); \ + *}*/ +#define ASLCLIENT_DECL /*aslclient asl*/ #else #define TclMacOSXNotifierDbgMsg(m, ...) #define OPEN_NOTIFIER_LOG #define CLOSE_NOTIFIER_LOG #define ENABLE_ASL #define DISABLE_ASL +#define ASLCLIENT_DECL #endif /* TCL_MAC_DEBUG_NOTIFIER */ /* @@ -236,28 +250,30 @@ typedef struct ThreadSpecificData { FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler list. */ int polled; /* True if the notifier thread has polled for - * this thread. - */ + * this thread. */ int sleeping; /* True if runloop is inside Tcl_Sleep. */ int runLoopSourcePerformed; /* True after the runLoopSource callack was * performed. */ - int runLoopRunning; /* True if this thread's Tcl runLoop is running */ - int runLoopNestingLevel; /* Level of nested runLoop invocations */ + int runLoopRunning; /* True if this thread's Tcl runLoop is + * running. */ + int runLoopNestingLevel; /* Level of nested runLoop invocations. */ int runLoopServicingEvents; /* True if this thread's runLoop is servicing - * tcl events */ + * Tcl events. */ + /* Must hold the notifierLock before accessing the following fields: */ /* Start notifierLock section */ - int onList; /* True if this thread is on the waitingList */ + int onList; /* True if this thread is on the + * waitingList */ struct ThreadSpecificData *nextPtr, *prevPtr; /* All threads that are currently waiting on * an event have their ThreadSpecificData * structure on a doubly-linked listed formed - * from these pointers. - */ + * from these pointers. */ /* End notifierLock section */ + OSSpinLock tsdLock; /* Must hold this lock before acessing the - * following fields from more than one thread. - */ + * following fields from more than one + * thread. */ /* Start tsdLock section */ SelectMasks checkMasks; /* This structure is used to build up the * masks to be used in the next call to @@ -269,9 +285,11 @@ typedef struct ThreadSpecificData { int numFdBits; /* Number of valid bits in checkMasks (one * more than highest fd for which * Tcl_WatchFile has been called). */ - int polling; /* True if this thread is polling for events */ + int polling; /* True if this thread is polling for + * events. */ CFRunLoopRef runLoop; /* This thread's CFRunLoop, needs to be woken - * up whenever the runLoopSource is signaled */ + * up whenever the runLoopSource is + * signaled. */ CFRunLoopSourceRef runLoopSource; /* Any other thread alerts a notifier that an * event is ready to be processed by signaling @@ -283,11 +301,10 @@ typedef struct ThreadSpecificData { /* Wakes up CFRunLoop after given timeout when * running embedded. */ /* End tsdLock section */ + CFTimeInterval waitTime; /* runLoopTimer wait time when running * embedded. */ -#ifdef TCL_MAC_DEBUG_NOTIFIER - ASLCLIENT; -#endif + ASLCLIENT_DECL; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -337,8 +354,8 @@ static int receivePipe = -1; /* Output end of triggerPipe */ static int notifierThreadRunning; /* - * This is the thread ID of the notifier thread that does select. - * Only valid when notifierThreadRunning is non-zero. + * This is the thread ID of the notifier thread that does select. Only valid + * when notifierThreadRunning is non-zero. * * You must hold the notifierInitLock before accessing this variable. */ @@ -347,7 +364,7 @@ static pthread_t notifierThread; /* * Custom runloop mode for running with only the runloop source for the - * notifier thread + * notifier thread. */ #ifndef TCL_EVENTS_ONLY_RUN_LOOP_MODE @@ -369,38 +386,45 @@ static CFStringRef tclEventsOnlyRunLoopMode = NULL; * Static routines defined in this file. */ -static void StartNotifierThread(void); -static void NotifierThreadProc(ClientData clientData) - __attribute__ ((__noreturn__)); -static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); -static void TimerWakeUp(CFRunLoopTimerRef timer, void *info); -static void QueueFileEvents(void *info); -static void UpdateWaitingListAndServiceEvents(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void *info); -static int OnOffWaitingList(ThreadSpecificData *tsdPtr, int onList, - int signalNotifier); +static void StartNotifierThread(void); +static void NotifierThreadProc(ClientData clientData) + __attribute__ ((__noreturn__)); +static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); +static void TimerWakeUp(CFRunLoopTimerRef timer, void *info); +static void QueueFileEvents(void *info); +static void UpdateWaitingListAndServiceEvents( + CFRunLoopObserverRef observer, + CFRunLoopActivity activity, void *info); +static int OnOffWaitingList(ThreadSpecificData *tsdPtr, + int onList, int signalNotifier); #ifdef HAVE_PTHREAD_ATFORK -static int atForkInit = 0; -static void AtForkPrepare(void); -static void AtForkParent(void); -static void AtForkChild(void); +static int atForkInit = 0; +static void AtForkPrepare(void); +static void AtForkParent(void); +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; +#define MayUsePthreadAtfork() (pthread_atfork != NULL) +#else +#define MayUsePthreadAtfork() (1) #endif /* HAVE_WEAK_IMPORT */ + /* * On Darwin 9 and later, it is not possible to call CoreFoundation after * a fork. */ + #if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || \ MAC_OS_X_VERSION_MIN_REQUIRED < 1050 MODULE_SCOPE long tclMacOSXDarwinRelease; -#define noCFafterFork (tclMacOSXDarwinRelease >= 9) +#define noCFafterFork (tclMacOSXDarwinRelease >= 9) #else /* MAC_OS_X_VERSION_MIN_REQUIRED */ -#define noCFafterFork 1 +#define noCFafterFork 1 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #endif /* HAVE_PTHREAD_ATFORK */ @@ -516,11 +540,7 @@ Tcl_InitNotifier(void) * child of a fork. */ - if ( -#ifdef WEAK_IMPORT_PTHREAD_ATFORK - pthread_atfork != NULL && -#endif - !atForkInit) { + if (MayUsePthreadAtfork() && !atForkInit) { int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild); if (result) { @@ -528,7 +548,7 @@ Tcl_InitNotifier(void) } atForkInit = 1; } -#endif +#endif /* HAVE_PTHREAD_ATFORK */ if (notifierCount == 0) { int fds[2], status; @@ -569,7 +589,7 @@ Tcl_InitNotifier(void) notifierCount++; UNLOCK_NOTIFIER_INIT; - return (ClientData) tsdPtr; + return tsdPtr; } /* @@ -695,10 +715,10 @@ Tcl_FinalizeNotifier( * 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] + * 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); @@ -821,7 +841,7 @@ Tcl_SetTimer( return; } if (timePtr) { - Tcl_Time vTime = *timePtr; + Tcl_Time vTime = *timePtr; if (vTime.sec != 0 || vTime.usec != 0) { tclScaleTimeProcPtr(&vTime, tclTimeClientData); @@ -965,19 +985,19 @@ Tcl_CreateFileHandler( LOCK_NOTIFIER_TSD; if (mask & TCL_READABLE) { - FD_SET(fd, &(tsdPtr->checkMasks.readable)); + FD_SET(fd, &tsdPtr->checkMasks.readable); } else { - FD_CLR(fd, &(tsdPtr->checkMasks.readable)); + FD_CLR(fd, &tsdPtr->checkMasks.readable); } if (mask & TCL_WRITABLE) { - FD_SET(fd, &(tsdPtr->checkMasks.writable)); + FD_SET(fd, &tsdPtr->checkMasks.writable); } else { - FD_CLR(fd, &(tsdPtr->checkMasks.writable)); + FD_CLR(fd, &tsdPtr->checkMasks.writable); } if (mask & TCL_EXCEPTION) { - FD_SET(fd, &(tsdPtr->checkMasks.exceptional)); + FD_SET(fd, &tsdPtr->checkMasks.exceptional); } else { - FD_CLR(fd, &(tsdPtr->checkMasks.exceptional)); + FD_CLR(fd, &tsdPtr->checkMasks.exceptional); } if (tsdPtr->numFdBits <= fd) { tsdPtr->numFdBits = fd+1; @@ -1039,9 +1059,9 @@ Tcl_DeleteFileHandler( if (fd+1 == tsdPtr->numFdBits) { 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))) { + if (FD_ISSET(i, &tsdPtr->checkMasks.readable) + || FD_ISSET(i, &tsdPtr->checkMasks.writable) + || FD_ISSET(i, &tsdPtr->checkMasks.exceptional)) { numFdBits = i+1; break; } @@ -1058,13 +1078,13 @@ Tcl_DeleteFileHandler( */ if (filePtr->mask & TCL_READABLE) { - FD_CLR(fd, &(tsdPtr->checkMasks.readable)); + FD_CLR(fd, &tsdPtr->checkMasks.readable); } if (filePtr->mask & TCL_WRITABLE) { - FD_CLR(fd, &(tsdPtr->checkMasks.writable)); + FD_CLR(fd, &tsdPtr->checkMasks.writable); } if (filePtr->mask & TCL_EXCEPTION) { - FD_CLR(fd, &(tsdPtr->checkMasks.exceptional)); + FD_CLR(fd, &tsdPtr->checkMasks.exceptional); } UNLOCK_NOTIFIER_TSD; @@ -1148,13 +1168,13 @@ FileHandlerEventProc( if (mask != 0) { LOCK_NOTIFIER_TSD; if (mask & TCL_READABLE) { - FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.readable)); + FD_CLR(filePtr->fd, &tsdPtr->readyMasks.readable); } if (mask & TCL_WRITABLE) { - FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.writable)); + FD_CLR(filePtr->fd, &tsdPtr->readyMasks.writable); } if (mask & TCL_EXCEPTION) { - FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.exceptional)); + FD_CLR(filePtr->fd, &tsdPtr->readyMasks.exceptional); } UNLOCK_NOTIFIER_TSD; filePtr->proc(filePtr->clientData, mask); @@ -1205,7 +1225,7 @@ Tcl_WaitForEvent( } if (timePtr) { - Tcl_Time vTime = *timePtr; + Tcl_Time vTime = *timePtr; /* * TIP #233 (Virtualized Time). Is virtual time in effect? And do we @@ -1256,7 +1276,7 @@ Tcl_WaitForEvent( UNLOCK_NOTIFIER_TSD; switch (runLoopStatus) { case kCFRunLoopRunFinished: - Tcl_Panic("Tcl_WaitForEvent: CFRunLoop finished"); + Tcl_Panic("Tcl_WaitForEvent: CFRunLoop finished"); break; case kCFRunLoopRunTimedOut: QueueFileEvents(tsdPtr); @@ -1293,19 +1313,19 @@ QueueFileEvents( { SelectMasks readyMasks; FileHandler *filePtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info; + ThreadSpecificData *tsdPtr = info; /* * Queue all detected file events. */ LOCK_NOTIFIER_TSD; - FD_COPY(&(tsdPtr->readyMasks.readable), &readyMasks.readable); - FD_COPY(&(tsdPtr->readyMasks.writable), &readyMasks.writable); - FD_COPY(&(tsdPtr->readyMasks.exceptional), &readyMasks.exceptional); - FD_ZERO(&(tsdPtr->readyMasks.readable)); - FD_ZERO(&(tsdPtr->readyMasks.writable)); - FD_ZERO(&(tsdPtr->readyMasks.exceptional)); + FD_COPY(&tsdPtr->readyMasks.readable, &readyMasks.readable); + FD_COPY(&tsdPtr->readyMasks.writable, &readyMasks.writable); + FD_COPY(&tsdPtr->readyMasks.exceptional, &readyMasks.exceptional); + FD_ZERO(&tsdPtr->readyMasks.readable); + FD_ZERO(&tsdPtr->readyMasks.writable); + FD_ZERO(&tsdPtr->readyMasks.exceptional); UNLOCK_NOTIFIER_TSD; tsdPtr->runLoopSourcePerformed = 1; @@ -1365,7 +1385,7 @@ UpdateWaitingListAndServiceEvents( CFRunLoopActivity activity, void *info) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData*) info; + ThreadSpecificData *tsdPtr = info; if (tsdPtr->sleeping) { return; @@ -1376,7 +1396,7 @@ UpdateWaitingListAndServiceEvents( if (tsdPtr->numFdBits > 0 || tsdPtr->polling) { LOCK_NOTIFIER; if (!OnOffWaitingList(tsdPtr, 1, 1) && tsdPtr->polling) { - write(triggerPipe, "", 1); + write(triggerPipe, "", 1); } UNLOCK_NOTIFIER; } @@ -1391,7 +1411,8 @@ UpdateWaitingListAndServiceEvents( break; case kCFRunLoopBeforeWaiting: if (tsdPtr->runLoopTimer && !tsdPtr->runLoopServicingEvents && - (tsdPtr->runLoopNestingLevel > 1 || !tsdPtr->runLoopRunning)) { + (tsdPtr->runLoopNestingLevel > 1 + || !tsdPtr->runLoopRunning)) { tsdPtr->runLoopServicingEvents = 1; while (Tcl_ServiceAll() && tsdPtr->waitTime == 0) {} tsdPtr->runLoopServicingEvents = 0; @@ -1407,8 +1428,8 @@ UpdateWaitingListAndServiceEvents( * * OnOffWaitingList -- * - * Add/remove the specified thread to/from the global waitingList - * and optionally signal the notifier. + * Add/remove the specified thread to/from the global waitingList and + * optionally signal the notifier. * * !!! Requires notifierLock to be held !!! * @@ -1428,8 +1449,9 @@ OnOffWaitingList( int signalNotifier) { int changeWaitingList; + #ifdef TCL_MAC_DEBUG_NOTIFIER - if(SpinLockTry(¬ifierLock)) { + if (SpinLockTry(¬ifierLock)) { Tcl_Panic("OnOffWaitingList: notifierLock unlocked"); } #endif @@ -1456,7 +1478,7 @@ OnOffWaitingList( tsdPtr->onList = 0; } if (signalNotifier) { - write(triggerPipe, "", 1); + write(triggerPipe, "", 1); } } @@ -1494,7 +1516,7 @@ Tcl_Sleep( * TIP #233: Scale from virtual time to real-time. */ - vdelay.sec = ms / 1000; + vdelay.sec = ms / 1000; vdelay.usec = (ms % 1000) * 1000; tclScaleTimeProcPtr(&vdelay, tclTimeClientData); @@ -1520,8 +1542,8 @@ Tcl_Sleep( } tsdPtr->sleeping = 1; do { - runLoopStatus = CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, - FALSE); + runLoopStatus = CFRunLoopRunInMode(kCFRunLoopDefaultMode, + waitTime, FALSE); switch (runLoopStatus) { case kCFRunLoopRunFinished: Tcl_Panic("Tcl_Sleep: CFRunLoop finished"); @@ -1657,10 +1679,10 @@ TclUnixWaitForFile( * Setup the select masks for the fd. */ - if (mask & TCL_READABLE) { + if (mask & TCL_READABLE) { FD_SET(fd, &readableMask); } - if (mask & TCL_WRITABLE) { + if (mask & TCL_WRITABLE) { FD_SET(fd, &writableMask); } if (mask & TCL_EXCEPTION) { @@ -1674,10 +1696,10 @@ TclUnixWaitForFile( numFound = select(fd + 1, &readableMask, &writableMask, &exceptionalMask, timeoutPtr); if (numFound == 1) { - if (FD_ISSET(fd, &readableMask)) { + if (FD_ISSET(fd, &readableMask)) { SET_BITS(result, TCL_READABLE); } - if (FD_ISSET(fd, &writableMask)) { + if (FD_ISSET(fd, &writableMask)) { SET_BITS(result, TCL_WRITABLE); } if (FD_ISSET(fd, &exceptionalMask)) { @@ -1761,13 +1783,13 @@ NotifierThreadProc( for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { LOCK_NOTIFIER_TSD; for (i = tsdPtr->numFdBits-1; i >= 0; --i) { - if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) { + if (FD_ISSET(i, &tsdPtr->checkMasks.readable)) { FD_SET(i, &readableMask); } - if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) { + if (FD_ISSET(i, &tsdPtr->checkMasks.writable)) { FD_SET(i, &writableMask); } - if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) { + if (FD_ISSET(i, &tsdPtr->checkMasks.exceptional)) { FD_SET(i, &exceptionalMask); } } @@ -1810,9 +1832,9 @@ NotifierThreadProc( SelectMasks readyMasks, checkMasks; LOCK_NOTIFIER_TSD; - FD_COPY(&(tsdPtr->checkMasks.readable), &checkMasks.readable); - FD_COPY(&(tsdPtr->checkMasks.writable), &checkMasks.writable); - FD_COPY(&(tsdPtr->checkMasks.exceptional), &checkMasks.exceptional); + FD_COPY(&tsdPtr->checkMasks.readable, &checkMasks.readable); + FD_COPY(&tsdPtr->checkMasks.writable, &checkMasks.writable); + FD_COPY(&tsdPtr->checkMasks.exceptional, &checkMasks.exceptional); UNLOCK_NOTIFIER_TSD; found = tsdPtr->polled; FD_ZERO(&readyMasks.readable); @@ -1848,9 +1870,10 @@ NotifierThreadProc( OnOffWaitingList(tsdPtr, 0, 0); LOCK_NOTIFIER_TSD; - FD_COPY(&readyMasks.readable, &(tsdPtr->readyMasks.readable)); - FD_COPY(&readyMasks.writable, &(tsdPtr->readyMasks.writable)); - FD_COPY(&readyMasks.exceptional, &(tsdPtr->readyMasks.exceptional)); + FD_COPY(&readyMasks.readable, &tsdPtr->readyMasks.readable); + FD_COPY(&readyMasks.writable, &tsdPtr->readyMasks.writable); + FD_COPY(&readyMasks.exceptional, + &tsdPtr->readyMasks.exceptional); UNLOCK_NOTIFIER_TSD; tsdPtr->polled = 0; if (tsdPtr->runLoop) { |