summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp')
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp
new file mode 100644
index 0000000000..7f0c58cd26
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp
@@ -0,0 +1,217 @@
+// 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/test8/test8.c
+**
+** Pyrpose: Ensure critical section functionality is working by
+** having multiple threads racing on a CS under different
+** scenarios
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+#define MAX_THREAD_COUNT 128
+#define DEFAULT_THREAD_COUNT 10
+#define DEFAULT_LOOP_COUNT 1000
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+int g_iThreadCount = DEFAULT_THREAD_COUNT;
+int g_iLoopCount = DEFAULT_LOOP_COUNT;
+volatile LONG g_lCriticalCount = 0;
+HANDLE g_hEvStart = NULL;
+
+CRITICAL_SECTION g_cs;
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ int i, j, iLpCnt;
+ DWORD dwRet = 0;
+ DWORD dwTid = GetCurrentThreadId();
+ LONG lRet;
+ BOOL bSleepInside;
+ BOOL bSleepOutside;
+
+ Trace("[tid=%u] Thread starting\n", dwTid);
+
+ dwRet = WaitForSingleObject(g_hEvStart, INFINITE);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("WaitForSingleObject returned unexpected %u [GetLastError()=%u]\n",
+ dwRet, GetLastError());
+ }
+
+ for (j=0;j<8;j++)
+ {
+ bSleepInside = 2 & j;
+ bSleepOutside = 4 & j;
+
+ iLpCnt = g_iLoopCount;
+ if (bSleepInside || bSleepOutside)
+ {
+ iLpCnt /= 10;
+ }
+
+ for (i=0;i<iLpCnt;i++)
+ {
+ EnterCriticalSection(&g_cs);
+ if (1 & i)
+ {
+ // Simple increment on odd iterations
+ lRet = (g_lCriticalCount += 1);
+ }
+ else
+ {
+ // Interlocked increment on even iterations
+ lRet = InterlockedIncrement(&g_lCriticalCount);
+ }
+
+ if (1 != lRet || 1 != g_lCriticalCount)
+ {
+ Fail("Detected %d threads in area protected by critical section "
+ "[expected: 1 thread]\n", g_lCriticalCount);
+ }
+ if (bSleepInside)
+ {
+ Sleep(rand()%10);
+ }
+ if (1 != g_lCriticalCount)
+ {
+ Fail("Detected %d threads inside area protected by critical section "
+ "[expected: 1 thread]\n", (int)g_lCriticalCount);
+ }
+
+ if (1 & i)
+ {
+ // Simple decrement on odd iterations
+ lRet = (g_lCriticalCount -= 1);
+ }
+ else
+ {
+ // Interlocked decrement on even iterations
+ lRet = InterlockedDecrement(&g_lCriticalCount);
+ }
+ LeaveCriticalSection(&g_cs);
+
+ if (bSleepOutside)
+ {
+ Sleep(rand()%10);
+ }
+ }
+ }
+
+ Trace("[tid=%u] Thread done\n", dwTid);
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwRet;
+ HANDLE hThreads[MAX_THREAD_COUNT] = { 0 };
+ int iThreadCount = 0;
+ int i, iVal;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ srand(time(NULL));
+
+ for (i=1; i<argc; i++)
+ {
+ if ('-' == *argv[i])
+ {
+ switch(*(argv[i]+1))
+ {
+ case 'n':
+ if (i < argc-1)
+ {
+ i += 1;
+ iVal = atoi(argv[i]);
+ if (0 < iVal)
+ {
+ g_iLoopCount = iVal;
+ }
+ }
+ break;
+ case 't':
+ if (i < argc-1)
+ {
+ i += 1;
+ iVal = atoi(argv[i]);
+ if (0 < iVal && MAX_THREAD_COUNT >= iVal)
+ {
+ g_iThreadCount = iVal;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Trace ("Iterations:\t%d\n", g_iLoopCount);
+ Trace ("Threads:\t%d\n", g_iThreadCount);
+
+ g_hEvStart = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (g_hEvStart == NULL)
+ {
+ Fail("CreateEvent call failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ InitializeCriticalSection(&g_cs);
+
+ for (i=0;i<g_iThreadCount;i++)
+ {
+ hThreads[iThreadCount] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId);
+ if (NULL != hThreads[iThreadCount])
+ {
+ iThreadCount++;
+ }
+ }
+
+ Sleep(100);
+
+ Trace("Created %d client threads\n", g_iThreadCount);
+
+ if (2 > iThreadCount)
+ {
+ Fail("Failed to create minimum number if threads, i.e. 2\n");
+ }
+
+ if (!SetEvent(g_hEvStart))
+ {
+ Fail("SetEvent failed [GetLastError()=%u]\n", GetLastError());
+ }
+
+ for (i=0; i<iThreadCount; i+=64)
+ {
+ dwRet = WaitForMultipleObjects(MIN(iThreadCount-i,64),
+ hThreads+i,
+ TRUE,
+ INFINITE);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("Wait for all threads failed\n");
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}