Skip to content

Commit 23ef8fd

Browse files
benpeartdscho
authored andcommitted
fscache: make fscache_enable() thread safe
The recent change to make fscache thread specific relied on fscache_enable() being called first from the primary thread before being called in parallel from worker threads. Make that more robust and protect it with a critical section to avoid any issues. Helped-by: Johannes Schindelin <[email protected]> Signed-off-by: Ben Peart <[email protected]>
1 parent 56c29f2 commit 23ef8fd

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

compat/mingw.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "dir.h"
1212
#include "../attr.h"
1313
#include "../string-list.h"
14+
#include "win32/fscache.h"
1415

1516
#define HCAST(type, handle) ((type)(intptr_t)handle)
1617

@@ -3168,6 +3169,9 @@ int wmain(int argc, const wchar_t **wargv)
31683169
InitializeCriticalSection(&pinfo_cs);
31693170
InitializeCriticalSection(&phantom_symlinks_cs);
31703171

3172+
/* initialize critical section for fscache */
3173+
InitializeCriticalSection(&fscache_cs);
3174+
31713175
/* set up default file mode and file modes for stdin/out/err */
31723176
_fmode = _O_BINARY;
31733177
_setmode(_fileno(stdin), _O_BINARY);

compat/win32/fscache.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
static volatile long initialized;
99
static DWORD dwTlsIndex;
10-
static CRITICAL_SECTION mutex;
10+
CRITICAL_SECTION fscache_cs;
1111

1212
/*
1313
* Store one fscache per thread to avoid thread contention and locking.
@@ -370,12 +370,12 @@ int fscache_enable(size_t initial_size)
370370
* opendir and lstat function pointers are redirected if
371371
* any threads are using the fscache.
372372
*/
373+
EnterCriticalSection(&fscache_cs);
373374
if (!initialized) {
374-
InitializeCriticalSection(&mutex);
375375
if (!dwTlsIndex) {
376376
dwTlsIndex = TlsAlloc();
377377
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
378-
LeaveCriticalSection(&mutex);
378+
LeaveCriticalSection(&fscache_cs);
379379
return 0;
380380
}
381381
}
@@ -384,12 +384,13 @@ int fscache_enable(size_t initial_size)
384384
opendir = fscache_opendir;
385385
lstat = fscache_lstat;
386386
}
387-
InterlockedIncrement(&initialized);
387+
initialized++;
388+
LeaveCriticalSection(&fscache_cs);
388389

389390
/* refcount the thread specific initialization */
390391
cache = fscache_getcache();
391392
if (cache) {
392-
InterlockedIncrement(&cache->enabled);
393+
cache->enabled++;
393394
} else {
394395
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
395396
cache->enabled = 1;
@@ -423,7 +424,7 @@ void fscache_disable(void)
423424
BUG("fscache_disable() called on a thread where fscache has not been initialized");
424425
if (!cache->enabled)
425426
BUG("fscache_disable() called on an fscache that is already disabled");
426-
InterlockedDecrement(&cache->enabled);
427+
cache->enabled--;
427428
if (!cache->enabled) {
428429
TlsSetValue(dwTlsIndex, NULL);
429430
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
@@ -436,12 +437,14 @@ void fscache_disable(void)
436437
}
437438

438439
/* update the global fscache initialization */
439-
InterlockedDecrement(&initialized);
440+
EnterCriticalSection(&fscache_cs);
441+
initialized--;
440442
if (!initialized) {
441443
/* reset opendir and lstat to the original implementations */
442444
opendir = dirent_opendir;
443445
lstat = mingw_lstat;
444446
}
447+
LeaveCriticalSection(&fscache_cs);
445448

446449
trace_printf_key(&trace_fscache, "fscache: disable\n");
447450
return;
@@ -608,7 +611,7 @@ void fscache_merge(struct fscache *dest)
608611
* isn't being used so the critical section only needs to prevent
609612
* the the child threads from stomping on each other.
610613
*/
611-
EnterCriticalSection(&mutex);
614+
EnterCriticalSection(&fscache_cs);
612615

613616
hashmap_iter_init(&cache->map, &iter);
614617
while ((e = hashmap_iter_next(&iter)))
@@ -620,9 +623,9 @@ void fscache_merge(struct fscache *dest)
620623
dest->opendir_requests += cache->opendir_requests;
621624
dest->fscache_requests += cache->fscache_requests;
622625
dest->fscache_misses += cache->fscache_misses;
623-
LeaveCriticalSection(&mutex);
626+
initialized--;
627+
LeaveCriticalSection(&fscache_cs);
624628

625629
free(cache);
626630

627-
InterlockedDecrement(&initialized);
628631
}

compat/win32/fscache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* for each thread where caching is desired.
77
*/
88

9+
extern CRITICAL_SECTION fscache_cs;
10+
911
int fscache_enable(size_t initial_size);
1012
#define enable_fscache(initial_size) fscache_enable(initial_size)
1113

0 commit comments

Comments
 (0)