]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: introduce entersyscallblock()
authorDmitriy Vyukov <dvyukov@google.com>
Wed, 20 Feb 2013 16:21:45 +0000 (20:21 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Wed, 20 Feb 2013 16:21:45 +0000 (20:21 +0400)
In preparation for the new scheduler.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7386044

src/pkg/runtime/cpuprof.c
src/pkg/runtime/mheap.c
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h
src/pkg/runtime/sigqueue.goc
src/pkg/runtime/time.goc

index 1bb768085d9c427dd9af1f44d40082482c560ab4..dbbf5554fc0a7ea678dc930a7267450b0cd4e8fb 100644 (file)
@@ -360,7 +360,7 @@ getprofile(Profile *p)
                return ret;
 
        // Wait for new log.
-       runtime·entersyscall();
+       runtime·entersyscallblock();
        runtime·notesleep(&p->wait);
        runtime·exitsyscall();
        runtime·noteclear(&p->wait);
index 3191e6f5d17a77ad5eaa41dec00461e911751939..44c9e99b487cb35e34e9bfaddad2c8fe050b9368 100644 (file)
@@ -424,7 +424,7 @@ runtime·MHeap_Scavenger(void)
        h = runtime·mheap;
        for(k=0;; k++) {
                runtime·noteclear(&note);
-               runtime·entersyscall();
+               runtime·entersyscallblock();
                runtime·notetsleep(&note, tick);
                runtime·exitsyscall();
 
@@ -438,7 +438,7 @@ runtime·MHeap_Scavenger(void)
                        runtime·noteclear(&note);
                        notep = &note;
                        runtime·newproc1((byte*)forcegchelper, (byte*)&notep, sizeof(notep), 0, runtime·MHeap_Scavenger);
-                       runtime·entersyscall();
+                       runtime·entersyscallblock();
                        runtime·notesleep(&note);
                        runtime·exitsyscall();
                        if(trace)
index 111d90b07912267bb09a91e5c302258b377def65..b83bd9066f857fc827e58d85ee805d5015baf525 100644 (file)
@@ -1049,6 +1049,59 @@ runtime·entersyscall(void)
        schedunlock();
 }
 
+// The same as runtime·entersyscall(), but with a hint that the syscall is blocking.
+// The hint is ignored at the moment, and it's just a copy of runtime·entersyscall().
+#pragma textflag 7
+void
+runtime·entersyscallblock(void)
+{
+       uint32 v;
+
+       if(m->profilehz > 0)
+               runtime·setprof(false);
+
+       // Leave SP around for gc and traceback.
+       runtime·gosave(&g->sched);
+       g->gcsp = g->sched.sp;
+       g->gcstack = g->stackbase;
+       g->gcguard = g->stackguard;
+       g->status = Gsyscall;
+       if(g->gcsp < g->gcguard-StackGuard || g->gcstack < g->gcsp) {
+               // runtime·printf("entersyscall inconsistent %p [%p,%p]\n",
+               //      g->gcsp, g->gcguard-StackGuard, g->gcstack);
+               runtime·throw("entersyscall");
+       }
+
+       // Fast path.
+       // The slow path inside the schedlock/schedunlock will get
+       // through without stopping if it does:
+       //      mcpu--
+       //      gwait not true
+       //      waitstop && mcpu <= mcpumax not true
+       // If we can do the same with a single atomic add,
+       // then we can skip the locks.
+       v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
+       if(!atomic_gwaiting(v) && (!atomic_waitstop(v) || atomic_mcpu(v) > atomic_mcpumax(v)))
+               return;
+
+       schedlock();
+       v = runtime·atomicload(&runtime·sched.atomic);
+       if(atomic_gwaiting(v)) {
+               matchmg();
+               v = runtime·atomicload(&runtime·sched.atomic);
+       }
+       if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) {
+               runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift);
+               runtime·notewakeup(&runtime·sched.stopped);
+       }
+
+       // Re-save sched in case one of the calls
+       // (notewakeup, matchmg) triggered something using it.
+       runtime·gosave(&g->sched);
+
+       schedunlock();
+}
+
 // The goroutine g exited its system call.
 // Arrange for it to run on a cpu again.
 // This is called only from the go syscall library, not
index a787cad563d45ff81106100fa14c6e1db903fb03..e63877e681c002d0eb617a26a6d943c0fc11b546 100644 (file)
@@ -692,6 +692,7 @@ M*  runtime·newm(void);
 void   runtime·goexit(void);
 void   runtime·asmcgocall(void (*fn)(void*), void*);
 void   runtime·entersyscall(void);
+void   runtime·entersyscallblock(void);
 void   runtime·exitsyscall(void);
 G*     runtime·newproc1(byte*, byte*, int32, int32, void*);
 bool   runtime·sigsend(int32 sig);
index ecc38466255f7ae33f186a5f559433462a285650..ab5f312e420134640e3d2d52c5d04d3cc881c8df 100644 (file)
@@ -105,7 +105,7 @@ func signal_recv() (m uint32) {
                                new = HASWAITER;
                        if(runtime·cas(&sig.state, old, new)) {
                                if (new == HASWAITER) {
-                                       runtime·entersyscall();
+                                       runtime·entersyscallblock();
                                        runtime·notesleep(&sig);
                                        runtime·exitsyscall();
                                        runtime·noteclear(&sig);
index e41df2c572b5083360be6d7cab3207a49846af09..d962b74e1ff1815e70ba98ec357199d7edfe1e88 100644 (file)
@@ -200,7 +200,7 @@ timerproc(void)
                timers.sleeping = true;
                runtime·noteclear(&timers.waitnote);
                runtime·unlock(&timers);
-               runtime·entersyscall();
+               runtime·entersyscallblock();
                runtime·notetsleep(&timers.waitnote, delta);
                runtime·exitsyscall();
        }