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:
parent
e8018fbebe
commit
156e8b306d
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user