Commit a92e11a2 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: ensure forward progress of runtime.Gosched() for locked goroutines

The removed code leads to the situation when M executes the same locked G again
and again.
This is https://golang.org/cl/7310096 but with return instead of break
in the nested switch.
Fixes #4820.

R=golang-dev, alex.brainman, rsc
CC=golang-dev
https://golang.org/cl/7304102
parent 92ab6fb4
...@@ -397,14 +397,6 @@ canaddmcpu(void) ...@@ -397,14 +397,6 @@ canaddmcpu(void)
static void static void
gput(G *gp) gput(G *gp)
{ {
M *mp;
// If g is wired, hand it off directly.
if((mp = gp->lockedm) != nil && canaddmcpu()) {
mnextg(mp, gp);
return;
}
// If g is the idle goroutine for an m, hand it off. // If g is the idle goroutine for an m, hand it off.
if(gp->idlem != nil) { if(gp->idlem != nil) {
if(gp->idlem->idleg != nil) { if(gp->idlem->idleg != nil) {
......
...@@ -46,6 +46,36 @@ func TestStopTheWorldDeadlock(t *testing.T) { ...@@ -46,6 +46,36 @@ func TestStopTheWorldDeadlock(t *testing.T) {
runtime.GOMAXPROCS(maxprocs) runtime.GOMAXPROCS(maxprocs)
} }
func TestYieldProgress(t *testing.T) {
testYieldProgress(t, false)
}
func TestYieldLockedProgress(t *testing.T) {
testYieldProgress(t, true)
}
func testYieldProgress(t *testing.T, locked bool) {
c := make(chan bool)
cack := make(chan bool)
go func() {
if locked {
runtime.LockOSThread()
}
for {
select {
case <-c:
cack <- true
return
default:
runtime.Gosched()
}
}
}()
time.Sleep(10 * time.Millisecond)
c <- true
<-cack
}
func TestYieldLocked(t *testing.T) { func TestYieldLocked(t *testing.T) {
const N = 10 const N = 10
c := make(chan bool) c := make(chan bool)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment