1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
10 //#include <pthread.h>
11 //#include "mtx_critsect.cpp"
12 #include "mtx_critsect.h"
13 #include "resultbuffer.h"
17 #define LONGLONG long long
18 #define ULONGLONG unsigned LONGLONG
19 /*Defining Global Variables*/
24 int USE_PROCESS_COUNT = 0;
28 LONGLONG callibrationValue = 0;
30 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
31 pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER;
32 pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER;
33 CRITICAL_SECTION g_cs;
35 /* Capture statistics for each worker thread */
37 unsigned int processId;
38 unsigned int operationsFailed;
39 unsigned int operationsPassed;
40 unsigned int operationsTotal;
42 unsigned int relationId;
46 struct applicationStatistics{
48 unsigned int relationId;
49 unsigned int processCount;
50 unsigned int threadCount;
51 unsigned int repeatCount;
56 ResultBuffer *resultBuffer;
59 void* waitforworkerthreads(void*);
62 int cleanuptest(void);
63 int GetParameters( int , char **);
64 void incrementCounter(void);
65 ULONGLONG GetTicks(void);
66 ULONGLONG getPerfCallibrationValue(void);
70 extern int main(int argc, char **argv)
72 //Variable Declaration
73 pthread_t pthreads[640];
78 ULONGLONG startTicks = 0;
80 /* Variables to capture the file name and the file pointer*/
81 char fileName[MAX_PATH];
83 struct statistics* buffer;
84 int statisticsSize = 0;
86 /*Variable to Captutre Information at the Application Level*/
87 struct applicationStatistics appStats;
88 char mainFileName[MAX_PATH];
91 //Get perfCallibrationValue
93 callibrationValue = getPerfCallibrationValue();
94 printf("Callibration Value for this Platform %llu \n", callibrationValue);
98 if(GetParameters(argc, argv))
100 printf("Error in obtaining the parameters\n");
104 //Assign Values to Application Statistics Members
105 appStats.relationId=RELATION_ID;
106 appStats.operationTime=0;
107 appStats.buildNumber = "999.99";
108 appStats.processCount = USE_PROCESS_COUNT;
109 appStats.threadCount = THREAD_COUNT;
110 appStats.repeatCount = REPEAT_COUNT;
112 printf("RELATION ID : %d\n", appStats.relationId);
113 printf("Process Count : %d\n", appStats.processCount);
114 printf("Thread Count : %d\n", appStats.threadCount);
115 printf("Repeat Count : %d\n", appStats.repeatCount);
118 //Open file for Application Statistics Collection
119 snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId);
120 hMainFile = fopen(mainFileName, "w+");
122 if(hMainFile == NULL)
124 printf("Error in opening main file for write\n");
128 for (i=0;i<THREAD_COUNT;i++)
133 statisticsSize = sizeof(struct statistics);
135 snprintf(fileName, MAX_PATH, "%d_thread_nativecriticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
136 hFile = fopen(fileName, "w+");
140 printf("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
144 // For each thread we will log operations failed (int), passed (int), total (int)
145 // and number of ticks (DWORD) for the operations
146 resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
148 //Call Test Case Setup Routine
152 printf("Error Initializing Test Case\n");
157 if (0!=pthread_mutex_lock(&g_mutex))
160 printf("Error Accquiring Lock\n");
164 //USE NATIVE METHOD TO GET TICK COUNT
165 startTicks = GetTicks();
167 /*Loop to create number THREAD_COUNT number of threads*/
168 for (i=0;i< THREAD_COUNT;i++)
171 //printf("Creating Thread Count %d\n", i);
172 //printf("Thread arrary value = %d\n", threadID[i]);
173 rtn=pthread_create(&pthreads[i], NULL, waitforworkerthreads, &threadID[i]);
175 { /* ERROR Condition */
176 printf("Error: pthread Creat, %s \n", strerror(rtn));
183 //printf("Main Thread waits to recevie signal when all threads are done\n");
184 pthread_cond_wait(&g_cv2,&g_mutex);
186 //printf("Main thread has received signal\n");
188 /*Signal Threads to Start Working*/
189 //printf("Raise signal for all threads to start working\n");
193 if (0!=pthread_cond_broadcast(&g_cv))
196 printf("Error Broadcasting Conditional Event\n");
201 if (0!=pthread_mutex_unlock(&g_mutex))
204 printf("Error Releasing Lock\n");
209 while (j < THREAD_COUNT)
211 if (0 != pthread_join(pthreads[j],NULL))
214 printf("Error Joining Threads\n");
221 /*Write Application Results to File*/
222 //CAPTURE NATIVE TICK COUNT HERE
223 appStats.operationTime = (DWORD)(GetTicks() - startTicks)/callibrationValue;
226 /* Write Results to a file*/
229 for( i = 0; i < THREAD_COUNT; i++ )
231 buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
232 fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
233 //printf("Iteration %d over\n", i);
240 //Call Test Case Cleanup Routine
241 if (0!=cleanuptest())
244 printf("Error Cleaning up Test Case");
251 printf("Writing to Main File \n");
252 fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
259 void * waitforworkerthreads(void * threadId)
262 int *threadParam = (int*) threadId;
264 // printf("Thread ID : %d \n", *threadParam);
267 if (0!=pthread_mutex_lock(&g_mutex))
270 printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n");
274 //Increment Global Counter
278 //If global counter is equal to thread count then signal main thread
279 if (GLOBAL_COUNTER == THREAD_COUNT)
281 if (0!=pthread_cond_signal(&g_cv2))
284 printf("Error in setting conditional variable\n");
289 //Wait for main thread to signal
290 if (0!=pthread_cond_wait(&g_cv,&g_mutex))
293 printf("Error waiting on conditional variable in Worker Thread\n");
297 //Release the mutex lock
298 if (0!=pthread_mutex_unlock(&g_mutex))
301 printf("Error Releasing Mutex Lock in Worker Thread\n");
306 starttests(*threadParam);
310 void starttests(int threadID)
312 /*All threads beign executing tests cases*/
315 struct statistics stats;
316 ULONGLONG startTime = 0;
317 ULONGLONG endTime = 0;
319 LONG volatile Destination;
324 stats.relationId = RELATION_ID;
325 stats.processId = USE_PROCESS_COUNT;
326 stats.operationsFailed = 0;
327 stats.operationsPassed = 0;
328 stats.operationsTotal = 0;
329 stats.operationTime = 0;
331 //Enter and Leave Critical Section in a loop REPEAT_COUNT Times
334 startTime = GetTicks();
336 for (i=0;i<REPEAT_COUNT;i++)
338 Destination = (LONG volatile) threadID;
340 Comperand = (LONG) threadID;
341 result = InterlockedCompareExchange(&Destination, Exchange, Comperand);
345 stats.operationsFailed++;
346 stats.operationsTotal++;
353 stats.operationTime = (DWORD)(GetTicks() - startTime)/callibrationValue;
355 // printf("Operation Time %d \n", stats.operationTime);
357 if(resultBuffer->LogResult(Id, (char *)&stats))
359 printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT);
367 //Initalize Critical Section
369 if (0!=MTXInitializeCriticalSection( &g_cs))
377 int cleanuptest(void)
380 //Delete Critical Section
382 if (0!=MTXDeleteCriticalSection(&g_cs))
390 int GetParameters( int argc, char **argv)
393 if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
394 || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
396 printf("PAL -Composite Native Critical Section Test\n");
398 printf("\t[PROCESS_ID ( greater than 1] \n");
399 printf("\t[THREAD_COUNT ( greater than 1] \n");
400 printf("\t[REPEAT_COUNT ( greater than 1]\n");
401 printf("\t[RELATION_ID [greater than or Equal to 1]\n");
406 USE_PROCESS_COUNT = atoi(argv[1]);
407 if( USE_PROCESS_COUNT < 0)
409 printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
413 THREAD_COUNT = atoi(argv[2]);
414 if( THREAD_COUNT < 1)
416 printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
420 REPEAT_COUNT = atoi(argv[3]);
421 if( REPEAT_COUNT < 1)
423 printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
427 RELATION_ID = atoi(argv[4]);
430 printf("\nInvalid RELATION_ID number, Pass greater than 1\n");
438 void incrementCounter(void)
444 //Implementation borrowed from pertrace.c
445 ULONGLONG GetTicks(void)
449 asm volatile("rdtsc":"=a" (a), "=d" (d));
450 return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a);
452 // #error Don''t know how to get ticks on this platform
453 return (ULONGLONG)gethrtime();
459 ULONGLONG getPerfCallibrationValue(void)
461 ULONGLONG startTicks;
464 startTicks = GetTicks();
466 endTicks = GetTicks();
468 return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds