Commit 5328df65 authored by Russ Cox's avatar Russ Cox

runtime: check for preemption due to garbage collection

	in various already expensive routines.

helps keep cpu utilization up when GOMAXPROCS > 1,
but not a full solution.

http://groups.google.com/group/golang-nuts/t/7a9535c4136d3e2

R=r
CC=golang-dev
https://golang.org/cl/184043
parent 752b1702
...@@ -174,6 +174,9 @@ chansend(Hchan *c, byte *ep, bool *pres) ...@@ -174,6 +174,9 @@ chansend(Hchan *c, byte *ep, bool *pres)
SudoG *sg; SudoG *sg;
G* gp; G* gp;
if(gcwaiting)
gosched();
if(debug) { if(debug) {
prints("chansend: chan="); prints("chansend: chan=");
runtime·printpointer(c); runtime·printpointer(c);
...@@ -277,6 +280,9 @@ chanrecv(Hchan* c, byte *ep, bool* pres) ...@@ -277,6 +280,9 @@ chanrecv(Hchan* c, byte *ep, bool* pres)
SudoG *sg; SudoG *sg;
G *gp; G *gp;
if(gcwaiting)
gosched();
if(debug) { if(debug) {
prints("chanrecv: chan="); prints("chanrecv: chan=");
runtime·printpointer(c); runtime·printpointer(c);
...@@ -631,6 +637,9 @@ runtime·selectgo(Select *sel) ...@@ -631,6 +637,9 @@ runtime·selectgo(Select *sel)
G *gp; G *gp;
byte *as; byte *as;
if(gcwaiting)
gosched();
if(debug) { if(debug) {
prints("selectgo: sel="); prints("selectgo: sel=");
runtime·printpointer(sel); runtime·printpointer(sel);
...@@ -908,6 +917,9 @@ runtime·closechan(Hchan *c) ...@@ -908,6 +917,9 @@ runtime·closechan(Hchan *c)
SudoG *sg; SudoG *sg;
G* gp; G* gp;
if(gcwaiting)
gosched();
lock(c); lock(c);
incerr(c); incerr(c);
c->closed |= Wclosed; c->closed |= Wclosed;
......
...@@ -744,6 +744,9 @@ mapaccess(Hmap *h, byte *ak, byte *av, bool *pres) ...@@ -744,6 +744,9 @@ mapaccess(Hmap *h, byte *ak, byte *av, bool *pres)
{ {
byte *res; byte *res;
if(gcwaiting)
gosched();
res = nil; res = nil;
if(hash_lookup(h, ak, (void**)&res)) { if(hash_lookup(h, ak, (void**)&res)) {
*pres = true; *pres = true;
...@@ -812,6 +815,9 @@ mapassign(Hmap *h, byte *ak, byte *av) ...@@ -812,6 +815,9 @@ mapassign(Hmap *h, byte *ak, byte *av)
byte *res; byte *res;
int32 hit; int32 hit;
if(gcwaiting)
gosched();
res = nil; res = nil;
if(av == nil) { if(av == nil) {
hash_remove(h, ak, (void**)&res); hash_remove(h, ak, (void**)&res);
...@@ -908,6 +914,9 @@ mapiterinit(Hmap *h) ...@@ -908,6 +914,9 @@ mapiterinit(Hmap *h)
void void
runtime·mapiternext(struct hash_iter *it) runtime·mapiternext(struct hash_iter *it)
{ {
if(gcwaiting)
gosched();
it->data = hash_next(it); it->data = hash_next(it);
if(debug) { if(debug) {
prints("runtime·mapiternext: iter="); prints("runtime·mapiternext: iter=");
......
...@@ -27,10 +27,11 @@ mallocgc(uintptr size, uint32 refflag, int32 dogc) ...@@ -27,10 +27,11 @@ mallocgc(uintptr size, uint32 refflag, int32 dogc)
void *v; void *v;
uint32 *ref; uint32 *ref;
if(gcwaiting && g != m->g0)
gosched();
if(m->mallocing) if(m->mallocing)
throw("malloc/free - deadlock"); throw("malloc/free - deadlock");
m->mallocing = 1; m->mallocing = 1;
if(size == 0) if(size == 0)
size = 1; size = 1;
......
...@@ -244,7 +244,7 @@ gc(int32 force) ...@@ -244,7 +244,7 @@ gc(int32 force)
sweep(); sweep();
mstats.next_gc = mstats.inuse_pages+mstats.inuse_pages*gcpercent/100; mstats.next_gc = mstats.inuse_pages+mstats.inuse_pages*gcpercent/100;
} }
starttheworld();
m->gcing = 0; m->gcing = 0;
semrelease(&gcsema); semrelease(&gcsema);
starttheworld();
} }
...@@ -14,6 +14,8 @@ G g0; // idle goroutine for m0 ...@@ -14,6 +14,8 @@ G g0; // idle goroutine for m0
static int32 debug = 0; static int32 debug = 0;
int32 gcwaiting;
// Go scheduler // Go scheduler
// //
// The go scheduler's job is to match ready-to-run goroutines (`g's) // The go scheduler's job is to match ready-to-run goroutines (`g's)
...@@ -362,6 +364,7 @@ void ...@@ -362,6 +364,7 @@ void
stoptheworld(void) stoptheworld(void)
{ {
lock(&sched); lock(&sched);
gcwaiting = 1;
sched.mcpumax = 1; sched.mcpumax = 1;
while(sched.mcpu > 1) { while(sched.mcpu > 1) {
noteclear(&sched.stopped); noteclear(&sched.stopped);
...@@ -379,6 +382,7 @@ void ...@@ -379,6 +382,7 @@ void
starttheworld(void) starttheworld(void)
{ {
lock(&sched); lock(&sched);
gcwaiting = 0;
sched.mcpumax = sched.gomaxprocs; sched.mcpumax = sched.gomaxprocs;
matchmg(); matchmg();
unlock(&sched); unlock(&sched);
......
...@@ -316,6 +316,7 @@ extern int32 gomaxprocs; ...@@ -316,6 +316,7 @@ extern int32 gomaxprocs;
extern int32 panicking; extern int32 panicking;
extern int32 maxround; extern int32 maxround;
extern int32 fd; // usually 1; set to 2 when panicking extern int32 fd; // usually 1; set to 2 when panicking
extern int32 gcwaiting; // gc is waiting to run
int8* goos; int8* goos;
/* /*
......
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