Remove obsolete platforms ifdefs from PAL (#8971)
[platform/upstream/coreclr.git] / src / pal / tests / palsuite / composite / synchronization / nativecs_interlocked / pal_composite_native_cs.cpp
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.
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <time.h>
10 //#include <pthread.h>
11 //#include "mtx_critsect.cpp"
12 #include "mtx_critsect.h"
13 #include "resultbuffer.h"
14
15
16
17 #define LONGLONG long long
18 #define ULONGLONG unsigned LONGLONG
19 /*Defining Global Variables*/
20
21 int THREAD_COUNT=0;
22 int REPEAT_COUNT=0;
23 int GLOBAL_COUNTER=0;
24 int USE_PROCESS_COUNT = 0;
25 int RELATION_ID =0;
26 int g_counter = 0;
27 int MAX_PATH = 256;
28 LONGLONG callibrationValue = 0;
29
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;
34
35 /* Capture statistics for each worker thread */
36 struct statistics{
37     unsigned int processId;
38     unsigned int operationsFailed;
39     unsigned int operationsPassed;
40     unsigned int operationsTotal; 
41     DWORD        operationTime;
42     unsigned int relationId;
43 };
44
45
46 struct applicationStatistics{
47     DWORD               operationTime;
48     unsigned int        relationId;
49     unsigned int        processCount;
50     unsigned int        threadCount;
51     unsigned int        repeatCount;
52     char*                       buildNumber;
53
54 };
55
56 ResultBuffer *resultBuffer;
57
58
59 void* waitforworkerthreads(void*);
60 void starttests(int);
61 int setuptest(void);
62 int cleanuptest(void);
63 int GetParameters( int , char **);
64 void incrementCounter(void);
65 ULONGLONG GetTicks(void);
66 ULONGLONG getPerfCallibrationValue(void);
67
68
69
70 extern int main(int argc, char **argv)
71  {
72         //Variable Declaration
73         pthread_t pthreads[640];
74         int threadID[640];
75         int i=0; 
76         int j=0;
77         int rtn=0;
78         ULONGLONG startTicks = 0;
79
80         /* Variables to capture the file name and the file pointer*/
81     char fileName[MAX_PATH];
82     FILE *hFile;
83     struct statistics* buffer;
84     int statisticsSize = 0;
85
86         /*Variable to Captutre Information at the Application Level*/
87         struct applicationStatistics appStats;
88         char mainFileName[MAX_PATH];
89     FILE *hMainFile;
90
91         //Get perfCallibrationValue 
92
93         callibrationValue = getPerfCallibrationValue();
94         printf("Callibration Value for this Platform %llu \n", callibrationValue);
95
96
97         //Get Parameters
98         if(GetParameters(argc, argv))
99     {
100      printf("Error in obtaining the parameters\n");
101          exit(-1);      
102     }
103
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;
111
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);
116
117
118         //Open file for Application Statistics Collection 
119         snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId);
120         hMainFile = fopen(mainFileName, "w+");
121
122         if(hMainFile == NULL)
123         { 
124             printf("Error in opening main file for write\n");
125         }
126
127
128         for (i=0;i<THREAD_COUNT;i++)
129                 {
130                         threadID[i] = i;
131                 }
132         
133         statisticsSize = sizeof(struct statistics);
134
135         snprintf(fileName, MAX_PATH, "%d_thread_nativecriticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
136         hFile = fopen(fileName, "w+");
137
138         if(hFile == NULL)
139         { 
140             printf("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
141         }
142
143
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);
147
148         //Call Test Case Setup Routine
149         if (0!=setuptest())
150         {
151                 //Error Condition
152                 printf("Error Initializing Test Case\n");
153                 exit(-1);
154         }
155
156         //Accquire Lock
157     if (0!=pthread_mutex_lock(&g_mutex))
158     {
159         //Error Condition
160                 printf("Error Accquiring Lock\n");
161                 exit(-1);
162     }
163
164         //USE NATIVE METHOD TO GET TICK COUNT
165         startTicks = GetTicks();        
166         
167         /*Loop to create number THREAD_COUNT number of threads*/
168         for (i=0;i< THREAD_COUNT;i++)
169         {
170                 
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]);
174                 if (0 != rtn)
175                         { /* ERROR Condition */
176                                 printf("Error:  pthread Creat, %s \n", strerror(rtn));
177                                 exit(-1);
178                         }
179                 
180         }
181
182         
183         //printf("Main Thread waits to recevie signal when all threads are done\n");
184         pthread_cond_wait(&g_cv2,&g_mutex);
185
186         //printf("Main thread has received signal\n");
187
188         /*Signal Threads to Start Working*/
189         //printf("Raise signal for all threads to start working\n");
190
191
192
193         if (0!=pthread_cond_broadcast(&g_cv))
194                 {
195                         //Error Condition
196                         printf("Error Broadcasting Conditional Event\n");
197                         exit(-1);
198                 }
199         
200         //Release the lock
201         if (0!=pthread_mutex_unlock(&g_mutex))
202                 {
203                         //Error Condition
204                         printf("Error Releasing Lock\n");
205                         exit(-1);
206                 }
207
208         /*Join Threads */
209         while (j < THREAD_COUNT)
210         {
211                 if (0 != pthread_join(pthreads[j],NULL))
212                         {
213                                 //Error Condition
214                                 printf("Error Joining Threads\n");
215                                 exit(-1);
216                         }
217                 j++;
218         }
219
220
221    /*Write Application Results to File*/
222    //CAPTURE NATIVE TICK COUNT HERE
223    appStats.operationTime = (DWORD)(GetTicks() - startTicks)/callibrationValue;
224    
225
226         /* Write Results to a file*/
227     if(hFile!= NULL)
228     { 
229         for( i = 0; i < THREAD_COUNT; i++ )
230         {  
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);
234         }
235     }
236     fclose(hFile);
237
238         
239
240         //Call Test Case Cleanup Routine
241         if (0!=cleanuptest())
242                 {
243                         //Error Condition
244                         printf("Error Cleaning up Test Case");
245                         exit(-1);
246                 }
247
248
249    if(hMainFile!= NULL)
250     { 
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);
253                 
254     }
255     fclose(hMainFile);
256         return 0;
257  }
258
259 void * waitforworkerthreads(void * threadId)
260 {
261
262         int *threadParam = (int*) threadId;
263         
264 //      printf("Thread ID : %d \n", *threadParam);
265         
266         //Accquire Lock 
267        if (0!=pthread_mutex_lock(&g_mutex))
268         {
269                 //Error Condition
270                         printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n");
271                         exit(-1);
272         }
273
274         //Increment Global Counter
275         GLOBAL_COUNTER++;
276         
277
278         //If global counter is equal to thread count then signal main thread
279         if (GLOBAL_COUNTER == THREAD_COUNT)
280                 {
281                         if (0!=pthread_cond_signal(&g_cv2))
282                                 {
283                                         //Error Condition
284                                         printf("Error in setting conditional variable\n");
285                                         exit(-1);
286                                 }
287                 }
288
289         //Wait for main thread to signal
290         if (0!=pthread_cond_wait(&g_cv,&g_mutex))
291                 {
292                         //Error Condition
293                         printf("Error waiting on conditional variable in Worker Thread\n");
294                         exit(-1);
295                 }
296
297         //Release the mutex lock
298         if (0!=pthread_mutex_unlock(&g_mutex))
299                 {
300                         //Error Condition
301                         printf("Error Releasing Mutex Lock in Worker Thread\n");
302                         exit(-1);
303                 }
304
305         //Start the test  
306         starttests(*threadParam);
307         
308 }
309
310 void starttests(int threadID)
311 {
312         /*All threads beign executing tests cases*/     
313         int i = 0;
314         int Id = threadID;
315         struct statistics stats;
316         ULONGLONG startTime = 0;
317         ULONGLONG endTime = 0;
318
319         LONG volatile Destination;
320         LONG Exchange;
321         LONG Comperand;
322         LONG result;
323
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;
330                 
331         //Enter and Leave Critical Section in a loop REPEAT_COUNT Times
332         
333         
334         startTime = GetTicks();
335
336         for (i=0;i<REPEAT_COUNT;i++)
337         {
338                   Destination = (LONG volatile) threadID;
339                   Exchange    = (LONG) i;
340                   Comperand   = (LONG) threadID;
341                   result = InterlockedCompareExchange(&Destination, Exchange, Comperand);
342
343                   if( i != result )
344                   {
345                        stats.operationsFailed++;
346                        stats.operationsTotal++;
347                        continue;
348                   }
349
350         }
351                   
352
353         stats.operationTime = (DWORD)(GetTicks() - startTime)/callibrationValue;
354
355 //      printf("Operation Time %d \n", stats.operationTime);
356         
357         if(resultBuffer->LogResult(Id, (char *)&stats))
358         {
359                 printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT);
360         }
361         
362 }
363
364 int setuptest(void)
365 {
366         
367         //Initalize Critical Section
368   /*
369         if (0!=MTXInitializeCriticalSection( &g_cs))
370                 {
371                         return -1;
372                 }
373   */
374         return 0;
375 }
376
377 int cleanuptest(void)
378 {
379         
380         //Delete Critical Section
381   /*
382         if (0!=MTXDeleteCriticalSection(&g_cs))
383                 {       
384                         return -1;
385                 }
386   */
387         return 0;
388 }
389
390 int GetParameters( int argc, char **argv)
391 {
392
393         if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) 
394        || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
395     {
396         printf("PAL -Composite Native Critical Section Test\n");
397         printf("Usage:\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"); 
402         return -1;
403     }
404  
405     
406     USE_PROCESS_COUNT = atoi(argv[1]);
407     if( USE_PROCESS_COUNT < 0) 
408     {
409         printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
410         return -1;
411     }
412
413     THREAD_COUNT = atoi(argv[2]);
414     if( THREAD_COUNT < 1) 
415     {
416         printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
417         return -1;
418     }
419
420     REPEAT_COUNT = atoi(argv[3]);
421     if( REPEAT_COUNT < 1) 
422     {
423         printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
424         return -1;
425     }
426
427     RELATION_ID = atoi(argv[4]);
428     if( RELATION_ID < 1) 
429     {
430         printf("\nInvalid RELATION_ID number, Pass greater than 1\n");
431         return -1;
432     }
433
434
435     return 0;
436 }
437
438 void incrementCounter(void)
439 {
440         g_counter ++;
441 }
442
443
444 //Implementation borrowed from pertrace.c 
445 ULONGLONG GetTicks(void)
446 {
447 #ifdef i386
448     unsigned long a, d;
449     asm volatile("rdtsc":"=a" (a), "=d" (d));
450     return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a);
451 #else
452     // #error Don''t know how to get ticks on this platform
453     return (ULONGLONG)gethrtime();
454 #endif // i386
455 }
456
457
458 /**/
459 ULONGLONG getPerfCallibrationValue(void)
460 {
461         ULONGLONG startTicks;
462         ULONGLONG endTicks;
463         
464         startTicks = GetTicks(); 
465         sleep(1);
466         endTicks = GetTicks();
467         
468         return ((endTicks-startTicks)/1000);  //Return number of Ticks in One Milliseconds
469
470 }
471