obsereved cost model.
[dyninst.git] / rtinst / src / RTfuncs.c
1 /*
2  * This file contains the implementation of runtime dynamic instrumentation
3  *   functions for a SUNOS SPARC processor.
4  *
5  * $Log: RTfuncs.c,v $
6  * Revision 1.7  1994/07/05 03:25:09  hollings
7  * obsereved cost model.
8  *
9  * Revision 1.6  1994/02/02  00:46:11  hollings
10  * Changes to make it compile with the new tree.
11  *
12  * Revision 1.5  1993/12/13  19:47:29  hollings
13  * support for DYNINSTsampleMultiple.
14  *
15  * Revision 1.4  1993/10/19  15:29:58  hollings
16  * new simpler primitives.
17  *
18  * Revision 1.3  1993/10/01  18:15:53  hollings
19  * Added filtering and resource discovery.
20  *
21  * Revision 1.2  1993/08/26  19:43:58  hollings
22  * new include syntax.
23  *
24  * Revision 1.1  1993/07/02  21:49:35  hollings
25  * Initial revision
26  *
27  *
28  */
29 #include <assert.h>
30 #include <sys/signal.h>
31 #include <stdio.h>
32
33 /*
34  * Now our include files.
35  *
36  */
37 #include "rtinst/h/trace.h"
38 #include "rtinst/h/rtinst.h"
39
40 /* This marks the end of user code in the text file. */
41 /* This is to prevent system libraries with symbols compiled into them
42  *    from adding extranious material to our inst. environment.
43  */
44 void DYNINSTendUserCode()
45 {
46 }
47
48 char DYNINSTdata[SYN_INST_BUF_SIZE];
49 char DYNINSTglobalData[SYN_INST_BUF_SIZE];
50 int DYNINSTnumSampled;
51 int DYNINSTnumReported;
52 int DYNINSTtotalAlaramExpires;
53
54 /*
55  * for now costCount is in cycles. 
56  */
57 float DYNINSTcyclesToUsec = 1/66.0;
58 extern time64 DYNINSTtotalSampleTime;
59
60 void DYNINSTreportCounter(intCounter *counter)
61 {
62     traceSample sample;
63
64     sample.value = counter->value;
65     sample.id = counter->id;
66
67     DYNINSTgenerateTraceRecord(0, TR_SAMPLE, sizeof(sample), &sample);
68 }
69
70 void DYNINSTsimplePrint()
71 {
72     printf("inside dynamic inst function\n");
73 }
74
75 void DYNINSTentryPrint(int arg)
76 {
77     printf("enter %d\n", arg);
78 }
79
80 void DYNINSTcallFrom(int arg)
81 {
82     printf("call from %d\n", arg);
83 }
84
85 void DYNINSTcallReturn(int arg)
86 {
87     printf("return to %d\n", arg);
88 }
89
90 void DYNINSTexitPrint(int arg)
91 {
92     printf("exit %d\n", arg);
93 }
94
95 volatile int DYNINSTsampleMultiple = 1;
96
97 /*
98  * This is a function that should be called when we want to sample the
99  *   timers and counters.  The code to do the sampling is added as func
100  *   entry dynamic instrumentation.
101  *
102  *   It also reports the current value of the observed cost.
103  *
104  */
105 void DYNINSTsampleValues()
106 {
107     DYNINSTnumReported++;
108 }
109
110 #define FOUR_BILLION (((double) 1.0) * 1024 * 1024 * 1024 * 4)
111
112 /* 
113  * Define a union to let us get at the bits of a 64 bit integer.
114  *
115  *  This is needed since gcc doesn't support 64 bit ints fully. 
116  *
117  *  Think at least twice before changing this.  jkh 7/2/94
118  */
119 union timeUnion {
120     unsigned int array[2];
121     int64 i64;
122 };
123
124 /*
125  * Return the observed cost of instrumentation in machine cycles.
126  *
127  */
128 int64 DYNINSTgetObservedCycles()
129 {
130     static int64 previous;
131     static union timeUnion value;
132     register unsigned int lowBits asm("%g7");
133
134     value.array[1] = lowBits;
135     if (value.i64 < previous) {
136         /*  add to high word 
137          *
138          ************************** WARNING ***************************
139          *     this assumes we sample frequenly enough to catch these *
140          **************************************************************
141          */
142         fprintf(stderr, "current %f, previous %f\n", ((double) value.i64),
143                 ((double) previous));
144         fprintf(stderr, "Warning observed cost register wrapped\n");
145         value.array[0] += 1;
146
147         fflush(stderr);
148     }
149     previous = value.i64;
150     return(value.i64);
151 }
152
153 void DYNINSTreportCost(intCounter *counter)
154 {
155     /*
156      *     This should eventually be replaced by the normal code to report
157      *     a mapped counter???
158      */
159
160     double cost;
161     int64 value; 
162     static double prevCost;
163     traceSample sample;
164
165     value = DYNINSTgetObservedCycles();
166     cost = ((double) value) * (DYNINSTcyclesToUsec / 1000000.0);
167
168     if (cost < prevCost) {
169         fprintf(stderr, "Fatal Error Cost counter went backwards\n");
170         fflush(stderr);
171         sigpause(0xffff);
172     }
173
174     prevCost = cost;
175
176     sample.value = cost;
177     sample.id = counter->id;
178
179     DYNINSTgenerateTraceRecord(0, TR_SAMPLE, sizeof(sample), &sample);
180 }
181
182 /*
183  * Call this function to generate a sample when needed.
184  *   Exception is the exit from the program which DYNINSTsampleValues should
185  *   be called directly!!!
186  *
187  */
188 void DYNINSTalarmExpire()
189 {
190     time64 start, end;
191     static int inSample;
192
193     /* should use atomic test and set for this */
194     if (inSample) return;
195
196     inSample = 1;
197
198     /* only sample every DYNINSTsampleMultiple calls */
199     DYNINSTtotalAlaramExpires++;
200     if ((++DYNINSTnumSampled % DYNINSTsampleMultiple) == 0)  {
201         start = DYNINSTgetCPUtime();
202         DYNINSTsampleValues();
203         end = DYNINSTgetCPUtime();
204         DYNINSTtotalSampleTime += end - start;
205     }
206
207     inSample = 0;
208 }
209