void runtime·MProf_Malloc(void*, uintptr);
void runtime·MProf_Free(void*, uintptr);
void runtime·MProf_GC(void);
-int32 runtime·helpgc(bool*);
+int32 runtime·gcprocs(void);
+void runtime·helpgc(int32 nproc);
void runtime·gchelper(void);
bool runtime·getfinalizer(void *p, bool del, void (**fn)(void*), int32 *nret);
if(s == nil)
continue;
-
p = (byte*)((uintptr)s->start<<PageShift);
if(s->sizeclass == 0) {
obj = p;
int32 nret;
FinBlock *block;
Finalizer *f;
-
+
if(!runtime·getfinalizer(p, true, &fn, &nret)) {
runtime·setblockspecial(p, false);
runtime·MProf_Free(p, size);
f->fn = fn;
f->nret = nret;
f->arg = p;
- runtime·unlock(&finlock);
+ runtime·unlock(&finlock);
return true;
}
int64 t0, t1, t2, t3;
uint64 heap0, heap1, obj0, obj1;
byte *p;
- bool extra;
GCStats stats;
// The gc is turned off (via enablegc) until
m->gcing = 1;
runtime·stoptheworld();
- cachestats(nil);
- heap0 = mstats.heap_alloc;
- obj0 = mstats.nmalloc - mstats.nfree;
+ heap0 = 0;
+ obj0 = 0;
+ if(gctrace) {
+ cachestats(nil);
+ heap0 = mstats.heap_alloc;
+ obj0 = mstats.nmalloc - mstats.nfree;
+ }
runtime·lock(&work.markgate);
runtime·lock(&work.sweepgate);
- extra = false;
- work.nproc = 1;
- if(runtime·gomaxprocs > 1 && runtime·ncpu > 1) {
+ work.nproc = runtime·gcprocs();
+ if(work.nproc > 1) {
runtime·noteclear(&work.alldone);
- work.nproc += runtime·helpgc(&extra);
+ runtime·helpgc(work.nproc);
}
work.nwait = 0;
work.ndone = 0;
runtime·MProf_GC();
runtime·semrelease(&runtime·worldsema);
-
- // If we could have used another helper proc, start one now,
- // in the hope that it will be available next time.
- // It would have been even better to start it before the collection,
- // but doing so requires allocating memory, so it's tricky to
- // coordinate. This lazy approach works out in practice:
- // we don't mind if the first couple gc rounds don't have quite
- // the maximum number of procs.
- runtime·starttheworld(extra);
+ runtime·starttheworld();
// give the queued finalizers, if any, a chance to run
if(finq != nil)
*stats = mstats;
m->gcing = 0;
runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld(false);
+ runtime·starttheworld();
}
static void
if(all) {
m->gcing = 0;
runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld(false);
+ runtime·starttheworld();
}
}
m->gcing = 0;
runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld(false);
+ runtime·starttheworld();
}
}
}
int32
-runtime·helpgc(bool *extra)
+runtime·gcprocs(void)
{
- M *mp;
- int32 n, max;
-
- // Figure out how many CPUs to use.
+ int32 n;
+
+ // Figure out how many CPUs to use during GC.
// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
- max = runtime·gomaxprocs;
- if(max > runtime·ncpu)
- max = runtime·ncpu;
- if(max > MaxGcproc)
- max = MaxGcproc;
+ n = runtime·gomaxprocs;
+ if(n > runtime·ncpu)
+ n = runtime·ncpu;
+ if(n > MaxGcproc)
+ n = MaxGcproc;
+ if(n > runtime·sched.mwait+1) // one M is currently running
+ n = runtime·sched.mwait+1;
+ return n;
+}
- // We're going to use one CPU no matter what.
- // Figure out the max number of additional CPUs.
- max--;
+void
+runtime·helpgc(int32 nproc)
+{
+ M *mp;
+ int32 n;
runtime·lock(&runtime·sched);
- n = 0;
- while(n < max && (mp = mget(nil)) != nil) {
- n++;
+ for(n = 1; n < nproc; n++) { // one M is currently running
+ mp = mget(nil);
+ if(mp == nil)
+ runtime·throw("runtime·gcprocs inconsistency");
mp->helpgc = 1;
mp->waitnextg = 0;
runtime·notewakeup(&mp->havenextg);
}
runtime·unlock(&runtime·sched);
- if(extra)
- *extra = n != max;
- return n;
}
void
}
void
-runtime·starttheworld(bool extra)
+runtime·starttheworld(void)
{
M *m;
+ int32 max;
+
+ // Figure out how many CPUs GC could possibly use.
+ max = runtime·gomaxprocs;
+ if(max > runtime·ncpu)
+ max = runtime·ncpu;
+ if(max > MaxGcproc)
+ max = MaxGcproc;
schedlock();
runtime·gcwaiting = 0;
setmcpumax(runtime·gomaxprocs);
matchmg();
- if(extra && canaddmcpu()) {
- // Start a new m that will (we hope) be idle
- // and so available to help when the next
- // garbage collection happens.
+ if(runtime·gcprocs() < max && canaddmcpu()) {
+ // If GC could have used another helper proc, start one now,
+ // in the hope that it will be available next time.
+ // It would have been even better to start it before the collection,
+ // but doing so requires allocating memory, so it's tricky to
+ // coordinate. This lazy approach works out in practice:
+ // we don't mind if the first couple gc rounds don't have quite
+ // the maximum number of procs.
// canaddmcpu above did mcpu++
// (necessary, because m will be doing various
// initialization work so is definitely running),
#pragma varargck type "S" String
void runtime·stoptheworld(void);
-void runtime·starttheworld(bool);
+void runtime·starttheworld(void);
extern uint32 runtime·worldsema;
/*