Skip to content

Commit 739dfee

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 573d422 commit 739dfee

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

compat/mingw.c

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "dir.h"
1313
#define SECURITY_WIN32
1414
#include <sspi.h>
15+
#include "win32/fscache.h"
1516

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

@@ -3405,6 +3406,9 @@ int wmain(int argc, const wchar_t **wargv)
34053406
/* initialize critical section for waitpid pinfo_t list */
34063407
InitializeCriticalSection(&pinfo_cs);
34073408

3409+
/* initialize critical section for fscache */
3410+
InitializeCriticalSection(&fscache_cs);
3411+
34083412
/* set up default file mode and file modes for stdin/out/err */
34093413
_fmode = _O_BINARY;
34103414
_setmode(_fileno(stdin), _O_BINARY);

compat/win32/fscache.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
static volatile long initialized;
1010
static DWORD dwTlsIndex;
11-
static CRITICAL_SECTION mutex;
11+
CRITICAL_SECTION fscache_cs;
1212

1313
/*
1414
* Store one fscache per thread to avoid thread contention and locking.
@@ -386,12 +386,12 @@ int fscache_enable(size_t initial_size)
386386
* opendir and lstat function pointers are redirected if
387387
* any threads are using the fscache.
388388
*/
389+
EnterCriticalSection(&fscache_cs);
389390
if (!initialized) {
390-
InitializeCriticalSection(&mutex);
391391
if (!dwTlsIndex) {
392392
dwTlsIndex = TlsAlloc();
393393
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
394-
LeaveCriticalSection(&mutex);
394+
LeaveCriticalSection(&fscache_cs);
395395
return 0;
396396
}
397397
}
@@ -400,12 +400,13 @@ int fscache_enable(size_t initial_size)
400400
opendir = fscache_opendir;
401401
lstat = fscache_lstat;
402402
}
403-
InterlockedIncrement(&initialized);
403+
initialized++;
404+
LeaveCriticalSection(&fscache_cs);
404405

405406
/* refcount the thread specific initialization */
406407
cache = fscache_getcache();
407408
if (cache) {
408-
InterlockedIncrement(&cache->enabled);
409+
cache->enabled++;
409410
} else {
410411
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
411412
cache->enabled = 1;
@@ -439,7 +440,7 @@ void fscache_disable(void)
439440
BUG("fscache_disable() called on a thread where fscache has not been initialized");
440441
if (!cache->enabled)
441442
BUG("fscache_disable() called on an fscache that is already disabled");
442-
InterlockedDecrement(&cache->enabled);
443+
cache->enabled--;
443444
if (!cache->enabled) {
444445
TlsSetValue(dwTlsIndex, NULL);
445446
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
@@ -452,12 +453,14 @@ void fscache_disable(void)
452453
}
453454

454455
/* update the global fscache initialization */
455-
InterlockedDecrement(&initialized);
456+
EnterCriticalSection(&fscache_cs);
457+
initialized--;
456458
if (!initialized) {
457459
/* reset opendir and lstat to the original implementations */
458460
opendir = dirent_opendir;
459461
lstat = mingw_lstat;
460462
}
463+
LeaveCriticalSection(&fscache_cs);
461464

462465
trace_printf_key(&trace_fscache, "fscache: disable\n");
463466
return;
@@ -626,7 +629,7 @@ void fscache_merge(struct fscache *dest)
626629
* isn't being used so the critical section only needs to prevent
627630
* the the child threads from stomping on each other.
628631
*/
629-
EnterCriticalSection(&mutex);
632+
EnterCriticalSection(&fscache_cs);
630633

631634
hashmap_iter_init(&cache->map, &iter);
632635
while ((e = hashmap_iter_next(&iter)))
@@ -638,9 +641,9 @@ void fscache_merge(struct fscache *dest)
638641
dest->opendir_requests += cache->opendir_requests;
639642
dest->fscache_requests += cache->fscache_requests;
640643
dest->fscache_misses += cache->fscache_misses;
641-
LeaveCriticalSection(&mutex);
644+
initialized--;
645+
LeaveCriticalSection(&fscache_cs);
642646

643647
free(cache);
644648

645-
InterlockedDecrement(&initialized);
646649
}

compat/win32/fscache.h

+2
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)