diff options
| author | Keith Randall <khr@golang.org> | 2014-09-16 17:26:16 -0700 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2014-09-16 17:26:16 -0700 |
| commit | da8cf5438aa676a99e8bb55c94011b2581743e1a (patch) | |
| tree | c5ce0da4ace36faa3cae7e0a8f1891251cc0cfba /src/runtime/proc.c | |
| parent | e28746c44494030e9b44aa523cd5a21ebfe39ff5 (diff) | |
| download | go-da8cf5438aa676a99e8bb55c94011b2581743e1a.tar.xz | |
runtime: always run semacquire on the G stack
semacquire might need to park the currently running G. It can
only park if called from the G stack (because it has no way of
saving the M stack state). So all calls to semacquire must come
from the G stack.
The three violators are GOMAXPROCS, ReadMemStats, and WriteHeapDump.
This change moves the semacquire call earlier, out of their C code
and into their Go code.
This seldom caused bugs because semacquire seldom actually had
to park the caller. But it did happen intermittently.
Fixes #8749
LGTM=dvyukov
R=golang-codereviews, dvyukov, bradfitz
CC=golang-codereviews
https://golang.org/cl/144940043
Diffstat (limited to 'src/runtime/proc.c')
| -rw-r--r-- | src/runtime/proc.c | 79 |
1 files changed, 5 insertions, 74 deletions
diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 25f9166403..0e677a9d28 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -24,42 +24,6 @@ // // Design doc at http://golang.org/s/go11sched. -typedef struct Sched Sched; -struct Sched { - Mutex lock; - - uint64 goidgen; - - M* midle; // idle m's waiting for work - int32 nmidle; // number of idle m's waiting for work - int32 nmidlelocked; // number of locked m's waiting for work - int32 mcount; // number of m's that have been created - int32 maxmcount; // maximum number of m's allowed (or die) - - P* pidle; // idle P's - uint32 npidle; - uint32 nmspinning; - - // Global runnable queue. - G* runqhead; - G* runqtail; - int32 runqsize; - - // Global cache of dead G's. - Mutex gflock; - G* gfree; - int32 ngfree; - - uint32 gcwaiting; // gc is waiting to run - int32 stopwait; - Note stopnote; - uint32 sysmonwait; - Note sysmonnote; - uint64 lastpoll; - - int32 profilehz; // cpu profiling rate -}; - enum { // Number of goroutine ids to grab from runtime·sched.goidgen to local per-P cache at once. @@ -67,7 +31,7 @@ enum GoidCacheBatch = 16, }; -Sched runtime·sched; +SchedType runtime·sched; int32 runtime·gomaxprocs; uint32 runtime·needextram; bool runtime·iscgo; @@ -79,7 +43,7 @@ M* runtime·extram; P* runtime·allp[MaxGomaxprocs+1]; int8* runtime·goos; int32 runtime·ncpu; -static int32 newprocs; +int32 runtime·newprocs; Mutex runtime·allglock; // the following vars are protected by this lock or by stoptheworld G** runtime·allg; @@ -763,9 +727,9 @@ runtime·starttheworld(void) injectglist(gp); add = needaddgcproc(); runtime·lock(&runtime·sched.lock); - if(newprocs) { - procresize(newprocs); - newprocs = 0; + if(runtime·newprocs) { + procresize(runtime·newprocs); + runtime·newprocs = 0; } else procresize(runtime·gomaxprocs); runtime·sched.gcwaiting = 0; @@ -2364,39 +2328,6 @@ runtime·Breakpoint(void) runtime·breakpoint(); } -// Implementation of runtime.GOMAXPROCS. -// delete when scheduler is even stronger -void -runtime·gomaxprocs_m(void) -{ - int32 n, ret; - - n = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - - if(n > MaxGomaxprocs) - n = MaxGomaxprocs; - runtime·lock(&runtime·sched.lock); - ret = runtime·gomaxprocs; - if(n <= 0 || n == ret) { - runtime·unlock(&runtime·sched.lock); - g->m->scalararg[0] = ret; - return; - } - runtime·unlock(&runtime·sched.lock); - - runtime·semacquire(&runtime·worldsema, false); - g->m->gcing = 1; - runtime·stoptheworld(); - newprocs = n; - g->m->gcing = 0; - runtime·semrelease(&runtime·worldsema); - runtime·starttheworld(); - - g->m->scalararg[0] = ret; - return; -} - // lockOSThread is called by runtime.LockOSThread and runtime.lockOSThread below // after they modify m->locked. Do not allow preemption during this call, // or else the m might be different in this function than in the caller. |
