aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc.c
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-09-16 17:26:16 -0700
committerKeith Randall <khr@golang.org>2014-09-16 17:26:16 -0700
commitda8cf5438aa676a99e8bb55c94011b2581743e1a (patch)
treec5ce0da4ace36faa3cae7e0a8f1891251cc0cfba /src/runtime/proc.c
parente28746c44494030e9b44aa523cd5a21ebfe39ff5 (diff)
downloadgo-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.c79
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.