// AUTO-GENERATED by autogen.sh; DO NOT EDIT #include "runtime.h" #include "arch.h" #include "malloc.h" #include "array.h" #line 57 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" typedef struct __go_open_array Slice; #define array __values #define len __count #define cap __capacity #line 62 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" enum { HashSize = 1<<10 , LogSize = 1<<17 , Assoc = 4 , MaxStack = 64 , } ; #line 70 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" typedef struct Profile Profile; typedef struct Bucket Bucket; typedef struct Entry Entry; #line 74 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" struct Entry { uintptr count; uintptr depth; uintptr stack[MaxStack]; } ; #line 80 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" struct Bucket { Entry entry[Assoc]; } ; #line 84 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" struct Profile { bool on; Note wait; uintptr count; uintptr evicts; uintptr lost; uintptr totallost; #line 93 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" Bucket hash[HashSize]; #line 98 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" uintptr log[2][LogSize/2]; uintptr nlog; int32 toggle; uint32 handoff; #line 106 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" uint32 wtoggle; bool wholding; bool flushing; bool eod_sent; } ; #line 112 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static Lock lk; static Profile *prof; #line 115 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static void tick ( uintptr* , int32 ) ; static void add ( Profile* , uintptr* , int32 ) ; static bool evict ( Profile* , Entry* ) ; static bool flushlog ( Profile* ) ; #line 120 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static uintptr eod[3] = { 0 , 1 , 0 } ; #line 125 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static void LostProfileData ( void ) { } #line 130 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" extern void runtime_SetCPUProfileRate ( intgo ) __asm__ ( GOSYM_PREFIX "runtime.SetCPUProfileRate" ) ; #line 135 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" void runtime_SetCPUProfileRate ( intgo hz ) { uintptr *p; uintptr n; #line 142 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( hz < 0 ) hz = 0; if ( hz > 1000000 ) hz = 1000000; #line 147 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" runtime_lock ( &lk ) ; if ( hz > 0 ) { if ( prof == nil ) { prof = runtime_SysAlloc ( sizeof *prof , &mstats.other_sys ) ; if ( prof == nil ) { runtime_printf ( "runtime: cpu profiling cannot allocate memory\n" ) ; runtime_unlock ( &lk ) ; return; } } if ( prof->on || prof->handoff != 0 ) { runtime_printf ( "runtime: cannot set cpu profile rate until previous profile has finished.\n" ) ; runtime_unlock ( &lk ) ; return; } #line 163 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" prof->on = true; p = prof->log[0]; #line 167 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" *p++ = 0; *p++ = 3; *p++ = 0; *p++ = 1000000 / hz; *p++ = 0; prof->nlog = p - prof->log[0]; prof->toggle = 0; prof->wholding = false; prof->wtoggle = 0; prof->flushing = false; prof->eod_sent = false; runtime_noteclear ( &prof->wait ) ; #line 180 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" runtime_setcpuprofilerate ( tick , hz ) ; } else if ( prof != nil && prof->on ) { runtime_setcpuprofilerate ( nil , 0 ) ; prof->on = false; #line 187 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" for ( ;; ) { n = prof->handoff; if ( n&0x80000000 ) runtime_printf ( "runtime: setcpuprofile(off) twice" ) ; if ( runtime_cas ( &prof->handoff , n , n|0x80000000 ) ) break; } if ( n == 0 ) { #line 196 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" runtime_notewakeup ( &prof->wait ) ; } } runtime_unlock ( &lk ) ; } #line 202 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static void tick ( uintptr *pc , int32 n ) { add ( prof , pc , n ) ; } #line 213 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static void add ( Profile *p , uintptr *pc , int32 n ) { int32 i , j; uintptr h , x; Bucket *b; Entry *e; #line 221 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( n > MaxStack ) n = MaxStack; #line 225 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" h = 0; for ( i=0; i> ( 8* ( sizeof ( h ) -1 ) ) ) ; x = pc[i]; h += x*31 + x*7 + x*3; } p->count++; #line 234 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" b = &p->hash[h%HashSize]; for ( i=0; ientry[i]; if ( e->depth != ( uintptr ) n ) continue; for ( j=0; jstack[j] != pc[j] ) goto ContinueAssoc; e->count++; return; ContinueAssoc:; } #line 248 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" e = &b->entry[0]; for ( i=1; ientry[i].count < e->count ) e = &b->entry[i]; if ( e->count > 0 ) { if ( !evict ( p , e ) ) { #line 255 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" p->lost++; p->totallost++; return; } p->evicts++; } #line 263 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" e->depth = n; e->count = 1; for ( i=0; istack[i] = pc[i]; } #line 275 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static bool evict ( Profile *p , Entry *e ) { int32 i , d , nslot; uintptr *log , *q; #line 281 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" d = e->depth; nslot = d+2; log = p->log[p->toggle]; if ( p->nlog+nslot > nelem ( p->log[0] ) ) { if ( !flushlog ( p ) ) return false; log = p->log[p->toggle]; } #line 290 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" q = log+p->nlog; *q++ = e->count; *q++ = d; for ( i=0; istack[i]; p->nlog = q - log; e->count = 0; return true; } #line 304 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" static bool flushlog ( Profile *p ) { uintptr *log , *q; #line 309 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( !runtime_cas ( &p->handoff , 0 , p->nlog ) ) return false; runtime_notewakeup ( &p->wait ) ; #line 313 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" p->toggle = 1 - p->toggle; log = p->log[p->toggle]; q = log; if ( p->lost > 0 ) { *q++ = p->lost; *q++ = 1; *q++ = ( uintptr ) LostProfileData; } p->nlog = q - log; return true; } #line 327 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" Slice getprofile ( Profile *p ) { uint32 i , j , n; Slice ret; Bucket *b; Entry *e; #line 335 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" ret.array = nil; ret.len = 0; ret.cap = 0; #line 339 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( p == nil ) return ret; #line 342 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( p->wholding ) { #line 345 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" for ( ;; ) { n = p->handoff; if ( n == 0 ) { runtime_printf ( "runtime: phase error during cpu profile handoff\n" ) ; return ret; } if ( n & 0x80000000 ) { p->wtoggle = 1 - p->wtoggle; p->wholding = false; p->flushing = true; goto flush; } if ( runtime_cas ( &p->handoff , n , 0 ) ) break; } p->wtoggle = 1 - p->wtoggle; p->wholding = false; } #line 364 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( p->flushing ) goto flush; #line 367 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( !p->on && p->handoff == 0 ) return ret; #line 371 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" runtime_notetsleepg ( &p->wait , -1 ) ; runtime_noteclear ( &p->wait ) ; #line 374 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" n = p->handoff; if ( n == 0 ) { runtime_printf ( "runtime: phase error during cpu profile wait\n" ) ; return ret; } if ( n == 0x80000000 ) { p->flushing = true; goto flush; } n &= ~0x80000000; #line 386 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" p->wholding = true; #line 388 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" ret.array = ( byte* ) p->log[p->wtoggle]; ret.len = n*sizeof ( uintptr ) ; ret.cap = ret.len; return ret; #line 393 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" flush: #line 398 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" for ( i=0; ihash[i]; for ( j=0; jentry[j]; if ( e->count > 0 && !evict ( p , e ) ) { #line 404 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" goto breakflush; } } } breakflush: #line 411 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( p->nlog > 0 ) { #line 414 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" ret.array = ( byte* ) p->log[p->toggle]; ret.len = p->nlog*sizeof ( uintptr ) ; ret.cap = ret.len; p->nlog = 0; return ret; } #line 422 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" if ( !p->eod_sent ) { #line 425 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" p->eod_sent = true; ret.array = ( byte* ) eod; ret.len = sizeof eod; ret.cap = ret.len; return ret; } #line 433 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" p->flushing = false; if ( !runtime_cas ( &p->handoff , p->handoff , 0 ) ) runtime_printf ( "runtime: profile flush racing with something\n" ) ; return ret; } Slice runtime_CPUProfile() __asm__ (GOSYM_PREFIX "runtime.CPUProfile"); Slice runtime_CPUProfile() { Slice ret; #line 441 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/cpuprof.goc" ret = getprofile(prof); return ret; }