summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclFileSystem.h30
-rw-r--r--generic/tclIOUtil.c317
-rw-r--r--generic/tclPathObj.c99
3 files changed, 251 insertions, 195 deletions
diff --git a/generic/tclFileSystem.h b/generic/tclFileSystem.h
index 966f221..7d74dc2 100644
--- a/generic/tclFileSystem.h
+++ b/generic/tclFileSystem.h
@@ -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: tclFileSystem.h,v 1.2 2003/04/14 15:48:35 vincentdarley Exp $
+ * RCS: @(#) $Id: tclFileSystem.h,v 1.3 2003/08/23 12:16:49 vasiljevic Exp $
*/
/*
@@ -31,8 +31,28 @@ typedef struct FilesystemRecord {
struct FilesystemRecord *nextPtr;
/* The next filesystem registered
* to Tcl, or NULL if no more. */
+ struct FilesystemRecord *prevPtr;
+ /* The previous filesystem registered
+ * to Tcl, or NULL if no more. */
} FilesystemRecord;
+/*
+ * This structure holds per-thread private copy of the
+ * current directory maintained by the global cwdPathPtr.
+ * This structure holds per-thread private copies of
+ * some global data. This way we avoid most of the
+ * synchronization calls which boosts performance, at
+ * cost of having to update this information each
+ * time the corresponding epoch counter changes.
+ */
+typedef struct ThreadSpecificData {
+ int initialized;
+ int cwdPathEpoch;
+ int filesystemEpoch;
+ Tcl_Obj *cwdPathPtr;
+ FilesystemRecord *filesystemList;
+} ThreadSpecificData;
+
/*
* The internal TclFS API provides routines for handling and
* manipulating paths efficiently, taking direct advantage of
@@ -50,12 +70,11 @@ Tcl_Obj* TclFSMakePathRelative _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *objPtr, Tcl_Obj *cwdPtr));
Tcl_Obj* TclFSInternalToNormalized _ANSI_ARGS_((
Tcl_Filesystem *fromFilesystem, ClientData clientData,
- FilesystemRecord **fsRecPtrPtr, int *epochPtr));
-int TclFSEnsureEpochOk _ANSI_ARGS_((Tcl_Obj* pathObjPtr, int theEpoch,
+ FilesystemRecord **fsRecPtrPtr));
+int TclFSEnsureEpochOk _ANSI_ARGS_((Tcl_Obj* pathObjPtr,
Tcl_Filesystem **fsPtrPtr));
void TclFSSetPathDetails _ANSI_ARGS_((Tcl_Obj *pathObjPtr,
- FilesystemRecord *fsRecPtr, ClientData clientData,
- int theEpoch));
+ FilesystemRecord *fsRecPtr, ClientData clientData ));
Tcl_Obj* TclFSNormalizeAbsolutePath _ANSI_ARGS_((Tcl_Interp* interp,
Tcl_Obj *pathPtr, ClientData *clientDataPtr));
@@ -64,6 +83,7 @@ Tcl_Obj* TclFSNormalizeAbsolutePath _ANSI_ARGS_((Tcl_Interp* interp,
*/
extern Tcl_Filesystem tclNativeFilesystem;
extern int theFilesystemEpoch;
+extern Tcl_ThreadDataKey fsDataKey;
/*
* Private shared functions for use by tclIOUtil.c and tclPathObj.c
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index edcad14..1999598 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -17,7 +17,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIOUtil.c,v 1.81 2003/05/13 22:59:49 hobbs Exp $
+ * RCS: @(#) $Id: tclIOUtil.c,v 1.82 2003/08/23 12:16:49 vasiljevic Exp $
*/
#include "tclInt.h"
@@ -35,10 +35,13 @@
* Prototypes for procedures defined later in this file.
*/
-static FilesystemRecord* FsGetIterator(void);
-static void FsReleaseIterator(void);
+static FilesystemRecord* FsGetFirstFilesystem(void);
static void FsThrExitProc(ClientData cd);
+#ifdef TCL_THREADS
+static void FsRecacheFilesystemList(void);
+#endif
+
/*
* These form part of the native filesystem support. They are needed
* here because we have a few native filesystem functions (which are
@@ -387,58 +390,30 @@ static FilesystemRecord nativeFilesystemRecord = {
};
/*
- * The following few variables are protected by the
- * filesystemMutex just below.
- */
-
-/*
* This is incremented each time we modify the linked list of
* filesystems. Any time it changes, all cached filesystem
* representations are suspect and must be freed.
+ * For multithreading builds, change of the filesystem epoch
+ * will trigger cache cleanup in all threads.
*/
int theFilesystemEpoch = 0;
/*
- * Stores the linked list of filesystems.
+ * Stores the linked list of filesystems. A 1:1 copy of this
+ * list is also maintained in the TSD for each thread. This
+ * is to avoid synchronization issues.
*/
static FilesystemRecord *filesystemList = &nativeFilesystemRecord;
-
-/*
- * The number of loops which are currently iterating over the linked
- * list. If this is greater than zero, we can't modify the list.
- */
-static int filesystemIteratorsInProgress = 0;
-
-/*
- * Someone wants to modify the list of filesystems if this is set.
- */
-static int filesystemWantToModify = 0;
-
-#ifdef TCL_THREADS
-static Tcl_Condition filesystemOkToModify = NULL;
-#endif
-
TCL_DECLARE_MUTEX(filesystemMutex)
/*
* Used to implement Tcl_FSGetCwd in a file-system independent way.
- * This is protected by the cwdMutex below.
*/
static Tcl_Obj* cwdPathPtr = NULL;
static int cwdPathEpoch = 0;
TCL_DECLARE_MUTEX(cwdMutex)
-/*
- * This structure holds per-thread private copy of the
- * current directory maintained by the global cwdPathPtr.
- */
-typedef struct ThreadSpecificData {
- int initialized;
- int cwdPathEpoch;
- Tcl_Obj *cwdPathPtr;
-} ThreadSpecificData;
-
-Tcl_ThreadDataKey dataKey;
+Tcl_ThreadDataKey fsDataKey;
/*
* Declare fallback support function and
@@ -469,23 +444,35 @@ FsThrExitProc(cd)
ClientData cd;
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData*)cd;
+ FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;
+
+ /* Trash the cwd copy */
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
}
+ /* Trash the filesystems cache */
+ fsRecPtr = tsdPtr->filesystemList;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = fsRecPtr->nextPtr;
+ if (--fsRecPtr->fileRefCount <= 0) {
+ ckfree((char *)fsRecPtr);
+ }
+ fsRecPtr = tmpFsRecPtr;
+ }
}
int
TclFSCwdPointerEquals(objPtr)
Tcl_Obj* objPtr;
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
Tcl_MutexLock(&cwdMutex);
- if (tsdPtr->initialized == 0) {
- Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
- tsdPtr->initialized = 1;
- }
- if (tsdPtr->cwdPathPtr == NULL) {
+ if (tsdPtr->cwdPathPtr == NULL
+ || tsdPtr->cwdPathEpoch != cwdPathEpoch) {
+ if (tsdPtr->cwdPathPtr) {
+ Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
+ }
if (cwdPathPtr == NULL) {
tsdPtr->cwdPathPtr = NULL;
} else {
@@ -493,40 +480,88 @@ TclFSCwdPointerEquals(objPtr)
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
tsdPtr->cwdPathEpoch = cwdPathEpoch;
- } else if (tsdPtr->cwdPathEpoch != cwdPathEpoch) {
- Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
- if (cwdPathPtr == NULL) {
- tsdPtr->cwdPathPtr = NULL;
- } else {
- tsdPtr->cwdPathPtr = Tcl_DuplicateObj(cwdPathPtr);
- Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
- }
}
Tcl_MutexUnlock(&cwdMutex);
+ if (tsdPtr->initialized == 0) {
+ Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
+ tsdPtr->initialized = 1;
+ }
+
return (tsdPtr->cwdPathPtr == objPtr);
}
-static FilesystemRecord*
-FsGetIterator(void) {
- Tcl_MutexLock(&filesystemMutex);
- filesystemIteratorsInProgress++;
- Tcl_MutexUnlock(&filesystemMutex);
- /* Now we know the list of filesystems cannot be modified */
- return filesystemList;
+#ifdef TCL_THREADS
+static void
+FsRecacheFilesystemList(void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
+ FilesystemRecord *fsRecPtr, *tmpFsRecPtr;
+
+ /* Trash the current cache */
+ fsRecPtr = tsdPtr->filesystemList;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = fsRecPtr->nextPtr;
+ if (--fsRecPtr->fileRefCount <= 0) {
+ ckfree((char *)fsRecPtr);
+ }
+ fsRecPtr = tmpFsRecPtr;
+ }
+ tsdPtr->filesystemList = NULL;
+
+ /*
+ * Code below operates on shared data. We
+ * are already called under mutex lock so
+ * we can safely proceede.
+ */
+
+ /* Locate tail of the global filesystem list */
+ fsRecPtr = filesystemList;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = fsRecPtr;
+ fsRecPtr = fsRecPtr->nextPtr;
+ }
+
+ /* Refill the cache honouring the order */
+ fsRecPtr = tmpFsRecPtr;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = (FilesystemRecord *)ckalloc(sizeof(FilesystemRecord));
+ *tmpFsRecPtr = *fsRecPtr;
+ tmpFsRecPtr->nextPtr = tsdPtr->filesystemList;
+ tmpFsRecPtr->prevPtr = NULL;
+ if (tsdPtr->filesystemList) {
+ tsdPtr->filesystemList->prevPtr = tmpFsRecPtr;
+ }
+ tsdPtr->filesystemList = tmpFsRecPtr;
+ fsRecPtr = fsRecPtr->prevPtr;
+ }
+
+ /* Make sure the above gets released on thread exit */
+ if (tsdPtr->initialized == 0) {
+ Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
+ tsdPtr->initialized = 1;
+ }
}
+#endif /* TCL_THREADS */
-static void
-FsReleaseIterator(void) {
+static FilesystemRecord *
+FsGetFirstFilesystem(void) {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
+ FilesystemRecord *fsRecPtr;
+#ifndef TCL_THREADS
+ tsdPtr->filesystemEpoch = theFilesystemEpoch;
+ fsRecPtr = filesystemList;
+#else
Tcl_MutexLock(&filesystemMutex);
- filesystemIteratorsInProgress--;
- if (filesystemIteratorsInProgress == 0) {
- /* Notify any waiting threads that things are ok now */
- if (filesystemWantToModify > 0) {
- Tcl_ConditionNotify(&filesystemOkToModify);
- }
+ if (tsdPtr->filesystemList == NULL
+ || (tsdPtr->filesystemEpoch != theFilesystemEpoch)) {
+ FsRecacheFilesystemList();
+ tsdPtr->filesystemEpoch = theFilesystemEpoch;
}
Tcl_MutexUnlock(&filesystemMutex);
+ fsRecPtr = tsdPtr->filesystemList;
+#endif
+ return fsRecPtr;
}
static void
@@ -535,7 +570,7 @@ FsUpdateCwd(cwdObj)
{
int len;
char *str = NULL;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (cwdObj != NULL) {
str = Tcl_GetStringFromObj(cwdObj, &len);
@@ -590,6 +625,8 @@ FsUpdateCwd(cwdObj)
void
TclFinalizeFilesystem()
{
+ FilesystemRecord *fsRecPtr, *tmpFsRecPtr;
+
/*
* Assumption that only one thread is active now. Otherwise
* we would need to put various mutexes around this code.
@@ -605,27 +642,25 @@ TclFinalizeFilesystem()
* Remove all filesystems, freeing any allocated memory
* that is no longer needed
*/
- while (filesystemList != NULL) {
- FilesystemRecord *tmpFsRecPtr = filesystemList->nextPtr;
- if (filesystemList->fileRefCount > 0) {
- /*
- * This filesystem must have some path objects still
- * around which will be freed later (e.g. when unloading
- * any shared libraries). If not, then someone is
- * causing us to leak memory.
- */
- } else {
- /* The native filesystem is static, so we don't free it */
- if (filesystemList != &nativeFilesystemRecord) {
- ckfree((char *)filesystemList);
- }
- }
- filesystemList = tmpFsRecPtr;
+
+ fsRecPtr = filesystemList;
+ while (fsRecPtr != NULL) {
+ tmpFsRecPtr = filesystemList->nextPtr;
+ if (fsRecPtr->fileRefCount <= 0) {
+ /* The native filesystem is static, so we don't free it */
+ if (fsRecPtr != &nativeFilesystemRecord) {
+ ckfree((char *)fsRecPtr);
+ }
+ }
+ fsRecPtr = tmpFsRecPtr;
}
+ filesystemList = NULL;
+
/*
* Now filesystemList is NULL. This means that any attempt
* to use the filesystem is likely to fail.
*/
+
statProcList = NULL;
accessProcList = NULL;
openFileChannelProcList = NULL;
@@ -660,11 +695,6 @@ TclResetFilesystem()
* down the cause.
*/
- filesystemIteratorsInProgress = 0;
- filesystemWantToModify = 0;
-#ifdef TCL_THREADS
- filesystemOkToModify = NULL;
-#endif
#ifdef __WIN32__
/*
* Cleans up the win32 API filesystem proc lookup table. This must
@@ -741,14 +771,14 @@ Tcl_FSRegister(clientData, fsPtr)
* a very rare action, this is not a very important point.
*/
Tcl_MutexLock(&filesystemMutex);
- if (filesystemIteratorsInProgress) {
- filesystemWantToModify++;
- Tcl_ConditionWait(&filesystemOkToModify, &filesystemMutex, NULL);
- filesystemWantToModify--;
- }
newFilesystemPtr->nextPtr = filesystemList;
+ newFilesystemPtr->prevPtr = NULL;
+ if (filesystemList) {
+ filesystemList->prevPtr = newFilesystemPtr;
+ }
filesystemList = newFilesystemPtr;
+
/*
* Increment the filesystem epoch counter, since existing paths
* might conceivably now belong to different filesystems.
@@ -789,28 +819,26 @@ Tcl_FSUnregister(fsPtr)
Tcl_Filesystem *fsPtr; /* The filesystem record to remove. */
{
int retVal = TCL_ERROR;
- FilesystemRecord *tmpFsRecPtr;
- FilesystemRecord *prevFsRecPtr = NULL;
+ FilesystemRecord *fsRecPtr;
Tcl_MutexLock(&filesystemMutex);
- if (filesystemIteratorsInProgress) {
- filesystemWantToModify++;
- Tcl_ConditionWait(&filesystemOkToModify, &filesystemMutex, NULL);
- filesystemWantToModify--;
- }
- tmpFsRecPtr = filesystemList;
+
/*
* Traverse the 'filesystemList' looking for the particular node
* whose 'fsPtr' member matches 'fsPtr' and remove that one from
* the list. Ensure that the "default" node cannot be removed.
*/
- while ((retVal == TCL_ERROR) && (tmpFsRecPtr != &nativeFilesystemRecord)) {
- if (tmpFsRecPtr->fsPtr == fsPtr) {
- if (prevFsRecPtr == NULL) {
- filesystemList = filesystemList->nextPtr;
+ fsRecPtr = filesystemList;
+ while ((retVal == TCL_ERROR) && (fsRecPtr != &nativeFilesystemRecord)) {
+ if (fsRecPtr->fsPtr == fsPtr) {
+ if (fsRecPtr->prevPtr) {
+ fsRecPtr->prevPtr->nextPtr = fsRecPtr->nextPtr;
} else {
- prevFsRecPtr->nextPtr = tmpFsRecPtr->nextPtr;
+ filesystemList = fsRecPtr->nextPtr;
+ }
+ if (fsRecPtr->nextPtr) {
+ fsRecPtr->nextPtr->prevPtr = fsRecPtr->prevPtr;
}
/*
* Increment the filesystem epoch counter, since existing
@@ -822,15 +850,14 @@ Tcl_FSUnregister(fsPtr)
*/
theFilesystemEpoch++;
- tmpFsRecPtr->fileRefCount--;
- if (tmpFsRecPtr->fileRefCount <= 0) {
- ckfree((char *)tmpFsRecPtr);
+ fsRecPtr->fileRefCount--;
+ if (fsRecPtr->fileRefCount <= 0) {
+ ckfree((char *)fsRecPtr);
}
retVal = TCL_OK;
} else {
- prevFsRecPtr = tmpFsRecPtr;
- tmpFsRecPtr = tmpFsRecPtr->nextPtr;
+ fsRecPtr = fsRecPtr->nextPtr;
}
}
@@ -1056,24 +1083,22 @@ Tcl_FSData(fsPtr)
Tcl_Filesystem *fsPtr; /* The filesystem record to query. */
{
ClientData retVal = NULL;
- FilesystemRecord *tmpFsRecPtr;
+ FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
- tmpFsRecPtr = FsGetIterator();
/*
* Traverse the 'filesystemList' looking for the particular node
* whose 'fsPtr' member matches 'fsPtr' and remove that one from
* the list. Ensure that the "default" node cannot be removed.
*/
- while ((retVal == NULL) && (tmpFsRecPtr != NULL)) {
- if (tmpFsRecPtr->fsPtr == fsPtr) {
- retVal = tmpFsRecPtr->clientData;
+ while ((retVal == NULL) && (fsRecPtr != NULL)) {
+ if (fsRecPtr->fsPtr == fsPtr) {
+ retVal = fsRecPtr->clientData;
}
- tmpFsRecPtr = tmpFsRecPtr->nextPtr;
+ fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
- return (retVal);
+ return retVal;
}
/*
@@ -1116,7 +1141,7 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
int startAt;
ClientData *clientDataPtr;
{
- FilesystemRecord *fsRecPtr;
+ FilesystemRecord *fsRecPtr, *firstFsRecPtr;
/* Ignore this variable */
(void)clientDataPtr;
@@ -1127,7 +1152,9 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
* is always a native filesystem (i.e. '/' on unix is native).
*/
- fsRecPtr = FsGetIterator();
+ firstFsRecPtr = FsGetFirstFilesystem();
+
+ fsRecPtr = firstFsRecPtr;
while (fsRecPtr != NULL) {
if (fsRecPtr == &nativeFilesystemRecord) {
Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;
@@ -1138,9 +1165,8 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
- fsRecPtr = FsGetIterator();
+ fsRecPtr = firstFsRecPtr;
while (fsRecPtr != NULL) {
/* Skip the native system next time through */
if (fsRecPtr != &nativeFilesystemRecord) {
@@ -1158,9 +1184,8 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
- return (startAt);
+ return startAt;
}
/*
@@ -2127,7 +2152,7 @@ Tcl_Obj*
Tcl_FSGetCwd(interp)
Tcl_Interp *interp;
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (TclFSCwdPointerEquals(NULL)) {
FilesystemRecord *fsRecPtr;
@@ -2140,7 +2165,7 @@ Tcl_FSGetCwd(interp)
* succeeded.
*/
- fsRecPtr = FsGetIterator();
+ fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSGetCwdProc *proc = fsRecPtr->fsPtr->getCwdProc;
if (proc != NULL) {
@@ -2148,7 +2173,6 @@ Tcl_FSGetCwd(interp)
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
/*
* Now the 'cwd' may NOT be normalized, at least on some
* platforms. For the sake of efficiency, we want a completely
@@ -2162,8 +2186,7 @@ Tcl_FSGetCwd(interp)
if (norm != NULL) {
/*
* We found a cwd, which is now in our global storage.
- * We must make a copy. Norm already has a refCount of
- * 1.
+ * We must make a copy. Norm already has a refCount of 1.
*
* Threading issue: note that multiple threads at system
* startup could in principle call this procedure
@@ -2770,7 +2793,7 @@ Tcl_FSListVolumes(void)
* a list of all drives from all filesystems.
*/
- fsRecPtr = FsGetIterator();
+ fsRecPtr = FsGetFirstFilesystem();
while (fsRecPtr != NULL) {
Tcl_FSListVolumesProc *proc = fsRecPtr->fsPtr->listVolumesProc;
if (proc != NULL) {
@@ -2782,7 +2805,6 @@ Tcl_FSListVolumes(void)
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
return resultPtr;
}
@@ -2886,22 +2908,20 @@ Tcl_FSSplitPath(pathPtr, lenPtr)
/* Simple helper function */
Tcl_Obj*
-TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr, epochPtr)
+TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr)
Tcl_Filesystem *fromFilesystem;
ClientData clientData;
FilesystemRecord **fsRecPtrPtr;
- int *epochPtr;
{
- FilesystemRecord *fsRecPtr = FsGetIterator();
+ FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
+
while (fsRecPtr != NULL) {
if (fsRecPtr->fsPtr == fromFilesystem) {
- *epochPtr = theFilesystemEpoch;
*fsRecPtrPtr = fsRecPtr;
break;
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
if ((fsRecPtr != NULL)
&& (fromFilesystem->internalToNormalizedProc != NULL)) {
@@ -2951,7 +2971,7 @@ GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
* matches).
*/
- fsRecPtr = FsGetIterator();
+ fsRecPtr = FsGetFirstFilesystem();
while (fsRecPtr != NULL) {
Tcl_FSListVolumesProc *proc = fsRecPtr->fsPtr->listVolumesProc;
/*
@@ -3025,7 +3045,6 @@ GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
if (type != TCL_PATH_ABSOLUTE) {
type = TclpGetNativePathType(pathObjPtr, driveNameLengthPtr,
@@ -3405,8 +3424,7 @@ Tcl_FSGetFileSystemForPath(pathObjPtr)
* Check if the filesystem has changed in some way since
* this object's internal representation was calculated.
*/
- if (TclFSEnsureEpochOk(pathObjPtr, theFilesystemEpoch,
- &retVal) != TCL_OK) {
+ if (TclFSEnsureEpochOk(pathObjPtr, &retVal) != TCL_OK) {
return NULL;
}
@@ -3416,7 +3434,7 @@ Tcl_FSGetFileSystemForPath(pathObjPtr)
* succeeded.
*/
- fsRecPtr = FsGetIterator();
+ fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSPathInFilesystemProc *proc = fsRecPtr->fsPtr->pathInFilesystemProc;
if (proc != NULL) {
@@ -3427,14 +3445,12 @@ Tcl_FSGetFileSystemForPath(pathObjPtr)
* We assume the type of pathObjPtr hasn't been changed
* by the above call to the pathInFilesystemProc.
*/
- TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData,
- theFilesystemEpoch);
+ TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData);
retVal = fsRecPtr->fsPtr;
}
}
fsRecPtr = fsRecPtr->nextPtr;
}
- FsReleaseIterator();
return retVal;
}
@@ -3812,7 +3828,7 @@ TclStatInsertProc (proc)
}
}
- return (retVal);
+ return retVal;
}
/*
@@ -3868,7 +3884,8 @@ TclStatDeleteProc (proc)
}
Tcl_MutexUnlock(&obsoleteFsHookMutex);
- return (retVal);
+
+ return retVal;
}
/*
@@ -3916,7 +3933,7 @@ TclAccessInsertProc(proc)
}
}
- return (retVal);
+ return retVal;
}
/*
@@ -3972,7 +3989,7 @@ TclAccessDeleteProc(proc)
}
Tcl_MutexUnlock(&obsoleteFsHookMutex);
- return (retVal);
+ return retVal;
}
/*
@@ -4079,6 +4096,6 @@ TclOpenFileChannelDeleteProc(proc)
}
Tcl_MutexUnlock(&obsoleteFsHookMutex);
- return (retVal);
+ return retVal;
}
#endif /* USE_OBSOLETE_FS_HOOKS */
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index cf9af4f..87ec24b 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.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: tclPathObj.c,v 1.5 2003/07/17 00:20:41 hobbs Exp $
+ * RCS: @(#) $Id: tclPathObj.c,v 1.6 2003/08/23 12:16:49 vasiljevic Exp $
*/
#include "tclInt.h"
@@ -24,14 +24,13 @@
* Prototypes for procedures defined later in this file.
*/
-static void DupFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static void FreeFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
-static void UpdateStringOfFsPath _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static int FindSplitPos _ANSI_ARGS_((char *path, char *separator));
-
+static void DupFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr));
+static void FreeFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
+static void UpdateStringOfFsPath _ANSI_ARGS_((Tcl_Obj *objPtr));
+static int SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr));
+static int FindSplitPos _ANSI_ARGS_((char *path, char *separator));
/*
@@ -504,6 +503,8 @@ Tcl_FSConvertToPathType(interp, objPtr)
Tcl_Obj *objPtr; /* Object to convert to a valid, current
* path type. */
{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
+
/*
* While it is bad practice to examine an object's type directly,
* this is actually the best thing to do here. The reason is that
@@ -515,7 +516,7 @@ Tcl_FSConvertToPathType(interp, objPtr)
*/
if (objPtr->typePtr == &tclFsPathType) {
FsPath *fsPathPtr = (FsPath*) PATHOBJ(objPtr);
- if (fsPathPtr->filesystemEpoch != theFilesystemEpoch) {
+ if (fsPathPtr->filesystemEpoch != tsdPtr->filesystemEpoch) {
if (objPtr->bytes == NULL) {
UpdateStringOfFsPath(objPtr);
}
@@ -609,6 +610,7 @@ TclNewFSPathObj(Tcl_Obj *dirPtr, CONST char *addStrRep, int len)
{
FsPath *fsPathPtr;
Tcl_Obj *objPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
objPtr = Tcl_NewObj();
fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
@@ -633,13 +635,14 @@ TclNewFSPathObj(Tcl_Obj *dirPtr, CONST char *addStrRep, int len)
Tcl_IncrRefCount(dirPtr);
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = theFilesystemEpoch;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
PATHOBJ(objPtr) = (VOID *) fsPathPtr;
PATHFLAGS(objPtr) = TCLPATH_RELATIVE | TCLPATH_APPENDED;
objPtr->typePtr = &tclFsPathType;
objPtr->bytes = NULL;
objPtr->length = 0;
+
return objPtr;
}
@@ -668,6 +671,7 @@ TclFSMakePathRelative(interp, objPtr, cwdPtr)
{
int cwdLen, len;
CONST char *tempStr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (objPtr->typePtr == &tclFsPathType) {
FsPath* fsPathPtr = (FsPath*) PATHOBJ(objPtr);
@@ -701,7 +705,7 @@ TclFSMakePathRelative(interp, objPtr, cwdPtr)
Tcl_IncrRefCount(cwdPtr);
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = theFilesystemEpoch;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
PATHOBJ(objPtr) = (VOID *) fsPathPtr;
PATHFLAGS(objPtr) = 0;
@@ -748,6 +752,7 @@ TclFSMakePathRelative(interp, objPtr, cwdPtr)
break;
}
tempStr = Tcl_GetStringFromObj(objPtr, &len);
+
return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
}
@@ -776,6 +781,7 @@ TclFSMakePathFromNormalized(interp, objPtr, nativeRep)
* else NULL. */
{
FsPath *fsPathPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (objPtr->typePtr == &tclFsPathType) {
return TCL_OK;
@@ -806,7 +812,7 @@ TclFSMakePathFromNormalized(interp, objPtr, nativeRep)
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = nativeRep;
fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = theFilesystemEpoch;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
PATHOBJ(objPtr) = (VOID *) fsPathPtr;
PATHFLAGS(objPtr) = 0;
@@ -850,11 +856,10 @@ Tcl_FSNewNativePath(fromFilesystem, clientData)
FsPath *fsPathPtr;
FilesystemRecord *fsFromPtr;
- int epoch;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
- objPtr = TclFSInternalToNormalized(fromFilesystem, clientData,
- &fsFromPtr, &epoch);
-
+ objPtr = TclFSInternalToNormalized(fromFilesystem, clientData,
+ &fsFromPtr);
if (objPtr == NULL) {
return NULL;
}
@@ -876,19 +881,20 @@ Tcl_FSNewNativePath(fromFilesystem, clientData)
}
fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
+
fsPathPtr->translatedPathPtr = NULL;
/* Circular reference, by design */
fsPathPtr->normPathPtr = objPtr;
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = clientData;
fsPathPtr->fsRecPtr = fsFromPtr;
- /* We must increase the refCount for this filesystem. */
fsPathPtr->fsRecPtr->fileRefCount++;
- fsPathPtr->filesystemEpoch = epoch;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
PATHOBJ(objPtr) = (VOID *) fsPathPtr;
PATHFLAGS(objPtr) = 0;
objPtr->typePtr = &tclFsPathType;
+
return objPtr;
}
@@ -917,7 +923,9 @@ Tcl_FSGetTranslatedPath(interp, pathPtr)
Tcl_Interp *interp;
Tcl_Obj* pathPtr;
{
- register FsPath* srcFsPathPtr;
+ Tcl_Obj *retObj = NULL;
+ FsPath *srcFsPathPtr;
+
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
@@ -932,11 +940,13 @@ Tcl_FSGetTranslatedPath(interp, pathPtr)
* object's string, translatedPath and normalizedPath
* are all identical.
*/
- return srcFsPathPtr->normPathPtr;
+ retObj = srcFsPathPtr->normPathPtr;
} else {
/* It is an ordinary path object */
- return srcFsPathPtr->translatedPathPtr;
+ retObj = srcFsPathPtr->translatedPathPtr;
}
+
+ return retObj;
}
/*
@@ -964,11 +974,12 @@ Tcl_FSGetTranslatedStringPath(interp, pathPtr)
Tcl_Obj* pathPtr;
{
Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
- if (transPtr == NULL) {
- return NULL;
- } else {
+
+ if (transPtr != NULL) {
return Tcl_GetString(transPtr);
}
+
+ return NULL;
}
/*
@@ -995,7 +1006,9 @@ Tcl_FSGetNormalizedPath(interp, pathObjPtr)
Tcl_Interp *interp;
Tcl_Obj* pathObjPtr;
{
- register FsPath* fsPathPtr;
+
+ FsPath *fsPathPtr;
+
if (Tcl_FSConvertToPathType(interp, pathObjPtr) != TCL_OK) {
return NULL;
}
@@ -1067,7 +1080,7 @@ Tcl_FSGetNormalizedPath(interp, pathObjPtr)
/* Now we need to construct the new path object */
if (pathType == TCL_PATH_RELATIVE) {
- register FsPath* origDirFsPathPtr;
+ FsPath* origDirFsPathPtr;
Tcl_Obj *origDir = fsPathPtr->cwdPtr;
origDirFsPathPtr = (FsPath*) PATHOBJ(origDir);
@@ -1209,6 +1222,7 @@ Tcl_FSGetNormalizedPath(interp, pathObjPtr)
fsPathPtr->cwdPtr = useThisCwd;
}
}
+
return fsPathPtr->normPathPtr;
}
@@ -1239,7 +1253,7 @@ Tcl_FSGetInternalRep(pathObjPtr, fsPtr)
Tcl_Obj* pathObjPtr;
Tcl_Filesystem *fsPtr;
{
- register FsPath* srcFsPathPtr;
+ FsPath* srcFsPathPtr;
if (Tcl_FSConvertToPathType(NULL, pathObjPtr) != TCL_OK) {
return NULL;
@@ -1309,6 +1323,7 @@ Tcl_FSGetInternalRep(pathObjPtr, fsPtr)
}
srcFsPathPtr->nativePathPtr = (*proc)(pathObjPtr);
}
+
return srcFsPathPtr->nativePathPtr;
}
@@ -1332,12 +1347,12 @@ Tcl_FSGetInternalRep(pathObjPtr, fsPtr)
*/
int
-TclFSEnsureEpochOk(pathObjPtr, theEpoch, fsPtrPtr)
+TclFSEnsureEpochOk(pathObjPtr, fsPtrPtr)
Tcl_Obj* pathObjPtr;
- int theEpoch;
Tcl_Filesystem **fsPtrPtr;
{
FsPath* srcFsPathPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
/*
* SHOULD BE ABLE TO IMPROVE EFFICIENCY HERE.
@@ -1353,7 +1368,7 @@ TclFSEnsureEpochOk(pathObjPtr, theEpoch, fsPtrPtr)
* Check if the filesystem has changed in some way since
* this object's internal representation was calculated.
*/
- if (srcFsPathPtr->filesystemEpoch != theEpoch) {
+ if (srcFsPathPtr->filesystemEpoch != tsdPtr->filesystemEpoch) {
/*
* We have to discard the stale representation and
* recalculate it
@@ -1372,23 +1387,24 @@ TclFSEnsureEpochOk(pathObjPtr, theEpoch, fsPtrPtr)
if (srcFsPathPtr->fsRecPtr != NULL) {
*fsPtrPtr = srcFsPathPtr->fsRecPtr->fsPtr;
}
+
return TCL_OK;
}
void
-TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData, theEpoch)
+TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData)
Tcl_Obj *pathObjPtr;
FilesystemRecord *fsRecPtr;
ClientData clientData;
- int theEpoch;
{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
/* We assume pathObjPtr is already of the correct type */
FsPath* srcFsPathPtr;
srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
srcFsPathPtr->fsRecPtr = fsRecPtr;
srcFsPathPtr->nativePathPtr = clientData;
- srcFsPathPtr->filesystemEpoch = theEpoch;
+ srcFsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
fsRecPtr->fileRefCount++;
}
@@ -1447,6 +1463,7 @@ Tcl_FSEqualPaths(firstPtr, secondPtr)
return 1;
}
}
+
return 0;
}
@@ -1480,6 +1497,7 @@ SetFsPathFromAny(interp, objPtr)
FsPath *fsPathPtr;
Tcl_Obj *transPtr;
char *name;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (objPtr->typePtr == &tclFsPathType) {
return TCL_OK;
@@ -1617,13 +1635,14 @@ SetFsPathFromAny(interp, objPtr)
*/
fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
+
fsPathPtr->translatedPathPtr = transPtr;
Tcl_IncrRefCount(fsPathPtr->translatedPathPtr);
fsPathPtr->normPathPtr = NULL;
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = theFilesystemEpoch;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
/*
* Free old representation before installing our new one.
@@ -1642,7 +1661,7 @@ static void
FreeFsPathInternalRep(pathObjPtr)
Tcl_Obj *pathObjPtr; /* Path object with internal rep to free. */
{
- register FsPath* fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
+ FsPath* fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
if (fsPathPtr->translatedPathPtr != NULL) {
if (fsPathPtr->translatedPathPtr != pathObjPtr) {
@@ -1684,9 +1703,9 @@ DupFsPathInternalRep(srcPtr, copyPtr)
Tcl_Obj *srcPtr; /* Path obj with internal rep to copy. */
Tcl_Obj *copyPtr; /* Path obj with internal rep to set. */
{
- register FsPath* srcFsPathPtr = (FsPath*) PATHOBJ(srcPtr);
- register FsPath* copyFsPathPtr =
- (FsPath*) ckalloc((unsigned)sizeof(FsPath));
+ FsPath* srcFsPathPtr = (FsPath*) PATHOBJ(srcPtr);
+ FsPath* copyFsPathPtr = (FsPath*) ckalloc((unsigned)sizeof(FsPath));
+
Tcl_FSDupInternalRepProc *dupProc;
PATHOBJ(copyPtr) = (VOID *) copyFsPathPtr;
@@ -1759,7 +1778,7 @@ static void
UpdateStringOfFsPath(objPtr)
register Tcl_Obj *objPtr; /* path obj with string rep to update. */
{
- register FsPath* fsPathPtr = (FsPath*) PATHOBJ(objPtr);
+ FsPath* fsPathPtr = (FsPath*) PATHOBJ(objPtr);
CONST char *cwdStr;
int cwdLen;
Tcl_Obj *copy;