diff options
author | dgp <dgp@users.sourceforge.net> | 2012-06-25 14:43:36 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2012-06-25 14:43:36 (GMT) |
commit | c56279aca031cd571054139f95be82bb90c7dbfa (patch) | |
tree | c871ead30ab5ffe77b435d00aead35267d1695d9 /generic | |
parent | 01eab1b3890706a987bfd038c2193a060660d823 (diff) | |
parent | 527a4f67fa396747502ba37514a882725f401110 (diff) | |
download | tcl-c56279aca031cd571054139f95be82bb90c7dbfa.zip tcl-c56279aca031cd571054139f95be82bb90c7dbfa.tar.gz tcl-c56279aca031cd571054139f95be82bb90c7dbfa.tar.bz2 |
Simplify bug fix so that active claims on the FilesystemRecord list of a threadbug_3024359
prevent any overwriting of that per-thread cache. This keeps active traversals
of the list valid. The possible downside is that this may result in some delay
in noticing new epochs and result in somewhat greater likelihood we will cache
things in a "path" value that are out of date. Since the system has to deal
with out of date cached data anyway, this should have no correctness affects,
measured against the status quo. In multi-threaded operation the possibility
of caching and/or retrieving outdated information can never be eliminated.
Checkin also includes merge of 8.5.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclCmdAH.c | 18 | ||||
-rw-r--r-- | generic/tclIOUtil.c | 69 | ||||
-rw-r--r-- | generic/tclPathObj.c | 3 |
3 files changed, 29 insertions, 61 deletions
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index e1ec927..8e32389 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -505,7 +505,7 @@ Tcl_EncodingObjCmd( break; } case ENC_DIRS: - return EncodingDirsObjCmd(dummy, interp, objc-1, objv+1); + return EncodingDirsObjCmd(dummy, interp, objc, objv); case ENC_NAMES: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); @@ -552,20 +552,24 @@ EncodingDirsObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "?dirList?"); + Tcl_Obj *dirListObj; + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?dirList?"); return TCL_ERROR; } - if (objc == 1) { + if (objc == 2) { Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath()); return TCL_OK; } - if (Tcl_SetEncodingSearchPath(objv[1]) == TCL_ERROR) { + + dirListObj = objv[2]; + if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) { Tcl_AppendResult(interp, "expected directory list but got \"", - TclGetString(objv[1]), "\"", NULL); + TclGetString(dirListObj), "\"", NULL); return TCL_ERROR; } - Tcl_SetObjResult(interp, objv[1]); + Tcl_SetObjResult(interp, dirListObj); return TCL_OK; } diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 9d81d18..dccbeb5 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -586,31 +586,19 @@ static void FsRecacheFilesystemList(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey); - FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *chain = NULL; + FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *list; /* * Trash the current cache. */ fsRecPtr = tsdPtr->filesystemList; - if (tsdPtr->claims <= 0) { - while (fsRecPtr != NULL) { - tmpFsRecPtr = fsRecPtr->nextPtr; - fsRecPtr->fsPtr = NULL; - fsRecPtr->nextPtr = toFree; - toFree = fsRecPtr; - fsRecPtr = tmpFsRecPtr; - } - } else { - chain = fsRecPtr; - while (fsRecPtr->nextPtr != NULL) { - fsRecPtr->prevPtr = fsRecPtr->nextPtr; - fsRecPtr->nextPtr = NULL; - fsRecPtr = fsRecPtr->prevPtr; - } - fsRecPtr->prevPtr = fsRecPtr; + while (fsRecPtr != NULL) { + tmpFsRecPtr = fsRecPtr->nextPtr; + fsRecPtr->nextPtr = toFree; + toFree = fsRecPtr; + fsRecPtr = tmpFsRecPtr; } - tsdPtr->filesystemList = NULL; /* * Locate tail of the global filesystem list. @@ -627,24 +615,26 @@ 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->prevPtr = chain; - chain = NULL; - tsdPtr->filesystemList = tmpFsRecPtr; + tmpFsRecPtr->nextPtr = list; + tmpFsRecPtr->prevPtr = NULL; + 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; } - tsdPtr->filesystemEpoch = theFilesystemEpoch; - Tcl_MutexUnlock(&filesystemMutex); /* * Make sure the above gets released on thread exit. @@ -660,8 +650,8 @@ static FilesystemRecord * FsGetFirstFilesystem(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey); - if (tsdPtr->filesystemList == NULL - || (tsdPtr->filesystemEpoch != theFilesystemEpoch)) { + if (tsdPtr->filesystemList == NULL || ((tsdPtr->claims == 0) + && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) { FsRecacheFilesystemList(); } return tsdPtr->filesystemList; @@ -683,7 +673,6 @@ static void Claim() { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey); - tsdPtr->claims++; } @@ -691,31 +680,7 @@ static void Disclaim() { 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->nextPtr != NULL) { - fsRecPtr = fsRecPtr->nextPtr; - } - - /* Then release everything that comes after. */ - lastCurrent = fsRecPtr; - toRelease = lastCurrent->prevPtr; - lastCurrent->prevPtr = NULL; - while (toRelease != NULL) { - fsRecPtr = (toRelease == toRelease->prevPtr) ? NULL - : toRelease->prevPtr; - ckfree((char *)toRelease); - toRelease = fsRecPtr; - } + tsdPtr->claims--; } /* diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index 66cc617..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: { /* |