From a92e11a256d8a527d547a2772992d9d9870fa817 Mon Sep 17 00:00:00 2001 From: Dmitriy Vyukov Date: Wed, 20 Feb 2013 12:13:04 +0400 Subject: [PATCH] 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 --- src/pkg/runtime/proc.c | 8 -------- src/pkg/runtime/proc_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index f8ddf9b47e5..5c60cddf9ba 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -397,14 +397,6 @@ canaddmcpu(void) static void 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(gp->idlem != nil) { if(gp->idlem->idleg != nil) { diff --git a/src/pkg/runtime/proc_test.go b/src/pkg/runtime/proc_test.go index 927bd7b816a..1f727da073c 100644 --- a/src/pkg/runtime/proc_test.go +++ b/src/pkg/runtime/proc_test.go @@ -46,6 +46,36 @@ func TestStopTheWorldDeadlock(t *testing.T) { 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) { const N = 10 c := make(chan bool)