Skip to content

Commit c496a4d

Browse files
benpeartGit for Windows Build Agent
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 4cfb809 commit c496a4d

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
@@ -14,6 +14,7 @@
1414
#include "symlinks.h"
1515
#include "trace2.h"
1616
#include "win32.h"
17+
#include "win32/fscache.h"
1718
#include "win32/lazyload.h"
1819
#include "wrapper.h"
1920
#include "write-or-die.h"
@@ -3723,6 +3724,9 @@ int wmain(int argc, const wchar_t **wargv)
37233724
/* initialize critical section for waitpid pinfo_t list */
37243725
InitializeCriticalSection(&pinfo_cs);
37253726

3727+
/* initialize critical section for fscache */
3728+
InitializeCriticalSection(&fscache_cs);
3729+
37263730
/* set up default file mode and file modes for stdin/out/err */
37273731
_fmode = _O_BINARY;
37283732
_setmode(_fileno(stdin), _O_BINARY);

compat/win32/fscache.c

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

1111
static volatile long initialized;
1212
static DWORD dwTlsIndex;
13-
static CRITICAL_SECTION mutex;
13+
CRITICAL_SECTION fscache_cs;
1414

1515
/*
1616
* Store one fscache per thread to avoid thread contention and locking.
@@ -393,12 +393,12 @@ int fscache_enable(size_t initial_size)
393393
* opendir and lstat function pointers are redirected if
394394
* any threads are using the fscache.
395395
*/
396+
EnterCriticalSection(&fscache_cs);
396397
if (!initialized) {
397-
InitializeCriticalSection(&mutex);
398398
if (!dwTlsIndex) {
399399
dwTlsIndex = TlsAlloc();
400400
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
401-
LeaveCriticalSection(&mutex);
401+
LeaveCriticalSection(&fscache_cs);
402402
return 0;
403403
}
404404
}
@@ -407,12 +407,13 @@ int fscache_enable(size_t initial_size)
407407
opendir = fscache_opendir;
408408
lstat = fscache_lstat;
409409
}
410-
InterlockedIncrement(&initialized);
410+
initialized++;
411+
LeaveCriticalSection(&fscache_cs);
411412

412413
/* refcount the thread specific initialization */
413414
cache = fscache_getcache();
414415
if (cache) {
415-
InterlockedIncrement(&cache->enabled);
416+
cache->enabled++;
416417
} else {
417418
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
418419
cache->enabled = 1;
@@ -446,7 +447,7 @@ void fscache_disable(void)
446447
BUG("fscache_disable() called on a thread where fscache has not been initialized");
447448
if (!cache->enabled)
448449
BUG("fscache_disable() called on an fscache that is already disabled");
449-
InterlockedDecrement(&cache->enabled);
450+
cache->enabled--;
450451
if (!cache->enabled) {
451452
TlsSetValue(dwTlsIndex, NULL);
452453
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
@@ -459,12 +460,14 @@ void fscache_disable(void)
459460
}
460461

461462
/* update the global fscache initialization */
462-
InterlockedDecrement(&initialized);
463+
EnterCriticalSection(&fscache_cs);
464+
initialized--;
463465
if (!initialized) {
464466
/* reset opendir and lstat to the original implementations */
465467
opendir = dirent_opendir;
466468
lstat = mingw_lstat;
467469
}
470+
LeaveCriticalSection(&fscache_cs);
468471

469472
trace_printf_key(&trace_fscache, "fscache: disable\n");
470473
return;
@@ -638,7 +641,7 @@ void fscache_merge(struct fscache *dest)
638641
* isn't being used so the critical section only needs to prevent
639642
* the the child threads from stomping on each other.
640643
*/
641-
EnterCriticalSection(&mutex);
644+
EnterCriticalSection(&fscache_cs);
642645

643646
hashmap_iter_init(&cache->map, &iter);
644647
while ((e = hashmap_iter_next(&iter)))
@@ -650,9 +653,9 @@ void fscache_merge(struct fscache *dest)
650653
dest->opendir_requests += cache->opendir_requests;
651654
dest->fscache_requests += cache->fscache_requests;
652655
dest->fscache_misses += cache->fscache_misses;
653-
LeaveCriticalSection(&mutex);
656+
initialized--;
657+
LeaveCriticalSection(&fscache_cs);
654658

655659
free(cache);
656660

657-
InterlockedDecrement(&initialized);
658661
}

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)