aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/go/runtime/runtime2.go21
-rw-r--r--libgo/go/runtime/stubs.go6
-rw-r--r--libgo/runtime/proc.c483
4 files changed, 243 insertions, 269 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 6e29f40..f0cbae6 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-fc4ca600b2fc6de81fd3c4014542d6a50593db1a
+bf4762823c4543229867436399be3ae30b4d13bb
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index f3bbb58..7a0cc43 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -550,9 +550,6 @@ const (
_MaxGomaxprocs = 1 << 8
)
-/*
-Commented out for gccgo for now.
-
type schedt struct {
// accessed atomically. keep at top to ensure alignment on 32-bit systems.
goidgen uint64
@@ -578,18 +575,17 @@ type schedt struct {
runqsize int32
// Global cache of dead G's.
- gflock mutex
- gfreeStack *g
- gfreeNoStack *g
- ngfree int32
+ gflock mutex
+ gfree *g
+ ngfree int32
// Central cache of sudog structs.
sudoglock mutex
sudogcache *sudog
- // Central pool of available defer structs of different sizes.
+ // Central pool of available defer structs.
deferlock mutex
- deferpool [5]*_defer
+ deferpool *_defer
gcwaiting uint32 // gc is waiting to run
stopwait int32
@@ -608,7 +604,6 @@ type schedt struct {
procresizetime int64 // nanotime() of last change to gomaxprocs
totaltime int64 // ∫gomaxprocs dt up to procresizetime
}
-*/
// The m.locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
@@ -772,8 +767,10 @@ var (
ncpu int32
-// forcegc forcegcstate
-// sched schedt
+ // forcegc forcegcstate
+
+ sched schedt
+
// newprocs int32
// Information about what cpu features are available.
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index 8d90cd6..b01bc7c 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -520,3 +520,9 @@ func dumpregs(*_siginfo_t, unsafe.Pointer)
// Temporary for gccgo until we port panic.go.
func startpanic()
+
+// Temporary for gccgo until we port proc.go.
+//go:linkname getsched runtime.getsched
+func getsched() *schedt {
+ return &sched
+}
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 43ced39..d8834ad 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -351,48 +351,18 @@ runtime_mcall(void (*pfn)(G*))
//
// Design doc at http://golang.org/s/go11sched.
-typedef struct Sched Sched;
-struct Sched {
- 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.
- Lock gflock;
- G* gfree;
-
- uint32 gcwaiting; // gc is waiting to run
- int32 stopwait;
- Note stopnote;
- uint32 sysmonwait;
- Note sysmonnote;
- uint64 lastpoll;
-
- int32 profilehz; // cpu profiling rate
-};
+typedef struct schedt Sched;
enum
{
- // Number of goroutine ids to grab from runtime_sched.goidgen to local per-P cache at once.
+ // Number of goroutine ids to grab from runtime_sched->goidgen to local per-P cache at once.
// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
GoidCacheBatch = 16,
};
-Sched runtime_sched;
+extern Sched* runtime_getsched() __asm__ (GOSYM_PREFIX "runtime.getsched");
+
+static Sched* runtime_sched;
int32 runtime_gomaxprocs;
uint32 runtime_needextram = 1;
M runtime_m0;
@@ -471,6 +441,8 @@ runtime_schedinit(void)
const byte *p;
Eface i;
+ runtime_sched = runtime_getsched();
+
m = &runtime_m0;
g = &runtime_g0;
m->g0 = g;
@@ -479,7 +451,7 @@ runtime_schedinit(void)
initcontext();
- runtime_sched.maxmcount = 10000;
+ runtime_sched->maxmcount = 10000;
runtime_precisestack = 0;
// runtime_symtabinit();
@@ -500,7 +472,7 @@ runtime_schedinit(void)
runtime_goenvs();
runtime_parsedebugvars();
- runtime_sched.lastpoll = runtime_nanotime();
+ runtime_sched->lastpoll = runtime_nanotime();
procs = 1;
s = runtime_getenv("GOMAXPROCS");
p = s.str;
@@ -747,8 +719,8 @@ static void
checkmcount(void)
{
// sched lock is held
- if(runtime_sched.mcount > runtime_sched.maxmcount) {
- runtime_printf("runtime: program exceeds %d-thread limit\n", runtime_sched.maxmcount);
+ if(runtime_sched->mcount > runtime_sched->maxmcount) {
+ runtime_printf("runtime: program exceeds %d-thread limit\n", runtime_sched->maxmcount);
runtime_throw("thread exhaustion");
}
}
@@ -782,8 +754,8 @@ mcommoninit(M *mp)
mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks();
- runtime_lock(&runtime_sched);
- mp->id = runtime_sched.mcount++;
+ runtime_lock(&runtime_sched->lock);
+ mp->id = runtime_sched->mcount++;
checkmcount();
runtime_mpreinit(mp);
@@ -793,7 +765,7 @@ mcommoninit(M *mp)
// runtime_NumCgoCall() iterates over allm w/o schedlock,
// so we need to publish it safely.
runtime_atomicstorep(&runtime_allm, mp);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// Mark gp ready to run.
@@ -808,7 +780,7 @@ runtime_ready(G *gp)
}
gp->atomicstatus = _Grunnable;
runqput((P*)g->m->p, gp);
- if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0) // TODO: fast atomic
+ if(runtime_atomicload(&runtime_sched->npidle) != 0 && runtime_atomicload(&runtime_sched->nmspinning) == 0) // TODO: fast atomic
wakep();
g->m->locks--;
}
@@ -828,15 +800,15 @@ runtime_gcprocs(void)
// Figure out how many CPUs to use during GC.
// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
n = runtime_gomaxprocs;
if(n > runtime_ncpu)
n = runtime_ncpu > 0 ? runtime_ncpu : 1;
if(n > MaxGcproc)
n = MaxGcproc;
- if(n > runtime_sched.nmidle+1) // one M is currently running
- n = runtime_sched.nmidle+1;
- runtime_unlock(&runtime_sched);
+ if(n > runtime_sched->nmidle+1) // one M is currently running
+ n = runtime_sched->nmidle+1;
+ runtime_unlock(&runtime_sched->lock);
return n;
}
@@ -845,14 +817,14 @@ needaddgcproc(void)
{
int32 n;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
n = runtime_gomaxprocs;
if(n > runtime_ncpu)
n = runtime_ncpu;
if(n > MaxGcproc)
n = MaxGcproc;
- n -= runtime_sched.nmidle+1; // one M is currently running
- runtime_unlock(&runtime_sched);
+ n -= runtime_sched->nmidle+1; // one M is currently running
+ runtime_unlock(&runtime_sched->lock);
return n > 0;
}
@@ -862,7 +834,7 @@ runtime_helpgc(int32 nproc)
M *mp;
int32 n, pos;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
pos = 0;
for(n = 1; n < nproc; n++) { // one M is currently running
if(runtime_allp[pos]->mcache == g->m->mcache)
@@ -875,7 +847,7 @@ runtime_helpgc(int32 nproc)
pos++;
runtime_notewakeup(&mp->park);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// Similar to stoptheworld but best-effort and can be called several times.
@@ -893,8 +865,8 @@ runtime_freezetheworld(void)
// so try several times
for(i = 0; i < 5; i++) {
// this should tell the scheduler to not start any new goroutines
- runtime_sched.stopwait = 0x7fffffff;
- runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+ runtime_sched->stopwait = 0x7fffffff;
+ runtime_atomicstore((uint32*)&runtime_sched->gcwaiting, 1);
// this should stop running goroutines
if(!preemptall())
break; // no running goroutines
@@ -914,34 +886,34 @@ runtime_stopTheWorldWithSema(void)
P *p;
bool wait;
- runtime_lock(&runtime_sched);
- runtime_sched.stopwait = runtime_gomaxprocs;
- runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+ runtime_lock(&runtime_sched->lock);
+ runtime_sched->stopwait = runtime_gomaxprocs;
+ runtime_atomicstore((uint32*)&runtime_sched->gcwaiting, 1);
preemptall();
// stop current P
((P*)g->m->p)->status = _Pgcstop;
- runtime_sched.stopwait--;
+ runtime_sched->stopwait--;
// try to retake all P's in _Psyscall status
for(i = 0; i < runtime_gomaxprocs; i++) {
p = runtime_allp[i];
s = p->status;
if(s == _Psyscall && runtime_cas(&p->status, s, _Pgcstop))
- runtime_sched.stopwait--;
+ runtime_sched->stopwait--;
}
// stop idle P's
while((p = pidleget()) != nil) {
p->status = _Pgcstop;
- runtime_sched.stopwait--;
+ runtime_sched->stopwait--;
}
- wait = runtime_sched.stopwait > 0;
- runtime_unlock(&runtime_sched);
+ wait = runtime_sched->stopwait > 0;
+ runtime_unlock(&runtime_sched->lock);
// wait for remaining P's to stop voluntarily
if(wait) {
- runtime_notesleep(&runtime_sched.stopnote);
- runtime_noteclear(&runtime_sched.stopnote);
+ runtime_notesleep(&runtime_sched->stopnote);
+ runtime_noteclear(&runtime_sched->stopnote);
}
- if(runtime_sched.stopwait)
+ if(runtime_sched->stopwait)
runtime_throw("stoptheworld: not stopped");
for(i = 0; i < runtime_gomaxprocs; i++) {
p = runtime_allp[i];
@@ -968,13 +940,13 @@ runtime_startTheWorldWithSema(void)
gp = runtime_netpoll(false); // non-blocking
injectglist(gp);
add = needaddgcproc();
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
if(newprocs) {
procresize(newprocs);
newprocs = 0;
} else
procresize(runtime_gomaxprocs);
- runtime_sched.gcwaiting = 0;
+ runtime_sched->gcwaiting = 0;
p1 = nil;
while((p = pidleget()) != nil) {
@@ -988,11 +960,11 @@ runtime_startTheWorldWithSema(void)
p->link = (uintptr)p1;
p1 = p;
}
- if(runtime_sched.sysmonwait) {
- runtime_sched.sysmonwait = false;
- runtime_notewakeup(&runtime_sched.sysmonnote);
+ if(runtime_sched->sysmonwait) {
+ runtime_sched->sysmonwait = false;
+ runtime_notewakeup(&runtime_sched->sysmonnote);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
while(p1) {
p = p1;
@@ -1285,7 +1257,7 @@ runtime_newextram(void)
mp->locked = _LockInternal;
mp->lockedg = gp;
gp->lockedm = mp;
- gp->goid = runtime_xadd64(&runtime_sched.goidgen, 1);
+ gp->goid = runtime_xadd64(&runtime_sched->goidgen, 1);
// put on allg for garbage collector
allgadd(gp);
@@ -1439,13 +1411,13 @@ stopm(void)
runtime_throw("stopm holding p");
if(m->spinning) {
m->spinning = false;
- runtime_xadd(&runtime_sched.nmspinning, -1);
+ runtime_xadd(&runtime_sched->nmspinning, -1);
}
retry:
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
mput(m);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
runtime_notesleep(&m->park);
m = g->m;
runtime_noteclear(&m->park);
@@ -1473,18 +1445,18 @@ startm(P *p, bool spinning)
M *mp;
void (*fn)(void);
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
if(p == nil) {
p = pidleget();
if(p == nil) {
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(spinning)
- runtime_xadd(&runtime_sched.nmspinning, -1);
+ runtime_xadd(&runtime_sched->nmspinning, -1);
return;
}
}
mp = mget();
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(mp == nil) {
fn = nil;
if(spinning)
@@ -1506,39 +1478,39 @@ static void
handoffp(P *p)
{
// if it has local work, start it straight away
- if(p->runqhead != p->runqtail || runtime_sched.runqsize) {
+ if(p->runqhead != p->runqtail || runtime_sched->runqsize) {
startm(p, false);
return;
}
// no local work, check that there are no spinning/idle M's,
// otherwise our help is not required
- if(runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) == 0 && // TODO: fast atomic
- runtime_cas(&runtime_sched.nmspinning, 0, 1)) {
+ if(runtime_atomicload(&runtime_sched->nmspinning) + runtime_atomicload(&runtime_sched->npidle) == 0 && // TODO: fast atomic
+ runtime_cas(&runtime_sched->nmspinning, 0, 1)) {
startm(p, true);
return;
}
- runtime_lock(&runtime_sched);
- if(runtime_sched.gcwaiting) {
+ runtime_lock(&runtime_sched->lock);
+ if(runtime_sched->gcwaiting) {
p->status = _Pgcstop;
- if(--runtime_sched.stopwait == 0)
- runtime_notewakeup(&runtime_sched.stopnote);
- runtime_unlock(&runtime_sched);
+ if(--runtime_sched->stopwait == 0)
+ runtime_notewakeup(&runtime_sched->stopnote);
+ runtime_unlock(&runtime_sched->lock);
return;
}
- if(runtime_sched.runqsize) {
- runtime_unlock(&runtime_sched);
+ if(runtime_sched->runqsize) {
+ runtime_unlock(&runtime_sched->lock);
startm(p, false);
return;
}
// If this is the last running P and nobody is polling network,
// need to wakeup another M to poll network.
- if(runtime_sched.npidle == (uint32)runtime_gomaxprocs-1 && runtime_atomicload64(&runtime_sched.lastpoll) != 0) {
- runtime_unlock(&runtime_sched);
+ if(runtime_sched->npidle == (uint32)runtime_gomaxprocs-1 && runtime_atomicload64(&runtime_sched->lastpoll) != 0) {
+ runtime_unlock(&runtime_sched->lock);
startm(p, false);
return;
}
pidleput(p);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// Tries to add one more P to execute G's.
@@ -1547,7 +1519,7 @@ static void
wakep(void)
{
// be conservative about spinning threads
- if(!runtime_cas(&runtime_sched.nmspinning, 0, 1))
+ if(!runtime_cas(&runtime_sched->nmspinning, 0, 1))
return;
startm(nil, true);
}
@@ -1606,18 +1578,18 @@ gcstopm(void)
{
P *p;
- if(!runtime_sched.gcwaiting)
+ if(!runtime_sched->gcwaiting)
runtime_throw("gcstopm: not waiting for gc");
if(g->m->spinning) {
g->m->spinning = false;
- runtime_xadd(&runtime_sched.nmspinning, -1);
+ runtime_xadd(&runtime_sched->nmspinning, -1);
}
p = releasep();
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
p->status = _Pgcstop;
- if(--runtime_sched.stopwait == 0)
- runtime_notewakeup(&runtime_sched.stopnote);
- runtime_unlock(&runtime_sched);
+ if(--runtime_sched->stopwait == 0)
+ runtime_notewakeup(&runtime_sched->stopnote);
+ runtime_unlock(&runtime_sched->lock);
stopm();
}
@@ -1639,7 +1611,7 @@ execute(G *gp)
gp->m = g->m;
// Check whether the profiler needs to be turned on or off.
- hz = runtime_sched.profilehz;
+ hz = runtime_sched->profilehz;
if(g->m->profilehz != hz)
runtime_resetcpuprofiler(hz);
@@ -1656,7 +1628,7 @@ findrunnable(void)
int32 i;
top:
- if(runtime_sched.gcwaiting) {
+ if(runtime_sched->gcwaiting) {
gcstopm();
goto top;
}
@@ -1667,10 +1639,10 @@ top:
if(gp)
return gp;
// global runq
- if(runtime_sched.runqsize) {
- runtime_lock(&runtime_sched);
+ if(runtime_sched->runqsize) {
+ runtime_lock(&runtime_sched->lock);
gp = globrunqget((P*)g->m->p, 0);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(gp)
return gp;
}
@@ -1684,15 +1656,15 @@ top:
// If number of spinning M's >= number of busy P's, block.
// This is necessary to prevent excessive CPU consumption
// when GOMAXPROCS>>1 but the program parallelism is low.
- if(!g->m->spinning && 2 * runtime_atomicload(&runtime_sched.nmspinning) >= runtime_gomaxprocs - runtime_atomicload(&runtime_sched.npidle)) // TODO: fast atomic
+ if(!g->m->spinning && 2 * runtime_atomicload(&runtime_sched->nmspinning) >= runtime_gomaxprocs - runtime_atomicload(&runtime_sched->npidle)) // TODO: fast atomic
goto stop;
if(!g->m->spinning) {
g->m->spinning = true;
- runtime_xadd(&runtime_sched.nmspinning, 1);
+ runtime_xadd(&runtime_sched->nmspinning, 1);
}
// random steal from other P's
for(i = 0; i < 2*runtime_gomaxprocs; i++) {
- if(runtime_sched.gcwaiting)
+ if(runtime_sched->gcwaiting)
goto top;
p = runtime_allp[runtime_fastrand1()%runtime_gomaxprocs];
if(p == (P*)g->m->p)
@@ -1704,30 +1676,30 @@ top:
}
stop:
// return P and block
- runtime_lock(&runtime_sched);
- if(runtime_sched.gcwaiting) {
- runtime_unlock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
+ if(runtime_sched->gcwaiting) {
+ runtime_unlock(&runtime_sched->lock);
goto top;
}
- if(runtime_sched.runqsize) {
+ if(runtime_sched->runqsize) {
gp = globrunqget((P*)g->m->p, 0);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
return gp;
}
p = releasep();
pidleput(p);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(g->m->spinning) {
g->m->spinning = false;
- runtime_xadd(&runtime_sched.nmspinning, -1);
+ runtime_xadd(&runtime_sched->nmspinning, -1);
}
// check all runqueues once again
for(i = 0; i < runtime_gomaxprocs; i++) {
p = runtime_allp[i];
if(p && p->runqhead != p->runqtail) {
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
p = pidleget();
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(p) {
acquirep(p);
goto top;
@@ -1736,17 +1708,17 @@ stop:
}
}
// poll network
- if(runtime_xchg64(&runtime_sched.lastpoll, 0) != 0) {
+ if(runtime_xchg64(&runtime_sched->lastpoll, 0) != 0) {
if(g->m->p)
runtime_throw("findrunnable: netpoll with p");
if(g->m->spinning)
runtime_throw("findrunnable: netpoll with spinning");
gp = runtime_netpoll(true); // block until new work is available
- runtime_atomicstore64(&runtime_sched.lastpoll, runtime_nanotime());
+ runtime_atomicstore64(&runtime_sched->lastpoll, runtime_nanotime());
if(gp) {
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
p = pidleget();
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(p) {
acquirep(p);
injectglist((G*)gp->schedlink);
@@ -1767,15 +1739,15 @@ resetspinning(void)
if(g->m->spinning) {
g->m->spinning = false;
- nmspinning = runtime_xadd(&runtime_sched.nmspinning, -1);
+ nmspinning = runtime_xadd(&runtime_sched->nmspinning, -1);
if(nmspinning < 0)
runtime_throw("findrunnable: negative nmspinning");
} else
- nmspinning = runtime_atomicload(&runtime_sched.nmspinning);
+ nmspinning = runtime_atomicload(&runtime_sched->nmspinning);
// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
// so see if we need to wakeup another P here.
- if (nmspinning == 0 && runtime_atomicload(&runtime_sched.npidle) > 0)
+ if (nmspinning == 0 && runtime_atomicload(&runtime_sched->npidle) > 0)
wakep();
}
@@ -1789,16 +1761,16 @@ injectglist(G *glist)
if(glist == nil)
return;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
for(n = 0; glist; n++) {
gp = glist;
glist = (G*)gp->schedlink;
gp->atomicstatus = _Grunnable;
globrunqput(gp);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
- for(; n && runtime_sched.npidle; n--)
+ for(; n && runtime_sched->npidle; n--)
startm(nil, false);
}
@@ -1814,7 +1786,7 @@ schedule(void)
runtime_throw("schedule: holding locks");
top:
- if(runtime_sched.gcwaiting) {
+ if(runtime_sched->gcwaiting) {
gcstopm();
goto top;
}
@@ -1826,10 +1798,10 @@ top:
tick = ((P*)g->m->p)->schedtick;
// This is a fancy way to say tick%61==0,
// it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
- if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime_sched.runqsize > 0) {
- runtime_lock(&runtime_sched);
+ if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime_sched->runqsize > 0) {
+ runtime_lock(&runtime_sched->lock);
gp = globrunqget((P*)g->m->p, 1);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(gp)
resetspinning();
}
@@ -1959,9 +1931,9 @@ runtime_gosched0(G *gp)
gp->atomicstatus = _Grunnable;
gp->m = nil;
m->curg = nil;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
globrunqput(gp);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(m->lockedg) {
stoplockedm();
execute(gp); // Never returns.
@@ -2074,25 +2046,25 @@ doentersyscall(uintptr pc, uintptr sp)
g->atomicstatus = _Gsyscall;
- if(runtime_atomicload(&runtime_sched.sysmonwait)) { // TODO: fast atomic
- runtime_lock(&runtime_sched);
- if(runtime_atomicload(&runtime_sched.sysmonwait)) {
- runtime_atomicstore(&runtime_sched.sysmonwait, 0);
- runtime_notewakeup(&runtime_sched.sysmonnote);
+ if(runtime_atomicload(&runtime_sched->sysmonwait)) { // TODO: fast atomic
+ runtime_lock(&runtime_sched->lock);
+ if(runtime_atomicload(&runtime_sched->sysmonwait)) {
+ runtime_atomicstore(&runtime_sched->sysmonwait, 0);
+ runtime_notewakeup(&runtime_sched->sysmonnote);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
g->m->mcache = nil;
((P*)(g->m->p))->m = 0;
runtime_atomicstore(&((P*)g->m->p)->status, _Psyscall);
- if(runtime_atomicload(&runtime_sched.gcwaiting)) {
- runtime_lock(&runtime_sched);
- if (runtime_sched.stopwait > 0 && runtime_cas(&((P*)g->m->p)->status, _Psyscall, _Pgcstop)) {
- if(--runtime_sched.stopwait == 0)
- runtime_notewakeup(&runtime_sched.stopnote);
+ if(runtime_atomicload(&runtime_sched->gcwaiting)) {
+ runtime_lock(&runtime_sched->lock);
+ if (runtime_sched->stopwait > 0 && runtime_cas(&((P*)g->m->p)->status, _Psyscall, _Pgcstop)) {
+ if(--runtime_sched->stopwait == 0)
+ runtime_notewakeup(&runtime_sched->stopnote);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
g->m->locks--;
@@ -2201,7 +2173,7 @@ exitsyscallfast(void)
gp = g;
// Freezetheworld sets stopwait but does not retake P's.
- if(runtime_sched.stopwait) {
+ if(runtime_sched->stopwait) {
gp->m->p = 0;
return false;
}
@@ -2215,14 +2187,14 @@ exitsyscallfast(void)
}
// Try to get any other idle P.
gp->m->p = 0;
- if(runtime_sched.pidle) {
- runtime_lock(&runtime_sched);
+ if(runtime_sched->pidle) {
+ runtime_lock(&runtime_sched->lock);
p = pidleget();
- if(p && runtime_atomicload(&runtime_sched.sysmonwait)) {
- runtime_atomicstore(&runtime_sched.sysmonwait, 0);
- runtime_notewakeup(&runtime_sched.sysmonnote);
+ if(p && runtime_atomicload(&runtime_sched->sysmonwait)) {
+ runtime_atomicstore(&runtime_sched->sysmonwait, 0);
+ runtime_notewakeup(&runtime_sched->sysmonnote);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(p) {
acquirep(p);
return true;
@@ -2243,15 +2215,15 @@ exitsyscall0(G *gp)
gp->atomicstatus = _Grunnable;
gp->m = nil;
m->curg = nil;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
p = pidleget();
if(p == nil)
globrunqput(gp);
- else if(runtime_atomicload(&runtime_sched.sysmonwait)) {
- runtime_atomicstore(&runtime_sched.sysmonwait, 0);
- runtime_notewakeup(&runtime_sched.sysmonnote);
+ else if(runtime_atomicload(&runtime_sched->sysmonwait)) {
+ runtime_atomicstore(&runtime_sched->sysmonwait, 0);
+ runtime_notewakeup(&runtime_sched->sysmonnote);
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
if(p) {
acquirep(p);
execute(gp); // Never returns.
@@ -2308,7 +2280,7 @@ syscall_runtime_AfterFork(void)
{
int32 hz;
- hz = runtime_sched.profilehz;
+ hz = runtime_sched->profilehz;
if(hz != 0)
runtime_resetcpuprofiler(hz);
runtime_m()->locks--;
@@ -2400,7 +2372,7 @@ __go_go(void (*fn)(void*), void* arg)
newg->gopc = (uintptr)__builtin_return_address(0);
newg->atomicstatus = _Grunnable;
if(p->goidcache == p->goidcacheend) {
- p->goidcache = runtime_xadd64(&runtime_sched.goidgen, GoidCacheBatch);
+ p->goidcache = runtime_xadd64(&runtime_sched->goidgen, GoidCacheBatch);
p->goidcacheend = p->goidcache + GoidCacheBatch;
}
newg->goid = p->goidcache++;
@@ -2421,7 +2393,7 @@ __go_go(void (*fn)(void*), void* arg)
runqput(p, vnewg);
- if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0 && fn != runtime_main) // TODO: fast atomic
+ if(runtime_atomicload(&runtime_sched->npidle) != 0 && runtime_atomicload(&runtime_sched->nmspinning) == 0 && fn != runtime_main) // TODO: fast atomic
wakep();
g->m->locks--;
return vnewg;
@@ -2462,15 +2434,15 @@ gfput(P *p, G *gp)
p->gfree = gp;
p->gfreecnt++;
if(p->gfreecnt >= 64) {
- runtime_lock(&runtime_sched.gflock);
+ runtime_lock(&runtime_sched->gflock);
while(p->gfreecnt >= 32) {
p->gfreecnt--;
gp = p->gfree;
p->gfree = (G*)gp->schedlink;
- gp->schedlink = (uintptr)runtime_sched.gfree;
- runtime_sched.gfree = gp;
+ gp->schedlink = (uintptr)runtime_sched->gfree;
+ runtime_sched->gfree = gp;
}
- runtime_unlock(&runtime_sched.gflock);
+ runtime_unlock(&runtime_sched->gflock);
}
}
@@ -2483,16 +2455,16 @@ gfget(P *p)
retry:
gp = p->gfree;
- if(gp == nil && runtime_sched.gfree) {
- runtime_lock(&runtime_sched.gflock);
- while(p->gfreecnt < 32 && runtime_sched.gfree) {
+ if(gp == nil && runtime_sched->gfree) {
+ runtime_lock(&runtime_sched->gflock);
+ while(p->gfreecnt < 32 && runtime_sched->gfree) {
p->gfreecnt++;
- gp = runtime_sched.gfree;
- runtime_sched.gfree = (G*)gp->schedlink;
+ gp = runtime_sched->gfree;
+ runtime_sched->gfree = (G*)gp->schedlink;
gp->schedlink = (uintptr)p->gfree;
p->gfree = gp;
}
- runtime_unlock(&runtime_sched.gflock);
+ runtime_unlock(&runtime_sched->gflock);
goto retry;
}
if(gp) {
@@ -2508,15 +2480,15 @@ gfpurge(P *p)
{
G *gp;
- runtime_lock(&runtime_sched.gflock);
+ runtime_lock(&runtime_sched->gflock);
while(p->gfreecnt) {
p->gfreecnt--;
gp = p->gfree;
p->gfree = (G*)gp->schedlink;
- gp->schedlink = (uintptr)runtime_sched.gfree;
- runtime_sched.gfree = gp;
+ gp->schedlink = (uintptr)runtime_sched->gfree;
+ runtime_sched->gfree = gp;
}
- runtime_unlock(&runtime_sched.gflock);
+ runtime_unlock(&runtime_sched->gflock);
}
void
@@ -2546,13 +2518,13 @@ runtime_GOMAXPROCS(intgo n)
if(n > _MaxGomaxprocs)
n = _MaxGomaxprocs;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
ret = (intgo)runtime_gomaxprocs;
if(n <= 0 || n == ret) {
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
return ret;
}
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
runtime_acquireWorldsema();
g->m->gcing = 1;
@@ -2653,7 +2625,7 @@ runtime_gcount(void)
int32
runtime_mcount(void)
{
- return runtime_sched.mcount;
+ return runtime_sched->mcount;
}
static struct {
@@ -2754,9 +2726,9 @@ runtime_setcpuprofilerate_m(int32 hz)
prof.hz = hz;
runtime_atomicstore(&prof.lock, 0);
- runtime_lock(&runtime_sched);
- runtime_sched.profilehz = hz;
- runtime_unlock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
+ runtime_sched->profilehz = hz;
+ runtime_unlock(&runtime_sched->lock);
if(hz != 0)
runtime_resetcpuprofiler(hz);
@@ -2809,22 +2781,22 @@ procresize(int32 new)
p->runqtail--;
gp = (G*)p->runq[p->runqtail%nelem(p->runq)];
// push onto head of global queue
- gp->schedlink = (uintptr)runtime_sched.runqhead;
- runtime_sched.runqhead = gp;
- if(runtime_sched.runqtail == nil)
- runtime_sched.runqtail = gp;
- runtime_sched.runqsize++;
+ gp->schedlink = runtime_sched->runqhead;
+ runtime_sched->runqhead = (uintptr)gp;
+ if(runtime_sched->runqtail == 0)
+ runtime_sched->runqtail = (uintptr)gp;
+ runtime_sched->runqsize++;
}
}
// fill local queues with at most nelem(p->runq)/2 goroutines
// start at 1 because current M already executes some G and will acquire allp[0] below,
// so if we have a spare G we want to put it into allp[1].
- for(i = 1; (uint32)i < (uint32)new * nelem(p->runq)/2 && runtime_sched.runqsize > 0; i++) {
- gp = runtime_sched.runqhead;
- runtime_sched.runqhead = (G*)gp->schedlink;
- if(runtime_sched.runqhead == nil)
- runtime_sched.runqtail = nil;
- runtime_sched.runqsize--;
+ for(i = 1; (uint32)i < (uint32)new * nelem(p->runq)/2 && runtime_sched->runqsize > 0; i++) {
+ gp = (G*)runtime_sched->runqhead;
+ runtime_sched->runqhead = gp->schedlink;
+ if(runtime_sched->runqhead == 0)
+ runtime_sched->runqtail = 0;
+ runtime_sched->runqsize--;
runqput(runtime_allp[i%new], gp);
}
@@ -2899,11 +2871,11 @@ releasep(void)
static void
incidlelocked(int32 v)
{
- runtime_lock(&runtime_sched);
- runtime_sched.nmidlelocked += v;
+ runtime_lock(&runtime_sched->lock);
+ runtime_sched->nmidlelocked += v;
if(v > 0)
checkdead();
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// Check for deadlock situation.
@@ -2923,7 +2895,7 @@ checkdead(void)
}
// -1 for sysmon
- run = runtime_sched.mcount - runtime_sched.nmidle - runtime_sched.nmidlelocked - 1 - countextra();
+ run = runtime_sched->mcount - runtime_sched->nmidle - runtime_sched->nmidlelocked - 1 - countextra();
if(run > 0)
return;
// If we are dying because of a signal caught on an already idle thread,
@@ -2934,7 +2906,7 @@ checkdead(void)
return;
if(run < 0) {
runtime_printf("runtime: checkdead: nmidle=%d nmidlelocked=%d mcount=%d\n",
- runtime_sched.nmidle, runtime_sched.nmidlelocked, runtime_sched.mcount);
+ runtime_sched->nmidle, runtime_sched->nmidlelocked, runtime_sched->mcount);
runtime_throw("checkdead: inconsistent counts");
}
grunning = 0;
@@ -2978,23 +2950,23 @@ sysmon(void)
delay = 10*1000;
runtime_usleep(delay);
if(runtime_debug.schedtrace <= 0 &&
- (runtime_sched.gcwaiting || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs)) { // TODO: fast atomic
- runtime_lock(&runtime_sched);
- if(runtime_atomicload(&runtime_sched.gcwaiting) || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs) {
- runtime_atomicstore(&runtime_sched.sysmonwait, 1);
- runtime_unlock(&runtime_sched);
- runtime_notesleep(&runtime_sched.sysmonnote);
- runtime_noteclear(&runtime_sched.sysmonnote);
+ (runtime_sched->gcwaiting || runtime_atomicload(&runtime_sched->npidle) == (uint32)runtime_gomaxprocs)) { // TODO: fast atomic
+ runtime_lock(&runtime_sched->lock);
+ if(runtime_atomicload(&runtime_sched->gcwaiting) || runtime_atomicload(&runtime_sched->npidle) == (uint32)runtime_gomaxprocs) {
+ runtime_atomicstore(&runtime_sched->sysmonwait, 1);
+ runtime_unlock(&runtime_sched->lock);
+ runtime_notesleep(&runtime_sched->sysmonnote);
+ runtime_noteclear(&runtime_sched->sysmonnote);
idle = 0;
delay = 20;
} else
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// poll network if not polled for more than 10ms
- lastpoll = runtime_atomicload64(&runtime_sched.lastpoll);
+ lastpoll = runtime_atomicload64(&runtime_sched->lastpoll);
now = runtime_nanotime();
if(lastpoll != 0 && lastpoll + 10*1000*1000 < now) {
- runtime_cas64(&runtime_sched.lastpoll, lastpoll, now);
+ runtime_cas64(&runtime_sched->lastpoll, lastpoll, now);
gp = runtime_netpoll(false); // non-blocking
if(gp) {
// Need to decrement number of idle locked M's
@@ -3060,7 +3032,7 @@ retake(int64 now)
// but on the other hand we want to retake them eventually
// because they can prevent the sysmon thread from deep sleep.
if(p->runqhead == p->runqtail &&
- runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) > 0 &&
+ runtime_atomicload(&runtime_sched->nmspinning) + runtime_atomicload(&runtime_sched->npidle) > 0 &&
pd->syscallwhen + 10*1000*1000 > now)
continue;
// Need to decrement number of idle locked M's
@@ -3117,14 +3089,14 @@ runtime_schedtrace(bool detailed)
if(starttime == 0)
starttime = now;
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
runtime_printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d idlethreads=%d runqueue=%d",
- (now-starttime)/1000000, runtime_gomaxprocs, runtime_sched.npidle, runtime_sched.mcount,
- runtime_sched.nmidle, runtime_sched.runqsize);
+ (now-starttime)/1000000, runtime_gomaxprocs, runtime_sched->npidle, runtime_sched->mcount,
+ runtime_sched->nmidle, runtime_sched->runqsize);
if(detailed) {
runtime_printf(" gcwaiting=%d nmidlelocked=%d nmspinning=%d stopwait=%d sysmonwait=%d\n",
- runtime_sched.gcwaiting, runtime_sched.nmidlelocked, runtime_sched.nmspinning,
- runtime_sched.stopwait, runtime_sched.sysmonwait);
+ runtime_sched->gcwaiting, runtime_sched->nmidlelocked, runtime_sched->nmspinning,
+ runtime_sched->stopwait, runtime_sched->sysmonwait);
}
// We must be careful while reading data from P's, M's and G's.
// Even if we hold schedlock, most data can be changed concurrently.
@@ -3153,7 +3125,7 @@ runtime_schedtrace(bool detailed)
}
}
if(!detailed) {
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
return;
}
for(mp = runtime_allm; mp; mp = mp->alllink) {
@@ -3185,7 +3157,7 @@ runtime_schedtrace(bool detailed)
lockedm ? lockedm->id : -1);
}
runtime_unlock(&allglock);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
}
// Put mp on midle list.
@@ -3193,9 +3165,9 @@ runtime_schedtrace(bool detailed)
static void
mput(M *mp)
{
- mp->schedlink = (uintptr)runtime_sched.midle;
- runtime_sched.midle = mp;
- runtime_sched.nmidle++;
+ mp->schedlink = runtime_sched->midle;
+ runtime_sched->midle = (uintptr)mp;
+ runtime_sched->nmidle++;
checkdead();
}
@@ -3206,9 +3178,9 @@ mget(void)
{
M *mp;
- if((mp = runtime_sched.midle) != nil){
- runtime_sched.midle = (M*)mp->schedlink;
- runtime_sched.nmidle--;
+ if((mp = (M*)runtime_sched->midle) != nil){
+ runtime_sched->midle = mp->schedlink;
+ runtime_sched->nmidle--;
}
return mp;
}
@@ -3219,12 +3191,12 @@ static void
globrunqput(G *gp)
{
gp->schedlink = 0;
- if(runtime_sched.runqtail)
- runtime_sched.runqtail->schedlink = (uintptr)gp;
+ if(runtime_sched->runqtail)
+ ((G*)runtime_sched->runqtail)->schedlink = (uintptr)gp;
else
- runtime_sched.runqhead = gp;
- runtime_sched.runqtail = gp;
- runtime_sched.runqsize++;
+ runtime_sched->runqhead = (uintptr)gp;
+ runtime_sched->runqtail = (uintptr)gp;
+ runtime_sched->runqsize++;
}
// Put a batch of runnable goroutines on the global runnable queue.
@@ -3233,12 +3205,12 @@ static void
globrunqputbatch(G *ghead, G *gtail, int32 n)
{
gtail->schedlink = 0;
- if(runtime_sched.runqtail)
- runtime_sched.runqtail->schedlink = (uintptr)ghead;
+ if(runtime_sched->runqtail)
+ ((G*)runtime_sched->runqtail)->schedlink = (uintptr)ghead;
else
- runtime_sched.runqhead = ghead;
- runtime_sched.runqtail = gtail;
- runtime_sched.runqsize += n;
+ runtime_sched->runqhead = (uintptr)ghead;
+ runtime_sched->runqtail = (uintptr)gtail;
+ runtime_sched->runqsize += n;
}
// Try get a batch of G's from the global runnable queue.
@@ -3249,24 +3221,24 @@ globrunqget(P *p, int32 max)
G *gp, *gp1;
int32 n;
- if(runtime_sched.runqsize == 0)
+ if(runtime_sched->runqsize == 0)
return nil;
- n = runtime_sched.runqsize/runtime_gomaxprocs+1;
- if(n > runtime_sched.runqsize)
- n = runtime_sched.runqsize;
+ n = runtime_sched->runqsize/runtime_gomaxprocs+1;
+ if(n > runtime_sched->runqsize)
+ n = runtime_sched->runqsize;
if(max > 0 && n > max)
n = max;
if((uint32)n > nelem(p->runq)/2)
n = nelem(p->runq)/2;
- runtime_sched.runqsize -= n;
- if(runtime_sched.runqsize == 0)
- runtime_sched.runqtail = nil;
- gp = runtime_sched.runqhead;
- runtime_sched.runqhead = (G*)gp->schedlink;
+ runtime_sched->runqsize -= n;
+ if(runtime_sched->runqsize == 0)
+ runtime_sched->runqtail = 0;
+ gp = (G*)runtime_sched->runqhead;
+ runtime_sched->runqhead = gp->schedlink;
n--;
while(n--) {
- gp1 = runtime_sched.runqhead;
- runtime_sched.runqhead = (G*)gp1->schedlink;
+ gp1 = (G*)runtime_sched->runqhead;
+ runtime_sched->runqhead = gp1->schedlink;
runqput(p, gp1);
}
return gp;
@@ -3277,9 +3249,9 @@ globrunqget(P *p, int32 max)
static void
pidleput(P *p)
{
- p->link = (uintptr)runtime_sched.pidle;
- runtime_sched.pidle = p;
- runtime_xadd(&runtime_sched.npidle, 1); // TODO: fast atomic
+ p->link = runtime_sched->pidle;
+ runtime_sched->pidle = (uintptr)p;
+ runtime_xadd(&runtime_sched->npidle, 1); // TODO: fast atomic
}
// Try get a p from pidle list.
@@ -3289,10 +3261,10 @@ pidleget(void)
{
P *p;
- p = runtime_sched.pidle;
+ p = (P*)runtime_sched->pidle;
if(p) {
- runtime_sched.pidle = (P*)p->link;
- runtime_xadd(&runtime_sched.npidle, -1); // TODO: fast atomic
+ runtime_sched->pidle = p->link;
+ runtime_xadd(&runtime_sched->npidle, -1); // TODO: fast atomic
}
return p;
}
@@ -3341,9 +3313,9 @@ runqputslow(P *p, G *gp, uint32 h, uint32 t)
for(i=0; i<n; i++)
batch[i]->schedlink = (uintptr)batch[i+1];
// Now put the batch on global queue.
- runtime_lock(&runtime_sched);
+ runtime_lock(&runtime_sched->lock);
globrunqputbatch(batch[0], batch[n], n+1);
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
return true;
}
@@ -3495,11 +3467,11 @@ runtime_setmaxthreads(intgo in)
{
intgo out;
- runtime_lock(&runtime_sched);
- out = (intgo)runtime_sched.maxmcount;
- runtime_sched.maxmcount = (int32)in;
+ runtime_lock(&runtime_sched->lock);
+ out = (intgo)runtime_sched->maxmcount;
+ runtime_sched->maxmcount = (int32)in;
checkmcount();
- runtime_unlock(&runtime_sched);
+ runtime_unlock(&runtime_sched->lock);
return out;
}
@@ -3558,7 +3530,6 @@ sync_atomic_runtime_procUnpin()
void
runtime_proc_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
{
- enqueue1(wbufp, (Obj){(byte*)&runtime_sched, sizeof runtime_sched, 0});
enqueue1(wbufp, (Obj){(byte*)&runtime_main_init_done, sizeof runtime_main_init_done, 0});
}
@@ -3567,7 +3538,7 @@ runtime_proc_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj
bool
runtime_gcwaiting(void)
{
- return runtime_sched.gcwaiting;
+ return runtime_sched->gcwaiting;
}
// os_beforeExit is called from os.Exit(0).
@@ -3602,7 +3573,7 @@ sync_runtime_canSpin(intgo i)
// GOMAXPROCS>1 and there is at least one other running P and local runq is empty.
// As opposed to runtime mutex we don't do passive spinning here,
// because there can be work on global runq on on other Ps.
- if (i >= ACTIVE_SPIN || runtime_ncpu <= 1 || runtime_gomaxprocs <= (int32)(runtime_sched.npidle+runtime_sched.nmspinning)+1) {
+ if (i >= ACTIVE_SPIN || runtime_ncpu <= 1 || runtime_gomaxprocs <= (int32)(runtime_sched->npidle+runtime_sched->nmspinning)+1) {
return false;
}
p = (P*)g->m->p;