2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / cpuprof.c
blob3398a92ea82583907fa986f3603e94e1b7daa9d1
1 // AUTO-GENERATED by autogen.sh; DO NOT EDIT
3 #include "runtime.h"
4 #include "arch.h"
5 #include "malloc.h"
6 #include "array.h"
8 #line 57 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
9 typedef struct __go_open_array Slice;
10 #define array __values
11 #define len __count
12 #define cap __capacity
13 #line 62 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
14 enum
16 HashSize = 1<<10 ,
17 LogSize = 1<<17 ,
18 Assoc = 4 ,
19 MaxStack = 64 ,
20 } ;
21 #line 70 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
22 typedef struct Profile Profile;
23 typedef struct Bucket Bucket;
24 typedef struct Entry Entry;
25 #line 74 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
26 struct Entry {
27 uintptr count;
28 uintptr depth;
29 uintptr stack[MaxStack];
30 } ;
31 #line 80 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
32 struct Bucket {
33 Entry entry[Assoc];
34 } ;
35 #line 84 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
36 struct Profile {
37 bool on;
38 Note wait;
39 uintptr count;
40 uintptr evicts;
41 uintptr lost;
42 uintptr totallost;
43 #line 93 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
44 Bucket hash[HashSize];
45 #line 98 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
46 uintptr log[2][LogSize/2];
47 uintptr nlog;
48 int32 toggle;
49 uint32 handoff;
50 #line 106 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
51 uint32 wtoggle;
52 bool wholding;
53 bool flushing;
54 bool eod_sent;
55 } ;
56 #line 112 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
57 static Lock lk;
58 static Profile *prof;
59 #line 115 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
60 static void tick ( uintptr* , int32 ) ;
61 static void add ( Profile* , uintptr* , int32 ) ;
62 static bool evict ( Profile* , Entry* ) ;
63 static bool flushlog ( Profile* ) ;
64 #line 120 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
65 static uintptr eod[3] = { 0 , 1 , 0 } ;
66 #line 125 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
67 static void
68 LostProfileData ( void )
71 #line 130 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
72 extern void runtime_SetCPUProfileRate ( intgo )
73 __asm__ ( GOSYM_PREFIX "runtime.SetCPUProfileRate" ) ;
74 #line 135 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
75 void
76 runtime_SetCPUProfileRate ( intgo hz )
78 uintptr *p;
79 uintptr n;
80 #line 142 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
81 if ( hz < 0 )
82 hz = 0;
83 if ( hz > 1000000 )
84 hz = 1000000;
85 #line 147 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
86 runtime_lock ( &lk ) ;
87 if ( hz > 0 ) {
88 if ( prof == nil ) {
89 prof = runtime_SysAlloc ( sizeof *prof , &mstats.other_sys ) ;
90 if ( prof == nil ) {
91 runtime_printf ( "runtime: cpu profiling cannot allocate memory\n" ) ;
92 runtime_unlock ( &lk ) ;
93 return;
96 if ( prof->on || prof->handoff != 0 ) {
97 runtime_printf ( "runtime: cannot set cpu profile rate until previous profile has finished.\n" ) ;
98 runtime_unlock ( &lk ) ;
99 return;
101 #line 163 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
102 prof->on = true;
103 p = prof->log[0];
104 #line 167 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
105 *p++ = 0;
106 *p++ = 3;
107 *p++ = 0;
108 *p++ = 1000000 / hz;
109 *p++ = 0;
110 prof->nlog = p - prof->log[0];
111 prof->toggle = 0;
112 prof->wholding = false;
113 prof->wtoggle = 0;
114 prof->flushing = false;
115 prof->eod_sent = false;
116 runtime_noteclear ( &prof->wait ) ;
117 #line 180 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
118 runtime_setcpuprofilerate ( tick , hz ) ;
119 } else if ( prof != nil && prof->on ) {
120 runtime_setcpuprofilerate ( nil , 0 ) ;
121 prof->on = false;
122 #line 187 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
123 for ( ;; ) {
124 n = prof->handoff;
125 if ( n&0x80000000 )
126 runtime_printf ( "runtime: setcpuprofile(off) twice" ) ;
127 if ( runtime_cas ( &prof->handoff , n , n|0x80000000 ) )
128 break;
130 if ( n == 0 ) {
131 #line 196 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
132 runtime_notewakeup ( &prof->wait ) ;
135 runtime_unlock ( &lk ) ;
137 #line 202 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
138 static void
139 tick ( uintptr *pc , int32 n )
141 add ( prof , pc , n ) ;
143 #line 213 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
144 static void
145 add ( Profile *p , uintptr *pc , int32 n )
147 int32 i , j;
148 uintptr h , x;
149 Bucket *b;
150 Entry *e;
151 #line 221 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
152 if ( n > MaxStack )
153 n = MaxStack;
154 #line 225 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
155 h = 0;
156 for ( i=0; i<n; i++ ) {
157 h = h<<8 | ( h>> ( 8* ( sizeof ( h ) -1 ) ) ) ;
158 x = pc[i];
159 h += x*31 + x*7 + x*3;
161 p->count++;
162 #line 234 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
163 b = &p->hash[h%HashSize];
164 for ( i=0; i<Assoc; i++ ) {
165 e = &b->entry[i];
166 if ( e->depth != ( uintptr ) n )
167 continue;
168 for ( j=0; j<n; j++ )
169 if ( e->stack[j] != pc[j] )
170 goto ContinueAssoc;
171 e->count++;
172 return;
173 ContinueAssoc:;
175 #line 248 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
176 e = &b->entry[0];
177 for ( i=1; i<Assoc; i++ )
178 if ( b->entry[i].count < e->count )
179 e = &b->entry[i];
180 if ( e->count > 0 ) {
181 if ( !evict ( p , e ) ) {
182 #line 255 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
183 p->lost++;
184 p->totallost++;
185 return;
187 p->evicts++;
189 #line 263 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
190 e->depth = n;
191 e->count = 1;
192 for ( i=0; i<n; i++ )
193 e->stack[i] = pc[i];
195 #line 275 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
196 static bool
197 evict ( Profile *p , Entry *e )
199 int32 i , d , nslot;
200 uintptr *log , *q;
201 #line 281 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
202 d = e->depth;
203 nslot = d+2;
204 log = p->log[p->toggle];
205 if ( p->nlog+nslot > nelem ( p->log[0] ) ) {
206 if ( !flushlog ( p ) )
207 return false;
208 log = p->log[p->toggle];
210 #line 290 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
211 q = log+p->nlog;
212 *q++ = e->count;
213 *q++ = d;
214 for ( i=0; i<d; i++ )
215 *q++ = e->stack[i];
216 p->nlog = q - log;
217 e->count = 0;
218 return true;
220 #line 304 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
221 static bool
222 flushlog ( Profile *p )
224 uintptr *log , *q;
225 #line 309 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
226 if ( !runtime_cas ( &p->handoff , 0 , p->nlog ) )
227 return false;
228 runtime_notewakeup ( &p->wait ) ;
229 #line 313 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
230 p->toggle = 1 - p->toggle;
231 log = p->log[p->toggle];
232 q = log;
233 if ( p->lost > 0 ) {
234 *q++ = p->lost;
235 *q++ = 1;
236 *q++ = ( uintptr ) LostProfileData;
238 p->nlog = q - log;
239 return true;
241 #line 327 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
242 Slice
243 getprofile ( Profile *p )
245 uint32 i , j , n;
246 Slice ret;
247 Bucket *b;
248 Entry *e;
249 #line 335 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
250 ret.array = nil;
251 ret.len = 0;
252 ret.cap = 0;
253 #line 339 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
254 if ( p == nil )
255 return ret;
256 #line 342 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
257 if ( p->wholding ) {
258 #line 345 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
259 for ( ;; ) {
260 n = p->handoff;
261 if ( n == 0 ) {
262 runtime_printf ( "runtime: phase error during cpu profile handoff\n" ) ;
263 return ret;
265 if ( n & 0x80000000 ) {
266 p->wtoggle = 1 - p->wtoggle;
267 p->wholding = false;
268 p->flushing = true;
269 goto flush;
271 if ( runtime_cas ( &p->handoff , n , 0 ) )
272 break;
274 p->wtoggle = 1 - p->wtoggle;
275 p->wholding = false;
277 #line 364 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
278 if ( p->flushing )
279 goto flush;
280 #line 367 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
281 if ( !p->on && p->handoff == 0 )
282 return ret;
283 #line 371 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
284 runtime_notetsleepg ( &p->wait , -1 ) ;
285 runtime_noteclear ( &p->wait ) ;
286 #line 374 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
287 n = p->handoff;
288 if ( n == 0 ) {
289 runtime_printf ( "runtime: phase error during cpu profile wait\n" ) ;
290 return ret;
292 if ( n == 0x80000000 ) {
293 p->flushing = true;
294 goto flush;
296 n &= ~0x80000000;
297 #line 386 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
298 p->wholding = true;
299 #line 388 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
300 ret.array = ( byte* ) p->log[p->wtoggle];
301 ret.len = n*sizeof ( uintptr ) ;
302 ret.cap = ret.len;
303 return ret;
304 #line 393 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
305 flush:
306 #line 398 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
307 for ( i=0; i<HashSize; i++ ) {
308 b = &p->hash[i];
309 for ( j=0; j<Assoc; j++ ) {
310 e = &b->entry[j];
311 if ( e->count > 0 && !evict ( p , e ) ) {
312 #line 404 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
313 goto breakflush;
317 breakflush:
318 #line 411 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
319 if ( p->nlog > 0 ) {
320 #line 414 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
321 ret.array = ( byte* ) p->log[p->toggle];
322 ret.len = p->nlog*sizeof ( uintptr ) ;
323 ret.cap = ret.len;
324 p->nlog = 0;
325 return ret;
327 #line 422 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
328 if ( !p->eod_sent ) {
329 #line 425 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
330 p->eod_sent = true;
331 ret.array = ( byte* ) eod;
332 ret.len = sizeof eod;
333 ret.cap = ret.len;
334 return ret;
336 #line 433 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
337 p->flushing = false;
338 if ( !runtime_cas ( &p->handoff , p->handoff , 0 ) )
339 runtime_printf ( "runtime: profile flush racing with something\n" ) ;
340 return ret;
342 Slice runtime_CPUProfile() __asm__ (GOSYM_PREFIX "runtime.CPUProfile");
343 Slice runtime_CPUProfile()
345 Slice ret;
346 #line 441 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc"
348 ret = getprofile(prof);
349 return ret;