summaryrefslogtreecommitdiffstats
path: root/generic/tclIOUtil.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2012-06-18 20:36:22 (GMT)
committerdgp <dgp@users.sourceforge.net>2012-06-18 20:36:22 (GMT)
commit5f8dff42ac6dc46d1aca06a1e94c41ac27c41cf2 (patch)
tree93369c28778113da82130ef8b20103751b842d11 /generic/tclIOUtil.c
parentd175d3a8425c48ce4739f167b9a6eb80d3678685 (diff)
downloadtcl-5f8dff42ac6dc46d1aca06a1e94c41ac27c41cf2.zip
tcl-5f8dff42ac6dc46d1aca06a1e94c41ac27c41cf2.tar.gz
tcl-5f8dff42ac6dc46d1aca06a1e94c41ac27c41cf2.tar.bz2
Next draft fix. This one appears to solve the problem, at least as demo'd
by the test attached to Tcl Bug 3024359.
Diffstat (limited to 'generic/tclIOUtil.c')
-rw-r--r--generic/tclIOUtil.c86
1 files changed, 40 insertions, 46 deletions
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index d98e760..80eccbf 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -40,10 +40,9 @@ static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr,
static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData);
static void FsRecacheFilesystemList(void);
-static void Purge(FilesystemRecord *fsRecPtr);
+static void Claim(void);
+static void Disclaim(void);
-#define Claim() (tsdPtr->claims++)
-#define Disclaim() if (--tsdPtr->claims <= 0) Purge(tsdPtr->filesystemList);
/*
* These form part of the native filesystem support. They are needed here
@@ -589,23 +588,31 @@ static void
FsRecacheFilesystemList(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL;
+ FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *chain = NULL;
/*
* Trash the current cache.
*/
+ fsRecPtr = tsdPtr->filesystemList;
if (tsdPtr->claims <= 0) {
- fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
- tmpFsRecPtr = fsRecPtr->nextPtr;
+ tmpFsRecPtr = fsRecPtr->nextPtr;
if (--fsRecPtr->fileRefCount <= 0) {
ckfree((char *)fsRecPtr);
}
fsRecPtr = tmpFsRecPtr;
}
- tsdPtr->filesystemList = NULL;
+ } else {
+ chain = fsRecPtr;
+ while (fsRecPtr->nextPtr != NULL) {
+ fsRecPtr->prevPtr = fsRecPtr->nextPtr;
+ fsRecPtr->nextPtr = NULL;
+ fsRecPtr = fsRecPtr->prevPtr;
+ }
+ fsRecPtr->prevPtr = fsRecPtr;
}
+ tsdPtr->filesystemList = NULL;
/*
* Locate tail of the global filesystem list.
@@ -627,7 +634,8 @@ FsRecacheFilesystemList(void)
tmpFsRecPtr = (FilesystemRecord *) ckalloc(sizeof(FilesystemRecord));
*tmpFsRecPtr = *fsRecPtr;
tmpFsRecPtr->nextPtr = tsdPtr->filesystemList;
- tmpFsRecPtr->prevPtr = NULL;
+ tmpFsRecPtr->prevPtr = chain;
+ chain = NULL;
tsdPtr->filesystemList = tmpFsRecPtr;
fsRecPtr = fsRecPtr->prevPtr;
}
@@ -668,24 +676,39 @@ TclFSEpochOk(
}
static void
-Purge(
- FilesystemRecord *fsRecPtr)
+Claim()
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ tsdPtr->claims++;
+}
+
+static void
+Disclaim()
{
- FilesystemRecord *toRelease;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+ FilesystemRecord *fsRecPtr, *toRelease, *lastCurrent;
+
+ if (--tsdPtr->claims > 0) {
+ return;
+ }
+ fsRecPtr = tsdPtr->filesystemList;
/*
* Release all out of date FilesystemRecords.
* First skip the current list.
*/
- while (fsRecPtr->fsPtr != &tclNativeFilesystem) {
+ while (fsRecPtr->nextPtr != NULL) {
fsRecPtr = fsRecPtr->nextPtr;
}
/* Then release everything that comes after. */
- toRelease = fsRecPtr->nextPtr;
+ lastCurrent = fsRecPtr;
+ toRelease = lastCurrent->prevPtr;
+ lastCurrent->prevPtr = NULL;
while (toRelease != NULL) {
- fsRecPtr = toRelease->nextPtr;
-
+ fsRecPtr = (toRelease == toRelease->prevPtr) ? NULL
+ : toRelease->prevPtr;
if (--toRelease->fileRefCount <= 0) {
ckfree((char *)toRelease);
}
@@ -1384,9 +1407,6 @@ Tcl_FSData(
if (fsRecPtr->fsPtr == fsPtr) {
retVal = fsRecPtr->clientData;
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
@@ -1432,7 +1452,6 @@ TclFSNormalizeToUniquePath(
* for a given filesystem, we can optionally
* return an fs-specific clientdata here. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr, *firstFsRecPtr;
/* Ignore this variable */
(void) clientDataPtr;
@@ -1465,9 +1484,7 @@ TclFSNormalizeToUniquePath(
* Skip the native system next time through.
*/
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- } else {
+ if (fsRecPtr->fsPtr != &tclNativeFilesystem) {
Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;
if (proc != NULL) {
startAt = (*proc)(interp, pathPtr, startAt);
@@ -2714,6 +2731,7 @@ Tcl_FSGetCwd(
}
Tcl_DecrRefCount(retVal);
retVal = NULL;
+ Disclaim();
goto cdDidNotChange;
} else if (interp != NULL) {
Tcl_AppendResult(interp,
@@ -2724,9 +2742,6 @@ Tcl_FSGetCwd(
retVal = (*proc)(interp);
}
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();
@@ -3665,7 +3680,6 @@ Tcl_FSLink(
Tcl_Obj*
Tcl_FSListVolumes(void)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr;
Tcl_Obj *resultPtr = Tcl_NewObj();
@@ -3687,9 +3701,6 @@ Tcl_FSListVolumes(void)
Tcl_DecrRefCount(thisFsVolumes);
}
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();
@@ -3720,7 +3731,6 @@ FsListMounts(
Tcl_Obj *pathPtr, /* Contains path to directory to search. */
const char *pattern) /* Pattern to match against. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr;
Tcl_GlobTypeData mountsOnly = { TCL_GLOB_TYPE_MOUNT, 0, NULL, NULL };
Tcl_Obj *resultPtr = NULL;
@@ -3745,9 +3755,6 @@ FsListMounts(
(*proc)(NULL, resultPtr, pathPtr, pattern, &mountsOnly);
}
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();
@@ -3867,7 +3874,6 @@ TclFSInternalToNormalized(
ClientData clientData,
FilesystemRecord **fsRecPtrPtr)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
Claim();
@@ -3876,10 +3882,6 @@ TclFSInternalToNormalized(
*fsRecPtrPtr = fsRecPtr;
break;
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- fsRecPtr = NULL;
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();
@@ -3985,7 +3987,6 @@ TclFSNonnativePathType(
* path, already with a refCount for the
* caller. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr;
Tcl_PathType type = TCL_PATH_RELATIVE;
@@ -4073,9 +4074,6 @@ TclFSNonnativePathType(
}
}
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();
@@ -4446,7 +4444,6 @@ Tcl_Filesystem *
Tcl_FSGetFileSystemForPath(
Tcl_Obj* pathPtr)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr;
Tcl_Filesystem* retVal = NULL;
@@ -4501,9 +4498,6 @@ Tcl_FSGetFileSystemForPath(
retVal = fsRecPtr->fsPtr;
}
}
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
- break;
- }
fsRecPtr = fsRecPtr->nextPtr;
}
Disclaim();