#include "runtime.h"
#include "defs.h"
#include "os.h"
#include "arch.h"
#include "malloc.h"

#line 15 "/go/src/pkg/runtime/time.goc"
static Timers timers; 
static void addtimer ( Timer* ) ; 
static bool deltimer ( Timer* ) ; 
void
time·Sleep(int64 ns)
{
#line 25 "/go/src/pkg/runtime/time.goc"

	g->status = Gwaiting;
	g->waitreason = "sleep";
	runtime·tsleep(ns);
}
void
time·startTimer(Timer* t)
{
#line 32 "/go/src/pkg/runtime/time.goc"

	addtimer(t);
}
void
time·stopTimer(Timer* t, bool stopped)
{
#line 38 "/go/src/pkg/runtime/time.goc"

	stopped = deltimer(t);
	FLUSH(&stopped);
}

#line 44 "/go/src/pkg/runtime/time.goc"
static void timerproc ( void ) ; 
static void siftup ( int32 ) ; 
static void siftdown ( int32 ) ; 
#line 49 "/go/src/pkg/runtime/time.goc"
static void 
ready ( int64 now , Eface e ) 
{ 
USED ( now ) ; 
#line 54 "/go/src/pkg/runtime/time.goc"
runtime·ready ( e.data ) ; 
} 
#line 59 "/go/src/pkg/runtime/time.goc"
void 
runtime·tsleep ( int64 ns ) 
{ 
Timer t; 
#line 64 "/go/src/pkg/runtime/time.goc"
if ( ns <= 0 ) 
return; 
#line 67 "/go/src/pkg/runtime/time.goc"
t.when = runtime·nanotime ( ) + ns; 
t.period = 0; 
t.f = ready; 
t.arg.data = g; 
addtimer ( &t ) ; 
runtime·gosched ( ) ; 
} 
#line 77 "/go/src/pkg/runtime/time.goc"
static void 
addtimer ( Timer *t ) 
{ 
int32 n; 
Timer **nt; 
#line 83 "/go/src/pkg/runtime/time.goc"
runtime·lock ( &timers ) ; 
if ( timers.len >= timers.cap ) { 
#line 86 "/go/src/pkg/runtime/time.goc"
n = 16; 
if ( n <= timers.cap ) 
n = timers.cap*3 / 2; 
nt = runtime·malloc ( n*sizeof nt[0] ) ; 
runtime·memmove ( nt , timers.t , timers.len*sizeof nt[0] ) ; 
runtime·free ( timers.t ) ; 
timers.t = nt; 
timers.cap = n; 
} 
t->i = timers.len++; 
timers.t[t->i] = t; 
siftup ( t->i ) ; 
if ( t->i == 0 ) { 
#line 100 "/go/src/pkg/runtime/time.goc"
if ( timers.sleeping ) { 
timers.sleeping = false; 
runtime·notewakeup ( &timers.waitnote ) ; 
} 
if ( timers.rescheduling ) { 
timers.rescheduling = false; 
runtime·ready ( timers.timerproc ) ; 
} 
} 
if ( timers.timerproc == nil ) 
timers.timerproc = runtime·newproc1 ( ( byte* ) timerproc , nil , 0 , 0 , addtimer ) ; 
runtime·unlock ( &timers ) ; 
} 
#line 117 "/go/src/pkg/runtime/time.goc"
static bool 
deltimer ( Timer *t ) 
{ 
int32 i; 
#line 122 "/go/src/pkg/runtime/time.goc"
runtime·lock ( &timers ) ; 
#line 127 "/go/src/pkg/runtime/time.goc"
i = t->i; 
if ( i < 0 || i >= timers.len || timers.t[i] != t ) { 
runtime·unlock ( &timers ) ; 
return false; 
} 
#line 133 "/go/src/pkg/runtime/time.goc"
timers.len--; 
if ( i == timers.len ) { 
timers.t[i] = nil; 
} else { 
timers.t[i] = timers.t[timers.len]; 
timers.t[timers.len] = nil; 
timers.t[i]->i = i; 
siftup ( i ) ; 
siftdown ( i ) ; 
} 
runtime·unlock ( &timers ) ; 
return true; 
} 
#line 151 "/go/src/pkg/runtime/time.goc"
static void 
timerproc ( void ) 
{ 
int64 delta , now; 
Timer *t; 
void ( *f ) ( int64 , Eface ) ; 
Eface arg; 
#line 159 "/go/src/pkg/runtime/time.goc"
for ( ;; ) { 
runtime·lock ( &timers ) ; 
now = runtime·nanotime ( ) ; 
for ( ;; ) { 
if ( timers.len == 0 ) { 
delta = -1; 
break; 
} 
t = timers.t[0]; 
delta = t->when - now; 
if ( delta > 0 ) 
break; 
if ( t->period > 0 ) { 
#line 173 "/go/src/pkg/runtime/time.goc"
t->when += t->period * ( 1 + -delta/t->period ) ; 
siftdown ( 0 ) ; 
} else { 
#line 177 "/go/src/pkg/runtime/time.goc"
timers.t[0] = timers.t[--timers.len]; 
timers.t[0]->i = 0; 
siftdown ( 0 ) ; 
t->i = -1; 
} 
f = t->f; 
arg = t->arg; 
runtime·unlock ( &timers ) ; 
f ( now , arg ) ; 
runtime·lock ( &timers ) ; 
} 
if ( delta < 0 ) { 
#line 190 "/go/src/pkg/runtime/time.goc"
timers.rescheduling = true; 
g->status = Gwaiting; 
g->waitreason = "timer goroutine (idle)" ; 
runtime·unlock ( &timers ) ; 
runtime·gosched ( ) ; 
continue; 
} 
#line 198 "/go/src/pkg/runtime/time.goc"
timers.sleeping = true; 
runtime·noteclear ( &timers.waitnote ) ; 
runtime·unlock ( &timers ) ; 
runtime·entersyscall ( ) ; 
runtime·notetsleep ( &timers.waitnote , delta ) ; 
runtime·exitsyscall ( ) ; 
} 
} 
#line 209 "/go/src/pkg/runtime/time.goc"
static void 
siftup ( int32 i ) 
{ 
int32 p; 
Timer **t , *tmp; 
#line 215 "/go/src/pkg/runtime/time.goc"
t = timers.t; 
while ( i > 0 ) { 
p = ( i-1 ) /2; 
if ( t[i]->when >= t[p]->when ) 
break; 
tmp = t[i]; 
t[i] = t[p]; 
t[p] = tmp; 
t[i]->i = i; 
t[p]->i = p; 
i = p; 
} 
} 
#line 229 "/go/src/pkg/runtime/time.goc"
static void 
siftdown ( int32 i ) 
{ 
int32 c , len; 
Timer **t , *tmp; 
#line 235 "/go/src/pkg/runtime/time.goc"
t = timers.t; 
len = timers.len; 
for ( ;; ) { 
c = i*2 + 1; 
if ( c >= len ) { 
break; 
} 
if ( c+1 < len && t[c+1]->when < t[c]->when ) 
c++; 
if ( t[c]->when >= t[i]->when ) 
break; 
tmp = t[i]; 
t[i] = t[c]; 
t[c] = tmp; 
t[i]->i = i; 
t[c]->i = c; 
i = c; 
} 
} 