| ︙ | | | ︙ | |
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
* 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;
ClientData cwdClientData;
FilesystemRecord *filesystemList;
int claims;
} ThreadSpecificData;
/*
* Prototypes for functions defined later in this file.
*/
static int EvalFileCallback(ClientData data[],
|
|
|
|
|
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
* 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;
size_t cwdPathEpoch;
size_t filesystemEpoch;
Tcl_Obj *cwdPathPtr;
ClientData cwdClientData;
FilesystemRecord *filesystemList;
size_t claims;
} ThreadSpecificData;
/*
* Prototypes for functions defined later in this file.
*/
static int EvalFileCallback(ClientData data[],
|
| ︙ | | | ︙ | |
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
/*
* 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.
*/
static int theFilesystemEpoch = 1;
/*
* 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;
TCL_DECLARE_MUTEX(filesystemMutex)
/*
* Used to implement Tcl_FSGetCwd in a file-system independent way.
*/
static Tcl_Obj *cwdPathPtr = NULL;
static int cwdPathEpoch = 0;
static ClientData cwdClientData = NULL;
TCL_DECLARE_MUTEX(cwdMutex)
static Tcl_ThreadDataKey fsDataKey;
/*
* One of these structures is used each time we successfully load a file from
|
|
|
|
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
/*
* 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.
*/
static size_t theFilesystemEpoch = 1;
/*
* 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;
TCL_DECLARE_MUTEX(filesystemMutex)
/*
* Used to implement Tcl_FSGetCwd in a file-system independent way.
*/
static Tcl_Obj *cwdPathPtr = NULL;
static size_t cwdPathEpoch = 0;
static ClientData cwdClientData = NULL;
TCL_DECLARE_MUTEX(cwdMutex)
static Tcl_ThreadDataKey fsDataKey;
/*
* One of these structures is used each time we successfully load a file from
|
| ︙ | | | ︙ | |
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
|
/*
* The epoch can be changed both by filesystems being added or removed and by
* env(HOME) changing.
*/
int
TclFSEpochOk(
int filesystemEpoch)
{
return (filesystemEpoch == 0 || filesystemEpoch == theFilesystemEpoch);
}
static void
Claim(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
tsdPtr->claims++;
}
static void
Disclaim(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
tsdPtr->claims--;
}
int
TclFSEpoch(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
return tsdPtr->filesystemEpoch;
}
|
|
|
|
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
|
/*
* The epoch can be changed both by filesystems being added or removed and by
* env(HOME) changing.
*/
int
TclFSEpochOk(
size_t filesystemEpoch)
{
return (filesystemEpoch == 0 || filesystemEpoch == theFilesystemEpoch);
}
static void
Claim(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
tsdPtr->claims++;
}
static void
Disclaim(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
tsdPtr->claims--;
}
size_t
TclFSEpoch(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
return tsdPtr->filesystemEpoch;
}
|
| ︙ | | | ︙ | |
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
|
*/
cwdPathPtr = Tcl_NewStringObj(str, len);
Tcl_IncrRefCount(cwdPathPtr);
cwdClientData = TclNativeDupInternalRep(clientData);
}
cwdPathEpoch++;
tsdPtr->cwdPathEpoch = cwdPathEpoch;
Tcl_MutexUnlock(&cwdMutex);
if (tsdPtr->cwdPathPtr) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
}
if (tsdPtr->cwdClientData) {
|
>
|
>
|
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
|
*/
cwdPathPtr = Tcl_NewStringObj(str, len);
Tcl_IncrRefCount(cwdPathPtr);
cwdClientData = TclNativeDupInternalRep(clientData);
}
if (++cwdPathEpoch == 0) {
++cwdPathEpoch;
}
tsdPtr->cwdPathEpoch = cwdPathEpoch;
Tcl_MutexUnlock(&cwdMutex);
if (tsdPtr->cwdPathPtr) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
}
if (tsdPtr->cwdClientData) {
|
| ︙ | | | ︙ | |
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
|
if (fsRecPtr != &nativeFilesystemRecord) {
ckfree(fsRecPtr);
}
fsRecPtr = tmpFsRecPtr;
}
if (++theFilesystemEpoch == 0) {
theFilesystemEpoch = 1;
}
filesystemList = NULL;
/*
* Now filesystemList is NULL. This means that any attempt to use the
* filesystem is likely to fail.
*/
|
|
|
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
|
if (fsRecPtr != &nativeFilesystemRecord) {
ckfree(fsRecPtr);
}
fsRecPtr = tmpFsRecPtr;
}
if (++theFilesystemEpoch == 0) {
++theFilesystemEpoch;
}
filesystemList = NULL;
/*
* Now filesystemList is NULL. This means that any attempt to use the
* filesystem is likely to fail.
*/
|
| ︙ | | | ︙ | |
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
|
*/
void
TclResetFilesystem(void)
{
filesystemList = &nativeFilesystemRecord;
if (++theFilesystemEpoch == 0) {
theFilesystemEpoch = 1;
}
#ifdef _WIN32
/*
* Cleans up the win32 API filesystem proc lookup table. This must happen
* very late in finalization so that deleting of copied dlls can occur.
*/
|
|
|
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
|
*/
void
TclResetFilesystem(void)
{
filesystemList = &nativeFilesystemRecord;
if (++theFilesystemEpoch == 0) {
++theFilesystemEpoch;
}
#ifdef _WIN32
/*
* Cleans up the win32 API filesystem proc lookup table. This must happen
* very late in finalization so that deleting of copied dlls can occur.
*/
|
| ︙ | | | ︙ | |
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
|
/*
* Increment the filesystem epoch counter, since existing paths might
* conceivably now belong to different filesystems.
*/
if (++theFilesystemEpoch == 0) {
theFilesystemEpoch = 1;
}
Tcl_MutexUnlock(&filesystemMutex);
return TCL_OK;
}
/*
|
|
|
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
|
/*
* Increment the filesystem epoch counter, since existing paths might
* conceivably now belong to different filesystems.
*/
if (++theFilesystemEpoch == 0) {
++theFilesystemEpoch;
}
Tcl_MutexUnlock(&filesystemMutex);
return TCL_OK;
}
/*
|
| ︙ | | | ︙ | |
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
|
* might conceivably now belong to different filesystems. This
* should also ensure that paths which have cached the filesystem
* which is about to be deleted do not reference that filesystem
* (which would of course lead to memory exceptions).
*/
if (++theFilesystemEpoch == 0) {
theFilesystemEpoch = 1;
}
ckfree(fsRecPtr);
retVal = TCL_OK;
} else {
fsRecPtr = fsRecPtr->nextPtr;
|
|
|
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
|
* might conceivably now belong to different filesystems. This
* should also ensure that paths which have cached the filesystem
* which is about to be deleted do not reference that filesystem
* (which would of course lead to memory exceptions).
*/
if (++theFilesystemEpoch == 0) {
++theFilesystemEpoch;
}
ckfree(fsRecPtr);
retVal = TCL_OK;
} else {
fsRecPtr = fsRecPtr->nextPtr;
|
| ︙ | | | ︙ | |
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
|
/*
* Increment the filesystem epoch counter, since existing paths might now
* belong to different filesystems.
*/
Tcl_MutexLock(&filesystemMutex);
if (++theFilesystemEpoch == 0) {
theFilesystemEpoch = 1;
}
Tcl_MutexUnlock(&filesystemMutex);
}
/*
*----------------------------------------------------------------------
*
|
|
|
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
|
/*
* Increment the filesystem epoch counter, since existing paths might now
* belong to different filesystems.
*/
Tcl_MutexLock(&filesystemMutex);
if (++theFilesystemEpoch == 0) {
++theFilesystemEpoch;
}
Tcl_MutexUnlock(&filesystemMutex);
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | | | ︙ | |