Skip to content

Commit 530271e

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 f05fe6e + 17a1809 commit 530271e

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
@@ -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

@@ -3176,6 +3177,9 @@ int wmain(int argc, const wchar_t **wargv)
31763177
/* initialize critical section for waitpid pinfo_t list */
31773178
InitializeCriticalSection(&pinfo_cs);
31783179

3180+
/* initialize critical section for fscache */
3181+
InitializeCriticalSection(&fscache_cs);
3182+
31793183
/* set up default file mode and file modes for stdin/out/err */
31803184
_fmode = _O_BINARY;
31813185
_setmode(_fileno(stdin), _O_BINARY);

compat/win32/fscache.c

+13-10
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.
@@ -380,12 +380,12 @@ int fscache_enable(size_t initial_size)
380380
* opendir and lstat function pointers are redirected if
381381
* any threads are using the fscache.
382382
*/
383+
EnterCriticalSection(&fscache_cs);
383384
if (!initialized) {
384-
InitializeCriticalSection(&mutex);
385385
if (!dwTlsIndex) {
386386
dwTlsIndex = TlsAlloc();
387387
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
388-
LeaveCriticalSection(&mutex);
388+
LeaveCriticalSection(&fscache_cs);
389389
return 0;
390390
}
391391
}
@@ -394,12 +394,13 @@ int fscache_enable(size_t initial_size)
394394
opendir = fscache_opendir;
395395
lstat = fscache_lstat;
396396
}
397-
InterlockedIncrement(&initialized);
397+
initialized++;
398+
LeaveCriticalSection(&fscache_cs);
398399

399400
/* refcount the thread specific initialization */
400401
cache = fscache_getcache();
401402
if (cache) {
402-
InterlockedIncrement(&cache->enabled);
403+
cache->enabled++;
403404
} else {
404405
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
405406
cache->enabled = 1;
@@ -433,7 +434,7 @@ void fscache_disable(void)
433434
BUG("fscache_disable() called on a thread where fscache has not been initialized");
434435
if (!cache->enabled)
435436
BUG("fscache_disable() called on an fscache that is already disabled");
436-
InterlockedDecrement(&cache->enabled);
437+
cache->enabled--;
437438
if (!cache->enabled) {
438439
TlsSetValue(dwTlsIndex, NULL);
439440
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
@@ -446,12 +447,14 @@ void fscache_disable(void)
446447
}
447448

448449
/* update the global fscache initialization */
449-
InterlockedDecrement(&initialized);
450+
EnterCriticalSection(&fscache_cs);
451+
initialized--;
450452
if (!initialized) {
451453
/* reset opendir and lstat to the original implementations */
452454
opendir = dirent_opendir;
453455
lstat = mingw_lstat;
454456
}
457+
LeaveCriticalSection(&fscache_cs);
455458

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

623626
hashmap_iter_init(&cache->map, &iter);
624627
while ((e = hashmap_iter_next(&iter)))
@@ -630,9 +633,9 @@ void fscache_merge(struct fscache *dest)
630633
dest->opendir_requests += cache->opendir_requests;
631634
dest->fscache_requests += cache->fscache_requests;
632635
dest->fscache_misses += cache->fscache_misses;
633-
LeaveCriticalSection(&mutex);
636+
initialized--;
637+
LeaveCriticalSection(&fscache_cs);
634638

635639
free(cache);
636640

637-
InterlockedDecrement(&initialized);
638641
}

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)