From: Rastislav Stanik git@rastos.org
use a critical section to guard access to local static variable with cached information
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58082 --- dlls/kernelbase/memory.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 0be178f6ab7..84968c0f386 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -42,6 +42,14 @@ WINE_DECLARE_DEBUG_CHANNEL(virtual); WINE_DECLARE_DEBUG_CHANNEL(globalmem);
+static CRITICAL_SECTION memstatus_section; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &memstatus_section, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": memstatus_section") } +}; +static CRITICAL_SECTION memstatus_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static CROSS_PROCESS_WORK_LIST *open_cross_process_connection( HANDLE process ) { @@ -1343,12 +1351,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status ) SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - if ((NtGetTickCount() - last_check) < 1000) + RtlEnterCriticalSection(&memstatus_section); + if ((NtGetTickCount() - last_check) < 1000 && cached_status.dwLength > 0) { *status = cached_status; + RtlLeaveCriticalSection(&memstatus_section); return TRUE; } - last_check = NtGetTickCount();
if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation, &basic_info, sizeof(basic_info), NULL )) || @@ -1356,7 +1365,10 @@ BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status ) &perf_info, sizeof(perf_info), NULL)) || !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &vmc, sizeof(vmc), NULL ))) + { + RtlLeaveCriticalSection(&memstatus_section); return FALSE; + }
status->dwMemoryLoad = 0; status->ullTotalPhys = basic_info.MmNumberOfPhysicalPages; @@ -1381,6 +1393,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status ) status->ullAvailPageFile, status->ullTotalVirtual, status->ullAvailVirtual );
cached_status = *status; + last_check = NtGetTickCount(); + RtlLeaveCriticalSection(&memstatus_section); return TRUE; }