made initTraceLibPN called from DYNINSTinitTraceLib.
[dyninst.git] / rtinst / src / RTcm5_pn.c
1 /*
2  * This file contains the implementation of runtime dynamic instrumentation
3  *   functions for a TMC CM-5 machine.
4  *
5  *
6  * $Log: RTcm5_pn.c,v $
7  * Revision 1.3  1993/08/26 23:07:34  hollings
8  * made initTraceLibPN called from DYNINSTinitTraceLib.
9  *
10  * Revision 1.2  1993/07/02  21:53:33  hollings
11  * removed unnecessary include files
12  *
13  * Revision 1.1  1993/07/02  21:49:35  hollings
14  * Initial revision
15  *
16  *
17  */
18 #include <signal.h>
19 #include <assert.h>
20
21 /* our include files */
22 #include <h/rtinst.h>
23 #include <h/trace.h>
24 #include <rtinst/traceio.h>
25
26 #include <cm/cmmd/amx.h>
27 #include <cm/cmmd/mp.h>
28 #include <cm/cmmd/cn.h>
29 #include <cm/cmmd/io.h>
30 #include <cm/cmmd/util.h>
31 #include <cm/cmmd/cmmd_constants.h>
32 #include <cm/cmmd.h>
33 #include <cm/cmna.h>
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stdtypes.h>
39 #include <sys/time.h>
40 #include <sys/timeb.h>
41 #include <dirent.h>
42 #include <sys/stat.h>
43 #include <sys/vfs.h>
44 #include <cm/cm_file.h>
45 #include <cm/cm_errno.h>
46 #include <errno.h>
47 #include <sys/un.h>
48 #include <sys/socket.h>
49 #include <netdb.h>
50 #include <netinet/in.h>
51 #include <fcntl.h>
52 #include <sys/filio.h>
53 #include <math.h>
54
55 #define NI_CLK_USEC 33
56 #define MILLION 1000000
57
58 void DYNINSTstartWallTimer(tTimer *timer)
59 {
60     if (timer->trigger && (!timer->trigger->value)) return;
61     if (timer->counter == 0) {
62          CMOS_get_time(&timer->start);
63          timer->normalize = NI_CLK_USEC * MILLION;
64     }
65     /* this must be last to prevent race conditions with the sampler */
66     timer->counter++;
67 }
68
69 void DYNINSTstopWallTimer(tTimer *timer)
70 {
71     time64 end;
72
73     if (timer->trigger && (timer->trigger->value <= 0)) return;
74     if (!timer->counter) return;
75
76     if (timer->counter == 1) {
77          CMOS_get_time(&end);
78          timer->total += (end - timer->start);
79     }
80     /* this must be last to prevent race conditions with the sampler */
81     timer->counter--;
82 }
83
84
85 void DYNINSTstartProcessTimer(tTimer *timer)
86 {
87     if (timer->trigger && (!timer->trigger->value)) return;
88     if (timer->counter == 0) {
89          CMOS_get_time(&timer->start);
90          CMOS_get_NI_time(&timer->ni_start);
91          timer->normalize = NI_CLK_USEC * MILLION;
92     }
93     /* this must be last to prevent race conditions with the sampler */
94     timer->counter++;
95 }
96
97 void DYNINSTstopProcessTimer(tTimer *timer)
98 {
99     time64 end;
100     time64 ni_end;
101
102     if (timer->trigger && (timer->trigger->value <= 0)) return;
103     if (!timer->counter) return;
104
105     if (timer->counter == 1) {
106          CMOS_get_time(&end);
107          CMOS_get_NI_time(&ni_end);
108          timer->total += (end - timer->start);
109          timer->total -= (ni_end - timer->ni_start);
110 #ifdef notdef
111          if (timer->total < 0) abort();
112 #endif
113     }
114     /* this must be last to prevent race conditions with the sampler */
115     timer->counter--;
116 }
117
118 void DYNINSTreportTimer(tTimer *timer)
119 {
120     time64 now;
121     double value;
122     time64 total;
123     time64 ni_now;
124     traceSample sample;
125
126
127     total = timer->total;
128     if (timer->counter) {
129         /* timer is running */
130
131         CMOS_get_time(&now);
132         CMOS_get_NI_time(&ni_now);
133         if (timer->type == processTime) {
134             total += (now - ni_now) - (timer->start - timer->ni_start);
135         } else {
136             total += (now - timer->start);
137         }
138     }
139     if (total < 0) {
140         double w1, w2, ni1, ni2;
141
142         w1 = timer->start;
143         w2 = now;
144         ni1 = timer->ni_start;
145         ni2 = ni_now;
146         abort();
147     }
148
149     sample.value = total / (double) timer->normalize;
150     sample.id = timer->id;
151
152     DYNINSTgenerateTraceRecord(0, TR_SAMPLE, sizeof(sample), &sample);
153 }
154
155 time64 startWall;
156 int DYNINSTnoHandlers;
157
158 /*
159  * should be called before main in each process1.
160  *
161  */
162 void DYNINSTinit()
163 {
164     char *interval;
165     struct timeval tv;
166     time64 startNItime;
167     extern void DYNINSTalarmExpire();
168
169     CMOS_get_time(&startNItime);
170     gettimeofday(&tv, NULL);
171
172     startWall = tv.tv_sec;
173     startWall *= MILLION;
174     startWall += tv.tv_usec;
175
176     /* change time base to ni time */
177     startWall *= NI_CLK_USEC;
178
179     startWall -= startNItime;
180
181 /*     initTraceLibPN(); */
182 }
183
184 /*
185  * DYNINSTinitTraceLib - call initTraceLibPN & trap back.
186  *
187  */
188 asm(".global _DYNINSTinitTraceLib");
189 asm("_DYNINSTinitTraceLib:");
190 asm("   call    _initTraceLibPN");
191 asm("   nop     ");
192 asm("   ta 0x1");
193 asm("   nop     ");
194
195 void DYNINSTexit()
196 {
197     cleanupTraceLibPN();
198 }
199
200 /*
201  * generate a trace record onto the named stream.
202  *
203  */
204 void DYNINSTgenerateTraceRecord(traceStream sid, short type, short length,
205     void *eventData)
206 {
207     int ret;
208     int count;
209     time64 pTime;
210     double newVal;
211     char buffer[1024];
212     traceSample *sample;
213     traceHeader header;
214
215     /* check and see if we should aggregate to other nodes */
216     if ((type == TR_SAMPLE) && (((traceSample*) eventData)->id.aggregate)) {
217          /* not ready yet! */
218          abort();
219
220          /* use reduction net to compute aggregate */
221          sample = (traceSample*) eventData;
222          /* newVal = CMMD_reduce_float(sample->value, CMMD_combiner_fadd); */
223          newVal = CMCN_reduce_float(sample->value, CMMD_combiner_fadd);
224          sample->value = newVal;
225
226
227          /* only node zero reports value */
228          if (CMMD_self_address()) return;
229     }
230
231     CMOS_get_time(&header.wall);
232     header.wall += startWall;
233     header.wall /= NI_CLK_USEC;
234
235     CMOS_get_time(&header.process);
236     CMOS_get_NI_time(&pTime);
237     header.process -= pTime;
238     header.process /= NI_CLK_USEC;
239
240     header.type = type;
241     header.length = length;
242     count = 0;
243     memcpy(&buffer[count], &sid, sizeof(traceStream));
244     count += sizeof(traceStream);
245
246     memcpy(&buffer[count], &header, sizeof(header));
247     count += sizeof(header);
248
249     memcpy(&buffer[count], eventData, length);
250     count += length;
251
252     TRACE(buffer, count);
253 }
254
255 void DYNINSTbreakPoint(int arg)
256 {
257     /* printf("Break point %d reached\n", arg); */
258     asm("ta 0x81");
259 }