summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp')
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp241
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);
+}