1
0
mirror of https://github.com/golang/go synced 2024-11-26 06:07:57 -07:00

runtime: do not park sysmon thread if any goroutines are running

Sysmon thread parks if no goroutines are running (runtime.sched.npidle == runtime.gomaxprocs).
Currently it's unparked when a goroutine enters syscall, it was enough
to retake P's from blocking syscalls.
But it's not enough for reliable goroutine preemption. We need to ensure that
sysmon runs if any goroutines are running.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/12167043
This commit is contained in:
Dmitriy Vyukov 2013-07-31 19:59:27 +04:00
parent e8018fbebe
commit 156e8b306d

View File

@ -1536,6 +1536,10 @@ exitsyscallfast(void)
if(runtime·sched.pidle) { if(runtime·sched.pidle) {
runtime·lock(&runtime·sched); runtime·lock(&runtime·sched);
p = pidleget(); p = pidleget();
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);
if(p) { if(p) {
acquirep(p); acquirep(p);
@ -1559,6 +1563,10 @@ exitsyscall0(G *gp)
p = pidleget(); p = pidleget();
if(p == nil) if(p == nil)
globrunqput(gp); globrunqput(gp);
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);
if(p) { if(p) {
acquirep(p); acquirep(p);
@ -1924,23 +1932,37 @@ static struct {
uintptr pcbuf[100]; uintptr pcbuf[100];
} prof; } prof;
static void
System(void)
{
}
// Called if we receive a SIGPROF signal. // Called if we receive a SIGPROF signal.
void void
runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp) runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
{ {
int32 n; int32 n;
bool traceback;
// Windows does profiling in a dedicated thread w/o m.
if(!Windows && (m == nil || m->mcache == nil))
return;
if(prof.fn == nil || prof.hz == 0) if(prof.fn == nil || prof.hz == 0)
return; return;
traceback = true;
// Windows does profiling in a dedicated thread w/o m.
if(!Windows && (m == nil || m->mcache == nil))
traceback = false;
if(gp == m->g0 || gp == m->gsignal)
traceback = false;
if(m != nil && m->racecall)
traceback = false;
runtime·lock(&prof); runtime·lock(&prof);
if(prof.fn == nil) { if(prof.fn == nil) {
runtime·unlock(&prof); runtime·unlock(&prof);
return; return;
} }
n = 1;
prof.pcbuf[0] = (uintptr)pc;
if(traceback)
n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false); n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
if(n > 0) if(n > 0)
prof.fn(prof.pcbuf, n); prof.fn(prof.pcbuf, n);