diff options
author | Shenghou Ma <minux@golang.org> | 2014-10-27 20:35:15 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-10-27 20:35:15 -0400 |
commit | 2fe9482343a4321d54dac5eca5eb04e06aea29d6 (patch) | |
tree | 5b0bf54eb62f351a4f9f887c048abacee3edfb24 | |
parent | 2eb1b658305bfd32774fd1e6a32cd6463564cf89 (diff) | |
download | go-2fe9482343a4321d54dac5eca5eb04e06aea29d6.tar.gz go-2fe9482343a4321d54dac5eca5eb04e06aea29d6.zip |
runtime: add fake time support back.
Revived from CL 15690048.
Fixes #5356.
LGTM=rsc
R=adg, dvyukov, rsc
CC=golang-codereviews
https://golang.org/cl/101400043
-rw-r--r-- | src/runtime/proc.c | 20 | ||||
-rw-r--r-- | src/runtime/rt0_nacl_amd64p32.s | 4 | ||||
-rw-r--r-- | src/runtime/sys_nacl_amd64p32.s | 6 | ||||
-rw-r--r-- | src/runtime/time.go | 29 |
4 files changed, 51 insertions, 8 deletions
diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 1426790f40..52f7ef3a5b 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -2758,6 +2758,8 @@ static void checkdead(void) { G *gp; + P *p; + M *mp; int32 run, grunning, s; uintptr i; @@ -2799,6 +2801,24 @@ checkdead(void) runtime·unlock(&runtime·allglock); if(grunning == 0) // possible if main goroutine calls runtime·Goexit() runtime·throw("no goroutines (main called runtime.Goexit) - deadlock!"); + + // Maybe jump time forward for playground. + if((gp = runtime·timejump()) != nil) { + runtime·casgstatus(gp, Gwaiting, Grunnable); + globrunqput(gp); + p = pidleget(); + if(p == nil) + runtime·throw("checkdead: no p for timer"); + mp = mget(); + if(mp == nil) + newm(nil, p); + else { + mp->nextp = p; + runtime·notewakeup(&mp->park); + } + return; + } + g->m->throwing = -1; // do not dump full stacks runtime·throw("all goroutines are asleep - deadlock!"); } diff --git a/src/runtime/rt0_nacl_amd64p32.s b/src/runtime/rt0_nacl_amd64p32.s index d8703dc0f0..6ad8bea6c7 100644 --- a/src/runtime/rt0_nacl_amd64p32.s +++ b/src/runtime/rt0_nacl_amd64p32.s @@ -25,6 +25,6 @@ TEXT _rt0_amd64p32_nacl(SB),NOSPLIT,$16 TEXT main(SB),NOSPLIT,$0 // Uncomment for fake time like on Go Playground. - //MOVQ $1257894000000000000, AX - //MOVQ AX, runtime·timens(SB) + MOVQ $1257894000000000000, AX + MOVQ AX, runtime·faketime(SB) JMP runtime·rt0_go(SB) diff --git a/src/runtime/sys_nacl_amd64p32.s b/src/runtime/sys_nacl_amd64p32.s index c30c2a8933..4eb4aacdd5 100644 --- a/src/runtime/sys_nacl_amd64p32.s +++ b/src/runtime/sys_nacl_amd64p32.s @@ -60,7 +60,7 @@ TEXT syscall·naclWrite(SB), NOSPLIT, $24-20 TEXT runtime·write(SB),NOSPLIT,$16-20 // If using fake time and writing to stdout or stderr, // emit playback header before actual data. - MOVQ runtime·timens(SB), AX + MOVQ runtime·faketime(SB), AX CMPQ AX, $0 JEQ write MOVL fd+0(FP), DI @@ -242,7 +242,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$8 RET TEXT time·now(SB),NOSPLIT,$16 - MOVQ runtime·timens(SB), AX + MOVQ runtime·faketime(SB), AX CMPQ AX, $0 JEQ realtime MOVQ $0, DX @@ -277,7 +277,7 @@ TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0 RET TEXT runtime·nanotime(SB),NOSPLIT,$16 - MOVQ runtime·timens(SB), AX + MOVQ runtime·faketime(SB), AX CMPQ AX, $0 JEQ 3(PC) MOVQ AX, ret+0(FP) diff --git a/src/runtime/time.go b/src/runtime/time.go index 8cf9eecf83..11862c7e23 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -35,8 +35,8 @@ var timers struct { t []*timer } -// nacl fake time support. -var timens int64 +// nacl fake time support - time in nanoseconds since 1970 +var faketime int64 // Package time APIs. // Godoc uses the comments in package time, not these. @@ -194,7 +194,7 @@ func timerproc() { f(arg, seq) lock(&timers.lock) } - if delta < 0 { + if delta < 0 || faketime > 0 { // No timers left - put goroutine to sleep. timers.rescheduling = true goparkunlock(&timers.lock, "timer goroutine (idle)") @@ -208,6 +208,29 @@ func timerproc() { } } +func timejump() *g { + if faketime == 0 { + return nil + } + + lock(&timers.lock) + if !timers.created || len(timers.t) == 0 { + unlock(&timers.lock) + return nil + } + + var gp *g + if faketime < timers.t[0].when { + faketime = timers.t[0].when + if timers.rescheduling { + timers.rescheduling = false + gp = timers.gp + } + } + unlock(&timers.lock) + return gp +} + // Heap maintenance algorithms. func siftupTimer(i int) { |