00d86ac99f
From-SVN: r212837
351 lines
10 KiB
C
351 lines
10 KiB
C
// 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<n; i++ ) {
|
|
h = h<<8 | ( h>> ( 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; i<Assoc; i++ ) {
|
|
e = &b->entry[i];
|
|
if ( e->depth != ( uintptr ) n )
|
|
continue;
|
|
for ( j=0; j<n; j++ )
|
|
if ( e->stack[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; i<Assoc; i++ )
|
|
if ( b->entry[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; i<n; i++ )
|
|
e->stack[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; i<d; i++ )
|
|
*q++ = e->stack[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; i<HashSize; i++ ) {
|
|
b = &p->hash[i];
|
|
for ( j=0; j<Assoc; j++ ) {
|
|
e = &b->entry[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;
|
|
}
|