]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add fake time support back.
authorShenghou Ma <minux@golang.org>
Tue, 28 Oct 2014 00:35:15 +0000 (20:35 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 28 Oct 2014 00:35:15 +0000 (20:35 -0400)
Revived from CL 15690048.

Fixes #5356.

LGTM=rsc
R=adg, dvyukov, rsc
CC=golang-codereviews
https://golang.org/cl/101400043

src/runtime/proc.c
src/runtime/rt0_nacl_amd64p32.s
src/runtime/sys_nacl_amd64p32.s
src/runtime/time.go

index 1426790f407c264ce914bc920eeeb8bad3132a93..52f7ef3a5bfbca96f63904fab25e35e4e3d62207 100644 (file)
@@ -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!");
 }
index d8703dc0f028a2f2d1a9dda9296395908b575de8..6ad8bea6c75790782908bd2ee5462f60a52d9365 100644 (file)
@@ -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)
index c30c2a8933f2d69c0e70b860cfef52521d801bd3..4eb4aacdd58cad0dd2d3b02b6b60d75292ee0b35 100644 (file)
@@ -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)
index 8cf9eecf834d99d4b4d9e0fef2dec9bc2cf368e9..11862c7e23520fe9e31ad1690ee0b36c98948832 100644 (file)
@@ -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) {