buildscript options to enable exaclty which coreprof events are needed, keeps instrum...
[IRC.git] / Robust / src / Runtime / coreprof / coreprof.c
1 #include "runtime.h"
2 #include "coreprof.h"
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "mlp_lock.h"
10
11 __thread int                     cp_threadnum;
12 __thread struct coreprofmonitor* cp_monitor     = NULL;
13          struct coreprofmonitor* cp_monitorList = NULL;
14 static volatile int              cp_threadCount = 0;
15
16
17 static inline int atomicinc(volatile int *lock) {
18   int retval=1;
19   __asm__ __volatile__("lock; xadd %0,%1"
20                        : "=r"(retval)
21                        : "m"(*lock), "0"(retval)
22                        : "memory");
23   return retval;
24 }
25
26
27 // Need to have global lock before calling this method
28 void cp_create() {
29   if( cp_monitor != NULL )
30     return;
31
32   struct coreprofmonitor* monitor = 
33     calloc( 1, sizeof( struct coreprofmonitor ) );
34
35   if( monitor == NULL ) {
36     printf( "ERROR: calloc returned NULL\n" );
37     exit( -1 );
38   }
39
40   struct coreprofmonitor* tmp;
41
42   // add ourself to the list
43   do {
44     tmp           = cp_monitorList;
45     monitor->next = tmp;
46   } while( CAS( &cp_monitorList, 
47                 (INTPTR) tmp, 
48                 (INTPTR) monitor 
49                 ) != ((INTPTR)tmp)
50            );
51
52   int ourcount = atomicinc( &cp_threadCount );
53   cp_threadnum = ourcount;
54
55   // point thread lock variable to event monitor
56   cp_monitor = monitor;
57 #ifdef CP_EVENTID_MAIN
58   CP_LOGEVENT( CP_EVENTID_MAIN, CP_EVENTTYPE_BEGIN );
59 #endif
60 }
61
62 // Place to do shutdown stuff
63 void cp_exit() {
64 #ifdef CP_EVENTID_MAIN
65   CP_LOGEVENT( CP_EVENTID_MAIN, CP_EVENTTYPE_END );
66 #endif
67 }
68
69 void cp_writedata( int fd, char* buffer, int count ) {
70   int offset = 0;
71   while( count > 0 ) {
72     int size = write( fd, &buffer[offset], count );
73     offset += size;
74     count  -= size;
75   }
76 }
77
78
79 void cp_dump() {
80   
81   int fd = open( "coreprof.dat", O_RDWR | O_CREAT, S_IRWXU );
82   int numThreads = 0;
83   int i;
84
85   struct coreprofmonitor* monitor;
86
87   // WRITING HEADER
88
89   // Write version number
90   int version = 0;
91   cp_writedata( fd, 
92                 (char*)&version, 
93                 sizeof( int ) );
94
95   // Write the number of threads
96   monitor = cp_monitorList;
97   while( monitor != NULL ) {
98     numThreads++;
99     monitor = monitor->next;
100   }
101   cp_writedata( fd, 
102                 (char*)&numThreads, 
103                 sizeof( int ) );
104
105   // Write the number of words used to log
106   // events for each thread
107   monitor = cp_monitorList;
108   while( monitor != NULL ) {
109     cp_writedata( fd, 
110                   (char*)&monitor->numWords, 
111                   sizeof( int ) );
112     monitor = monitor->next;
113   }
114
115   // END HEADER, BEGIN DATA
116   monitor = cp_monitorList;
117   while( monitor != NULL ) {
118     cp_writedata( fd, 
119                   (char*)monitor->data, 
120                   sizeof( unsigned int )*monitor->numWords );
121     monitor = monitor->next;
122   }
123
124   close( fd );
125 }
126
127
128 void cp_reportOverflow() {
129   printf( "ERROR: coreprof event overflow\n" ); 
130   exit( -1 );
131 }