Skip to content

Commit eed7470

Browse files
committed
Merge pull request git-for-windows#1934 from benpeart/fscache-thread-safe-enable-gfw
fscache: make fscache_enable() thread safe
2 parents 3ae35f3 + f45518e commit eed7470

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
@@ -8,6 +8,7 @@
88
#include "win32/lazyload.h"
99
#include "../config.h"
1010
#include "dir.h"
11+
#include "win32/fscache.h"
1112

1213
#define HCAST(type, handle) ((type)(intptr_t)handle)
1314

@@ -3203,6 +3204,9 @@ int wmain(int argc, const wchar_t **wargv)
32033204
/* initialize critical section for waitpid pinfo_t list */
32043205
InitializeCriticalSection(&pinfo_cs);
32053206

3207+
/* initialize critical section for fscache */
3208+
InitializeCriticalSection(&fscache_cs);
3209+
32063210
/* set up default file mode and file modes for stdin/out/err */
32073211
_fmode = _O_BINARY;
32083212
_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.
@@ -383,12 +383,12 @@ int fscache_enable(size_t initial_size)
383383
* opendir and lstat function pointers are redirected if
384384
* any threads are using the fscache.
385385
*/
386+
EnterCriticalSection(&fscache_cs);
386387
if (!initialized) {
387-
InitializeCriticalSection(&mutex);
388388
if (!dwTlsIndex) {
389389
dwTlsIndex = TlsAlloc();
390390
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
391-
LeaveCriticalSection(&mutex);
391+
LeaveCriticalSection(&fscache_cs);
392392
return 0;
393393
}
394394
}
@@ -397,12 +397,13 @@ int fscache_enable(size_t initial_size)
397397
opendir = fscache_opendir;
398398
lstat = fscache_lstat;
399399
}
400-
InterlockedIncrement(&initialized);
400+
initialized++;
401+
LeaveCriticalSection(&fscache_cs);
401402

402403
/* refcount the thread specific initialization */
403404
cache = fscache_getcache();
404405
if (cache) {
405-
InterlockedIncrement(&cache->enabled);
406+
cache->enabled++;
406407
} else {
407408
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
408409
cache->enabled = 1;
@@ -436,7 +437,7 @@ void fscache_disable(void)
436437
BUG("fscache_disable() called on a thread where fscache has not been initialized");
437438
if (!cache->enabled)
438439
BUG("fscache_disable() called on an fscache that is already disabled");
439-
InterlockedDecrement(&cache->enabled);
440+
cache->enabled--;
440441
if (!cache->enabled) {
441442
TlsSetValue(dwTlsIndex, NULL);
442443
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
@@ -449,12 +450,14 @@ void fscache_disable(void)
449450
}
450451

451452
/* update the global fscache initialization */
452-
InterlockedDecrement(&initialized);
453+
EnterCriticalSection(&fscache_cs);
454+
initialized--;
453455
if (!initialized) {
454456
/* reset opendir and lstat to the original implementations */
455457
opendir = dirent_opendir;
456458
lstat = mingw_lstat;
457459
}
460+
LeaveCriticalSection(&fscache_cs);
458461

459462
trace_printf_key(&trace_fscache, "fscache: disable\n");
460463
return;
@@ -621,7 +624,7 @@ void fscache_merge(struct fscache *dest)
621624
* isn't being used so the critical section only needs to prevent
622625
* the the child threads from stomping on each other.
623626
*/
624-
EnterCriticalSection(&mutex);
627+
EnterCriticalSection(&fscache_cs);
625628

626629
hashmap_iter_init(&cache->map, &iter);
627630
while ((e = hashmap_iter_next(&iter)))
@@ -633,9 +636,9 @@ void fscache_merge(struct fscache *dest)
633636
dest->opendir_requests += cache->opendir_requests;
634637
dest->fscache_requests += cache->fscache_requests;
635638
dest->fscache_misses += cache->fscache_misses;
636-
LeaveCriticalSection(&mutex);
639+
initialized--;
640+
LeaveCriticalSection(&fscache_cs);
637641

638642
free(cache);
639643

640-
InterlockedDecrement(&initialized);
641644
}

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)