BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags) { /** * See http://msdn.microsoft.com/en-us/library/ff541979(v=vs.85).aspx * - The LockCount field indicates the number of times that any thread has * called the EnterCriticalSection routine for this critical section, * minus one. This field starts at -1 for an unlocked critical section. * Each call of EnterCriticalSection increments this value; each call of * LeaveCriticalSection decrements it. * - The RecursionCount field indicates the number of times that the owning * thread has called EnterCriticalSection for this critical section. */ if (Flags != 0) { WLog_WARN(TAG, "Flags unimplemented"); } lpCriticalSection->DebugInfo = NULL; lpCriticalSection->LockCount = -1; lpCriticalSection->SpinCount = 0; lpCriticalSection->RecursionCount = 0; lpCriticalSection->OwningThread = NULL; lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t)); #if defined(__APPLE__) semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 0); #else sem_init(lpCriticalSection->LockSemaphore, 0, 0); #endif SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount); return TRUE; }
void mutex::set_spin_count(unsigned int count) { void *p = m_buf; CRITICAL_SECTION &m_cs = *static_cast<CRITICAL_SECTION *>(p); SetCriticalSectionSpinCount(&m_cs, count); }
STDMETHODIMP DHCrst::SetSpinCount(DWORD dwSpinCount) { _ASSERTE(m_pCrst && "Expected a non-null critical section here"); SetCriticalSectionSpinCount(m_pCrst, dwSpinCount); // TODO: retval transformation return S_OK; }
void set_spin_count(DWORD dwSpinCount) { SetCriticalSectionSpinCount(&cs, dwSpinCount); }
static PVOID TestSynchCritical_Main(PVOID arg) { int i, j; SYSTEM_INFO sysinfo; DWORD dwPreviousSpinCount; DWORD dwSpinCount; DWORD dwSpinCountExpected; HANDLE hMainThread; HANDLE* hThreads; HANDLE hThread; DWORD dwThreadCount; DWORD dwThreadExitCode; BOOL bTest1Running; PBOOL pbThreadTerminated = (PBOOL)arg; GetNativeSystemInfo(&sysinfo); hMainThread = (HANDLE) (ULONG_PTR) GetCurrentThreadId(); /** * Test SpinCount in SetCriticalSectionSpinCount, InitializeCriticalSectionEx and InitializeCriticalSectionAndSpinCount * SpinCount must be forced to be zero on on uniprocessor systems and on systems * where WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT is defined */ dwSpinCount = 100; InitializeCriticalSectionEx(&critical, dwSpinCount, 0); while(--dwSpinCount) { dwPreviousSpinCount = SetCriticalSectionSpinCount(&critical, dwSpinCount); dwSpinCountExpected = 0; #if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT) if (sysinfo.dwNumberOfProcessors > 1) dwSpinCountExpected = dwSpinCount+1; #endif if (dwPreviousSpinCount != dwSpinCountExpected) { printf("CriticalSection failure: SetCriticalSectionSpinCount returned %u (expected: %u)\n", dwPreviousSpinCount, dwSpinCountExpected); goto fail; } DeleteCriticalSection(&critical); if (dwSpinCount%2==0) InitializeCriticalSectionAndSpinCount(&critical, dwSpinCount); else InitializeCriticalSectionEx(&critical, dwSpinCount, 0); } DeleteCriticalSection(&critical); /** * Test single-threaded recursive TryEnterCriticalSection/EnterCriticalSection/LeaveCriticalSection * */ InitializeCriticalSection(&critical); for (i = 0; i < 1000; i++) { if (critical.RecursionCount != i) { printf("CriticalSection failure: RecursionCount field is %d instead of %d.\n", critical.RecursionCount, i); goto fail; } if (i%2==0) { EnterCriticalSection(&critical); } else { if (TryEnterCriticalSection(&critical) == FALSE) { printf("CriticalSection failure: TryEnterCriticalSection failed where it should not.\n"); goto fail; } } if (critical.OwningThread != hMainThread) { printf("CriticalSection failure: Could not verify section ownership (loop index=%d).\n", i); goto fail; } } while (--i >= 0) { LeaveCriticalSection(&critical); if (critical.RecursionCount != i) { printf("CriticalSection failure: RecursionCount field is %d instead of %d.\n", critical.RecursionCount, i); goto fail; } if (critical.OwningThread != (HANDLE)(i ? hMainThread : NULL)) { printf("CriticalSection failure: Could not verify section ownership (loop index=%d).\n", i); goto fail; } } DeleteCriticalSection(&critical); /** * Test using multiple threads modifying the same value */ dwThreadCount = sysinfo.dwNumberOfProcessors > 1 ? sysinfo.dwNumberOfProcessors : 2; hThreads = (HANDLE*) calloc(dwThreadCount, sizeof(HANDLE)); if (!hThreads) { printf("Problem allocating memory\n"); goto fail; } for (j = 0; j < TEST_SYNC_CRITICAL_TEST1_RUNS; j++) { dwSpinCount = j * 1000; InitializeCriticalSectionAndSpinCount(&critical, dwSpinCount); gTestValueVulnerable = 0; gTestValueSerialized = 0; /* the TestSynchCritical_Test1 threads shall run until bTest1Running is FALSE */ bTest1Running = TRUE; for (i = 0; i < (int) dwThreadCount; i++) { hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestSynchCritical_Test1, &bTest1Running, 0, NULL); } /* let it run for TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS ... */ Sleep(TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS); bTest1Running = FALSE; for (i = 0; i < (int) dwThreadCount; i++) { if (WaitForSingleObject(hThreads[i], INFINITE) != WAIT_OBJECT_0) { printf("CriticalSection failure: Failed to wait for thread #%d\n", i); goto fail; } GetExitCodeThread(hThreads[i], &dwThreadExitCode); if(dwThreadExitCode != 0) { printf("CriticalSection failure: Thread #%d returned error code %u\n", i, dwThreadExitCode); goto fail; } CloseHandle(hThreads[i]); } if (gTestValueVulnerable != gTestValueSerialized) { printf("CriticalSection failure: unexpected test value %d (expected %d)\n", gTestValueVulnerable, gTestValueSerialized); goto fail; } DeleteCriticalSection(&critical); } free(hThreads); /** * TryEnterCriticalSection in thread must fail if we hold the lock in the main thread */ InitializeCriticalSection(&critical); if (TryEnterCriticalSection(&critical) == FALSE) { printf("CriticalSection failure: TryEnterCriticalSection unexpectedly failed.\n"); goto fail; } /* This thread tries to call TryEnterCriticalSection which must fail */ hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestSynchCritical_Test2, NULL, 0, NULL); if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0) { printf("CriticalSection failure: Failed to wait for thread\n"); goto fail; } GetExitCodeThread(hThread, &dwThreadExitCode); if(dwThreadExitCode != 0) { printf("CriticalSection failure: Thread returned error code %u\n", dwThreadExitCode); goto fail; } CloseHandle(hThread); *pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */ return (PVOID)0; fail: *pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */ return (PVOID)1; }
PLuint SyncObject::SetSpinCount(PLuint spin_count) { return SetCriticalSectionSpinCount(&csCriticalSection, spin_count); }
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: #if _M_X64 gDebugLog = GlobalAllocator.New<CDebugLog>("AeonProfiler64.log"); #else gDebugLog = GlobalAllocator.New<CDebugLog>("AeonProfiler32.log"); #endif DebugLog("***** DLL_PROCESS_ATTACH *****"); ModuleHandle = hModule; ApplicationProcessId = GetCurrentProcessId(); ApplicationThreadId = GetCurrentThreadId(); InitializeCriticalSection(&gCriticalSection); SetCriticalSectionSpinCount(&gCriticalSection, 4000); // 4000 is what the Windows heap manager uses (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686197%28v=vs.85%29.aspx) DWORD64 Counter_Freq, Counter_Before, Counter_After; DWORD64 RDTSC_Before, RDTSC_After; QueryPerformanceFrequency((LARGE_INTEGER*)&Counter_Freq); QueryPerformanceCounter((LARGE_INTEGER*)&Counter_Before); RDTSC_Before = __rdtsc(); Sleep(1000); RDTSC_After = __rdtsc(); QueryPerformanceCounter((LARGE_INTEGER*)&Counter_After); ClockFreq = Counter_Freq * (RDTSC_After - RDTSC_Before) / (Counter_After - Counter_Before); TicksPerHundredNanoseconds = (int)(ClockFreq / 10000000); DialogCallTreeThreadId = ApplicationThreadId; // get the current thread id (this should be "main()" or "WinMain()") // Get the process name that's loading us GetModuleFileName( GetModuleHandle( NULL ), app_filename, _countof(app_filename) ); DebugLog("Application: %s", app_filename); DialogThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DialogThread, NULL, 0, &DialogThreadID); bTrackCallerData = true; break; case DLL_PROCESS_DETACH: bTrackCallerData = false; DebugLog("***** DLL_PROCESS_DETACH *****"); HandleExit(); if( DialogThreadHandle ) { if (WaitForSingleObject(DialogThreadHandle, INFINITE) == WAIT_TIMEOUT) { TerminateThread(DialogThreadHandle, 0); } CloseHandle(DialogThreadHandle); } DeleteCriticalSection(&gCriticalSection); if( gDebugLog ) { gDebugLog->~CDebugLog(); gDebugLog = nullptr; } break; } return TRUE; }