// 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;
}
