summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2012-06-25 15:19:52 (GMT)
committerdgp <dgp@users.sourceforge.net>2012-06-25 15:19:52 (GMT)
commitb0f256541bc7a9e4221bcf6500e83e8cf5c250d6 (patch)
tree737b11acc146f4cce01056bd8523581a7d4a0ad0
parent527a4f67fa396747502ba37514a882725f401110 (diff)
parentc56279aca031cd571054139f95be82bb90c7dbfa (diff)
downloadtcl-b0f256541bc7a9e4221bcf6500e83e8cf5c250d6.zip
tcl-b0f256541bc7a9e4221bcf6500e83e8cf5c250d6.tar.gz
tcl-b0f256541bc7a9e4221bcf6500e83e8cf5c250d6.tar.bz2
3024359 Make sure that the per-thread cache of the list of file systems
currently registered is only updated at times when no active loops are traversing it. Also reduce the amount of epoch storing and checking to where it can make a difference.
-rw-r--r--ChangeLog8
-rw-r--r--generic/tclFileSystem.h1
-rw-r--r--generic/tclIOUtil.c76
-rw-r--r--generic/tclPathObj.c20
4 files changed, 68 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index e2ca3f2..60c74ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-06-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclFileSystem.h: [Bug 3024359] Make sure that the
+ * generic/tclIOUtil.c: per-thread cache of the list of file systems
+ * generic/tclPathObj.c: currently registered is only updated at times
+ when no active loops are traversing it. Also reduce the amount of
+ epoch storing and checking to where it can make a difference.
+
2012-06-25 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCmdAH.c (EncodingDirsObjCmd): [Bug 3537605]: Do the right
diff --git a/generic/tclFileSystem.h b/generic/tclFileSystem.h
index c50c751..828e81d 100644
--- a/generic/tclFileSystem.h
+++ b/generic/tclFileSystem.h
@@ -51,6 +51,7 @@ typedef struct ThreadSpecificData {
Tcl_Obj *cwdPathPtr;
ClientData cwdClientData;
FilesystemRecord *filesystemList;
+ int claims;
} ThreadSpecificData;
/*
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 9e36d64..dccbeb5 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -39,9 +39,10 @@ static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr,
Tcl_GlobTypeData *types);
static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData);
-#ifdef TCL_THREADS
static void FsRecacheFilesystemList(void);
-#endif
+static void Claim(void);
+static void Disclaim(void);
+
/*
* These form part of the native filesystem support. They are needed here
@@ -409,7 +410,7 @@ static FilesystemRecord nativeFilesystemRecord = {
* trigger cache cleanup in all threads.
*/
-static int theFilesystemEpoch = 0;
+static int theFilesystemEpoch = 1;
/*
* Stores the linked list of filesystems. A 1:1 copy of this list is also
@@ -581,12 +582,11 @@ TclFSCwdPointerEquals(
}
}
-#ifdef TCL_THREADS
static void
FsRecacheFilesystemList(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL;
+ FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *list;
/*
* Trash the current cache.
@@ -595,20 +595,16 @@ FsRecacheFilesystemList(void)
fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr->nextPtr;
- fsRecPtr->fsPtr = NULL;
fsRecPtr->nextPtr = toFree;
toFree = fsRecPtr;
fsRecPtr = tmpFsRecPtr;
}
- tsdPtr->filesystemList = NULL;
/*
- * Code below operates on shared data. We are already called under mutex
- * lock so we can safely proceed.
- *
* Locate tail of the global filesystem list.
*/
+ Tcl_MutexLock(&filesystemMutex);
fsRecPtr = filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr;
@@ -619,21 +615,23 @@ FsRecacheFilesystemList(void)
* Refill the cache honouring the order.
*/
+ list = NULL;
fsRecPtr = tmpFsRecPtr;
while (fsRecPtr != NULL) {
tmpFsRecPtr = (FilesystemRecord *) ckalloc(sizeof(FilesystemRecord));
*tmpFsRecPtr = *fsRecPtr;
- tmpFsRecPtr->nextPtr = tsdPtr->filesystemList;
+ tmpFsRecPtr->nextPtr = list;
tmpFsRecPtr->prevPtr = NULL;
- if (tsdPtr->filesystemList) {
- tsdPtr->filesystemList->prevPtr = tmpFsRecPtr;
- }
- tsdPtr->filesystemList = tmpFsRecPtr;
+ list = tmpFsRecPtr;
fsRecPtr = fsRecPtr->prevPtr;
}
+ tsdPtr->filesystemList = list;
+ tsdPtr->filesystemEpoch = theFilesystemEpoch;
+ Tcl_MutexUnlock(&filesystemMutex);
while (toFree) {
FilesystemRecord *next = toFree->nextPtr;
+ toFree->fsPtr = NULL;
ckfree((char *)toFree);
toFree = next;
}
@@ -647,27 +645,16 @@ FsRecacheFilesystemList(void)
tsdPtr->initialized = 1;
}
}
-#endif /* TCL_THREADS */
static FilesystemRecord *
FsGetFirstFilesystem(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- FilesystemRecord *fsRecPtr;
-#ifndef TCL_THREADS
- tsdPtr->filesystemEpoch = theFilesystemEpoch;
- fsRecPtr = filesystemList;
-#else
- Tcl_MutexLock(&filesystemMutex);
- if (tsdPtr->filesystemList == NULL
- || (tsdPtr->filesystemEpoch != theFilesystemEpoch)) {
+ if (tsdPtr->filesystemList == NULL || ((tsdPtr->claims == 0)
+ && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) {
FsRecacheFilesystemList();
- tsdPtr->filesystemEpoch = theFilesystemEpoch;
}
- Tcl_MutexUnlock(&filesystemMutex);
- fsRecPtr = tsdPtr->filesystemList;
-#endif
- return fsRecPtr;
+ return tsdPtr->filesystemList;
}
/*
@@ -679,9 +666,21 @@ int
TclFSEpochOk(
int filesystemEpoch)
{
+ return (filesystemEpoch == 0 || filesystemEpoch == theFilesystemEpoch);
+}
+
+static void
+Claim()
+{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- (void) FsGetFirstFilesystem();
- return (filesystemEpoch == tsdPtr->filesystemEpoch);
+ tsdPtr->claims++;
+}
+
+static void
+Disclaim()
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+ tsdPtr->claims--;
}
/*
@@ -799,6 +798,7 @@ TclFinalizeFilesystem(void)
}
fsRecPtr = tmpFsRecPtr;
}
+ theFilesystemEpoch++;
filesystemList = NULL;
/*
@@ -836,6 +836,7 @@ void
TclResetFilesystem(void)
{
filesystemList = &nativeFilesystemRecord;
+ theFilesystemEpoch++;
#ifdef __WIN32__
/*
@@ -1408,6 +1409,7 @@ TclFSNormalizeToUniquePath(
firstFsRecPtr = FsGetFirstFilesystem();
+ Claim();
fsRecPtr = firstFsRecPtr;
while (fsRecPtr != NULL) {
if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
@@ -1440,6 +1442,7 @@ TclFSNormalizeToUniquePath(
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
return startAt;
}
@@ -2634,6 +2637,7 @@ Tcl_FSGetCwd(
*/
fsRecPtr = FsGetFirstFilesystem();
+ Claim();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSGetCwdProc *proc = fsRecPtr->fsPtr->getCwdProc;
if (proc != NULL) {
@@ -2671,6 +2675,7 @@ Tcl_FSGetCwd(
}
Tcl_DecrRefCount(retVal);
retVal = NULL;
+ Disclaim();
goto cdDidNotChange;
} else if (interp != NULL) {
Tcl_AppendResult(interp,
@@ -2683,6 +2688,7 @@ Tcl_FSGetCwd(
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
/*
* Now the 'cwd' may NOT be normalized, at least on some platforms.
@@ -3628,6 +3634,7 @@ Tcl_FSListVolumes(void)
*/
fsRecPtr = FsGetFirstFilesystem();
+ Claim();
while (fsRecPtr != NULL) {
Tcl_FSListVolumesProc *proc = fsRecPtr->fsPtr->listVolumesProc;
if (proc != NULL) {
@@ -3639,6 +3646,7 @@ Tcl_FSListVolumes(void)
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
return resultPtr;
}
@@ -3678,6 +3686,7 @@ FsListMounts(
*/
fsRecPtr = FsGetFirstFilesystem();
+ Claim();
while (fsRecPtr != NULL) {
if (fsRecPtr->fsPtr != &tclNativeFilesystem) {
Tcl_FSMatchInDirectoryProc *proc =
@@ -3691,6 +3700,7 @@ FsListMounts(
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
return resultPtr;
}
@@ -3903,6 +3913,7 @@ TclFSNonnativePathType(
*/
fsRecPtr = FsGetFirstFilesystem();
+ Claim();
while (fsRecPtr != NULL) {
Tcl_FSListVolumesProc *proc = fsRecPtr->fsPtr->listVolumesProc;
@@ -3981,6 +3992,7 @@ TclFSNonnativePathType(
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
return type;
}
@@ -4375,6 +4387,7 @@ Tcl_FSGetFileSystemForPath(
*/
fsRecPtr = FsGetFirstFilesystem();
+ Claim();
if (TclFSEnsureEpochOk(pathPtr, &retVal) != TCL_OK) {
return NULL;
@@ -4403,6 +4416,7 @@ Tcl_FSGetFileSystemForPath(
}
fsRecPtr = fsRecPtr->nextPtr;
}
+ Disclaim();
return retVal;
}
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 7911dea..4e1172a 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -563,8 +563,7 @@ TclPathPart(
if (pathPtr->typePtr == &tclFsPathType) {
FsPath *fsPathPtr = PATHOBJ(pathPtr);
- if (TclFSEpochOk(fsPathPtr->filesystemEpoch)
- && (PATHFLAGS(pathPtr) != 0)) {
+ if (PATHFLAGS(pathPtr) != 0) {
switch (portion) {
case TCL_PATH_DIRNAME: {
/*
@@ -1311,7 +1310,7 @@ TclNewFSPathObj(
Tcl_IncrRefCount(dirPtr);
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+ fsPathPtr->filesystemEpoch = 0;
SETPATHOBJ(pathPtr, fsPathPtr);
PATHFLAGS(pathPtr) = TCLPATH_APPENDED;
@@ -1417,7 +1416,6 @@ TclFSMakePathRelative(
{
int cwdLen, len;
const char *tempStr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
if (pathPtr->typePtr == &tclFsPathType) {
FsPath *fsPathPtr = PATHOBJ(pathPtr);
@@ -1481,7 +1479,7 @@ TclFSMakePathRelative(
Tcl_IncrRefCount(cwdPtr);
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+ fsPathPtr->filesystemEpoch = 0;
SETPATHOBJ(pathPtr, fsPathPtr);
PATHFLAGS(pathPtr) = 0;
@@ -1591,6 +1589,7 @@ TclFSMakePathFromNormalized(
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsPtr = NULL;
+ /* Remember the epoch under which we decided pathPtr was normalized */
fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
SETPATHOBJ(pathPtr, fsPathPtr);
@@ -1727,6 +1726,12 @@ Tcl_FSGetTranslatedPath(
retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
&(srcFsPathPtr->normPathPtr));
srcFsPathPtr->translatedPathPtr = retObj;
+ if (translatedCwdPtr->typePtr == &tclFsPathType) {
+ srcFsPathPtr->filesystemEpoch
+ = PATHOBJ(translatedCwdPtr)->filesystemEpoch;
+ } else {
+ srcFsPathPtr->filesystemEpoch = 0;
+ }
Tcl_IncrRefCount(retObj);
Tcl_DecrRefCount(translatedCwdPtr);
} else {
@@ -2527,12 +2532,15 @@ SetFsPathFromAny(
fsPathPtr->translatedPathPtr = transPtr;
if (transPtr != pathPtr) {
Tcl_IncrRefCount(fsPathPtr->translatedPathPtr);
+ /* Redo translation when $env(HOME) changes */
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+ } else {
+ fsPathPtr->filesystemEpoch = 0;
}
fsPathPtr->normPathPtr = NULL;
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = NULL;
fsPathPtr->fsPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
/*
* Free old representation before installing our new one.