summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/composite/wfmo/mutex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/tests/palsuite/composite/wfmo/mutex.cpp')
-rw-r--r--src/pal/tests/palsuite/composite/wfmo/mutex.cpp365
1 files changed, 365 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/composite/wfmo/mutex.cpp b/src/pal/tests/palsuite/composite/wfmo/mutex.cpp
new file mode 100644
index 0000000000..c8ed01426c
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/wfmo/mutex.cpp
@@ -0,0 +1,365 @@
+// 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 Code: main.c and mutex.c
+** main.c creates process and waits for all processes to get over
+** mutex.c creates a mutex and then calls threads which will
+** contend for the mutex
+**
+** This test is for WFMO Test case for Mutex
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int SLEEP_LENGTH = 0;
+unsigned int RELATION_ID = 1001;
+
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Handle to signal threads to start the tests */
+HANDLE StartTestsEvHandle = NULL;
+/* Handle to mutex which will be contended by threads */
+HANDLE hMutexHandle = NULL;
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 6) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite WFMO Test\n");
+ printf("Usage:\n");
+ printf("mutex\n\t[USE_PROCESS_COUNT [greater than 0] \n");
+ printf("\t[THREAD_COUNT [greater than 0] \n");
+ printf("\t[REPEAT_COUNT [greater than 0]\n");
+ printf("\t[SLEEP_LENGTH [greater than 0]\n");
+ printf("\t[RELATION_ID [greater than 0]\n");
+
+
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ SLEEP_LENGTH = atoi(argv[4]);
+ if( SLEEP_LENGTH < 1)
+ {
+ printf("\nMain Process:Invalid SLEEP_LENGTH number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[5]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+ int returnCode = 0;
+
+ DWORD dwParam = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d] and no. of threads is [%d]\n", USE_PROCESS_COUNT, THREAD_COUNT);
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error:%d: in opening Process File for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d], error [%d]\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create start tests Event for process count %d\n", GetLastError(), USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+ hMutexHandle = CreateMutex(
+ NULL,
+ FALSE, /* bInitialOwner, owns initially */
+ NULL
+ );
+
+ if( hMutexHandle == NULL)
+ {
+ Fail("Unable to create Mutex handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+
+ /* We already assume that the mutex was created previously*/
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ /* Test running */
+
+ if( THREAD_COUNT != 1 )
+ {
+ returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, INFINITE);
+ }
+ else
+ {
+ returnCode = WaitForSingleObject(hThread[0], INFINITE);
+ }
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //Trace("Iteration %d over\n", i);
+
+ }
+ }
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ if(fclose(pProcessFile))
+ {
+ Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ /* Logging for the test case over, clean up the handles */
+ // Trace("Test Process %d done\n", USE_PROCESS_COUNT);
+ //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer());
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return testStatus;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ struct statistics stats;
+
+ DWORD dwWaitResult;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to mutex
+ INFINITE);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error:%d: while waiting for StartTest Event@ thread %d\n", GetLastError(), Id);
+ testStatus = FAIL;
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+
+ /* Run the tests repeat count times */
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hMutexHandle, // handle to mutex
+ INFINITE);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error:%d: while waiting for onject @ thread %d, # iter %d\n", GetLastError(), Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+
+ Sleep(SLEEP_LENGTH);
+
+ if (!ReleaseMutex(hMutexHandle))
+ {
+ // Deal with error.
+ Trace("Error:%d: while releasing mutex @ thread %d # iter %d\n", GetLastError(), Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // do we need to have while true loop to attempt to release mutex...?
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+
+// Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ // Trace("Operation Time %lu, Process Count [%d], ThreadCount[%d]\n", stats.operationTime, USE_PROCESS_COUNT, Id);
+
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ // Trace("Contents of the buffer are after thread [%d]\n", Id);
+}