diff options
Diffstat (limited to 'src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp')
-rw-r--r-- | src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp new file mode 100644 index 0000000000..8a245a4776 --- /dev/null +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp @@ -0,0 +1,241 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source: criticalsectionfunctions/test4/test4.c +** +** Purpose: Test to see if threads blocked on a CRITICAL_SECTION object will +** be released in an orderly manner. This case looks at the following +** scenario. If one thread owns a CRITICAL_SECTION object and two threads +** block in EnterCriticalSection, trying to hold the already owned +** CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION +** object, will one and only one of the waiters get unblocked? +** +** Dependencies: CreateThread +** InitializeCriticalSection +** EnterCriticalSection +** LeaveCriticalSection +** DeleteCriticalSection +** Sleep +** WaitForSingleObject +** + +** +**=========================================================*/ + +#include <palsuite.h> + +#define NUM_BLOCKING_THREADS 2 + +BOOL bTestResult; +CRITICAL_SECTION CriticalSection; +HANDLE hThread[NUM_BLOCKING_THREADS]; +HANDLE hEvent; +DWORD dwThreadId[NUM_BLOCKING_THREADS]; +volatile int flags[NUM_BLOCKING_THREADS] = {0,0}; + +DWORD PALAPI ThreadTest1(LPVOID lpParam) +{ + + EnterCriticalSection ( &CriticalSection ); + + flags[0] = 1; + + return 0; + +} + +DWORD PALAPI ThreadTest2(LPVOID lpParam) +{ + + EnterCriticalSection ( &CriticalSection ); + + flags[1] = 1; + + return 0; + +} + +int __cdecl main(int argc, char **argv) +{ + + DWORD dwRet; + DWORD dwRet1; + bTestResult = FAIL; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(bTestResult); + } + + /* + * Create Critical Section Object + */ + InitializeCriticalSection ( &CriticalSection ); + + EnterCriticalSection ( &CriticalSection ); + + hThread[0] = CreateThread(NULL, + 0, + &ThreadTest1, + (LPVOID) 0, + CREATE_SUSPENDED, + &dwThreadId[0]); + if (hThread[0] == NULL) + { + Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " + "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest1, + (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[0], GetLastError()); + LeaveCriticalSection(&CriticalSection); + DeleteCriticalSection ( &CriticalSection ); + Fail(""); + } + + hThread[1] = CreateThread(NULL, + 0, + &ThreadTest2, + (LPVOID) 0, + CREATE_SUSPENDED, + &dwThreadId[1]); + if (hThread[1] == NULL) + { + Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " + "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest2, + (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[1], GetLastError()); + LeaveCriticalSection(&CriticalSection); + + dwRet = ResumeThread(hThread[0]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\n" + "GetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + + dwRet = WaitForSingleObject(hThread[0], 10000); + if (WAIT_OBJECT_0 == dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " + "failed. '%d' was returned instead of the expected '%d'.\n" + "GetLastError returned '%d'.\n", hThread[0], 10000, dwRet, + WAIT_OBJECT_0, GetLastError()); + } + + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[0], GetLastError()); + } + + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* + * Set other thread priorities to be higher than ours & Sleep to ensure + * we give up the processor. + */ + dwRet = (DWORD) SetThreadPriority(hThread[0], + THREAD_PRIORITY_ABOVE_NORMAL); + if (0 == dwRet) + { + Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); + } + + dwRet = (DWORD) SetThreadPriority(hThread[1], + THREAD_PRIORITY_ABOVE_NORMAL); + if (0 == dwRet) + { + Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[1], + THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); + } + + dwRet = ResumeThread(hThread[0]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + GetLastError() ); + } + + dwRet = ResumeThread(hThread[1]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + GetLastError()); + } + + Sleep (0); + + LeaveCriticalSection (&CriticalSection); + + dwRet = WaitForSingleObject(hThread[0], 10000); + dwRet1 = WaitForSingleObject(hThread[1], 10000); + + if ((WAIT_OBJECT_0 == dwRet) || + (WAIT_OBJECT_0 == dwRet1)) + { + if ((1 == flags[0] && 0 == flags[1]) || + (0 == flags[0] && 1 == flags[1])) + { + bTestResult = PASS; + } + else + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: flags[%d] = {%d,%d}. These values are" + "inconsistent.\nCriticalSection test failed.\n", + NUM_BLOCKING_THREADS, flags[0], flags[1]); + } + + /* Fail the test if both threads returned WAIT_OBJECT_0 */ + if ((WAIT_OBJECT_0 == dwRet) && (WAIT_OBJECT_0 == dwRet1)) + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " + "WaitForSingleObject(%p, %d)\nboth returned dwRet = '%d'\n" + "One should have returned WAIT_TIMEOUT ('%d').\n", + hThread[0], 10000, hThread[1], 10000, dwRet, WAIT_TIMEOUT); + } + } + else + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " + "WaitForSingleObject(%p, %d)\nReturned dwRet = '%d' and\n" + "dwRet1 = '%d' respectively.\n", hThread[0], 10000, hThread[1], + 10000, dwRet, dwRet1); + } + + if (WAIT_OBJECT_0 == dwRet) + { + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[0], GetLastError()); + } + } + if (WAIT_OBJECT_0 == dwRet1) + { + if (0 == CloseHandle(hThread[1])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[1], GetLastError()); + } + } + + /* Leaking the CS on purpose, since there is still a thread + waiting on it */ + + PAL_TerminateEx(bTestResult); + return (bTestResult); +} |