aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShenghou Ma <minux@golang.org>2014-10-27 20:35:15 -0400
committerRuss Cox <rsc@golang.org>2014-10-27 20:35:15 -0400
commit2fe9482343a4321d54dac5eca5eb04e06aea29d6 (patch)
tree5b0bf54eb62f351a4f9f887c048abacee3edfb24
parent2eb1b658305bfd32774fd1e6a32cd6463564cf89 (diff)
downloadgo-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.c20
-rw-r--r--src/runtime/rt0_nacl_amd64p32.s4
-rw-r--r--src/runtime/sys_nacl_amd64p32.s6
-rw-r--r--src/runtime/time.go29
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) {