Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(137)

Delta Between Two Patch Sets: src/pkg/runtime/mgc0.c

Issue 123700044: code review 123700044: runtime: convert timers to Go (Closed)
Left Patch Set: diff -r fd0a30a51d14a8a429ad72fdb5d13f7085d56d01 https://dvyukov%40google.com@code.google.com/p/go/ Created 10 years, 6 months ago
Right Patch Set: diff -r 3f13ed48b37ed52cd347d23aa321f81a4ec2c44d https://dvyukov%40google.com@code.google.com/p/go/ Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/runtime/netpoll.goc » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Garbage collector (GC). 5 // Garbage collector (GC).
6 // 6 //
7 // GC is: 7 // GC is:
8 // - mark&sweep 8 // - mark&sweep
9 // - mostly precise (with the exception of some C-allocated objects, assembly fr ames/arguments, etc) 9 // - mostly precise (with the exception of some C-allocated objects, assembly fr ames/arguments, etc)
10 // - parallel (up to MaxGcproc threads) 10 // - parallel (up to MaxGcproc threads)
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 static struct { 195 static struct {
196 uint64 full; // lock-free list of full blocks 196 uint64 full; // lock-free list of full blocks
197 uint64 empty; // lock-free list of empty blocks 197 uint64 empty; // lock-free list of empty blocks
198 byte pad0[CacheLineSize]; // prevents false-sharing between full/empt y and nproc/nwait 198 byte pad0[CacheLineSize]; // prevents false-sharing between full/empt y and nproc/nwait
199 uint32 nproc; 199 uint32 nproc;
200 int64 tstart; 200 int64 tstart;
201 volatile uint32 nwait; 201 volatile uint32 nwait;
202 volatile uint32 ndone; 202 volatile uint32 ndone;
203 Note alldone; 203 Note alldone;
204 ParFor* markfor; 204 ParFor* markfor;
205
206 // Copy of mheap.allspans for marker or sweeper.
207 MSpan** spans;
208 uint32 nspan;
205 } work; 209 } work;
206 210
207 // scanblock scans a block of n bytes starting at pointer b for references 211 // scanblock scans a block of n bytes starting at pointer b for references
208 // to other objects, scanning any it finds recursively until there are no 212 // to other objects, scanning any it finds recursively until there are no
209 // unscanned objects left. Instead of using an explicit recursion, it keeps 213 // unscanned objects left. Instead of using an explicit recursion, it keeps
210 // a work list in the Workbuf* structures and loops in the main function 214 // a work list in the Workbuf* structures and loops in the main function
211 // body. Keeping an explicit work list is easier on the stack allocator and 215 // body. Keeping an explicit work list is easier on the stack allocator and
212 // more efficient. 216 // more efficient.
213 static void 217 static void
214 scanblock(byte *b, uintptr n, byte *ptrmask) 218 scanblock(byte *b, uintptr n, byte *ptrmask)
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 runtime·throw("scanblock: scanned invalid object "); 497 runtime·throw("scanblock: scanned invalid object ");
494 } 498 }
495 } 499 }
496 } 500 }
497 } 501 }
498 502
499 static void 503 static void
500 markroot(ParFor *desc, uint32 i) 504 markroot(ParFor *desc, uint32 i)
501 { 505 {
502 FinBlock *fb; 506 FinBlock *fb;
503 » MHeap *h; 507 » MSpan *s;
504 » MSpan **allspans, *s;
505 uint32 spanidx, sg; 508 uint32 spanidx, sg;
506 G *gp; 509 G *gp;
507 void *p; 510 void *p;
508 511
509 USED(&desc); 512 USED(&desc);
510 // Note: if you add a case here, please also update heapdump.c:dumproots . 513 // Note: if you add a case here, please also update heapdump.c:dumproots .
511 switch(i) { 514 switch(i) {
512 case RootData: 515 case RootData:
513 scanblock(data, edata - data, runtime·gcdatamask); 516 scanblock(data, edata - data, runtime·gcdatamask);
514 break; 517 break;
515 518
516 case RootBss: 519 case RootBss:
517 scanblock(bss, ebss - bss, runtime·gcbssmask); 520 scanblock(bss, ebss - bss, runtime·gcbssmask);
518 break; 521 break;
519 522
520 case RootFinalizers: 523 case RootFinalizers:
521 for(fb=allfin; fb; fb=fb->alllink) 524 for(fb=allfin; fb; fb=fb->alllink)
522 scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), Sc anConservatively); 525 scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), Sc anConservatively);
523 break; 526 break;
524 527
525 case RootSpans: 528 case RootSpans:
526 // mark MSpan.specials 529 // mark MSpan.specials
527 » » h = &runtime·mheap; 530 » » sg = runtime·mheap.sweepgen;
528 » » sg = h->sweepgen; 531 » » for(spanidx=0; spanidx<work.nspan; spanidx++) {
529 » » allspans = h->allspans;
530 » » for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
531 Special *sp; 532 Special *sp;
532 SpecialFinalizer *spf; 533 SpecialFinalizer *spf;
533 534
534 » » » s = allspans[spanidx]; 535 » » » s = work.spans[spanidx];
535 if(s->state != MSpanInUse) 536 if(s->state != MSpanInUse)
536 continue; 537 continue;
537 if(s->sweepgen != sg) { 538 if(s->sweepgen != sg) {
538 runtime·printf("sweep %d %d\n", s->sweepgen, sg) ; 539 runtime·printf("sweep %d %d\n", s->sweepgen, sg) ;
539 runtime·throw("gc: unswept span"); 540 runtime·throw("gc: unswept span");
540 } 541 }
541 for(sp = s->specials; sp != nil; sp = sp->next) { 542 for(sp = s->specials; sp != nil; sp = sp->next) {
542 if(sp->kind != KindSpecialFinalizer) 543 if(sp->kind != KindSpecialFinalizer)
543 continue; 544 continue;
544 // don't mark finalized object, but scan it so w e 545 // don't mark finalized object, but scan it so w e
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 return res; 1078 return res;
1078 } 1079 }
1079 1080
1080 // State of background sweep. 1081 // State of background sweep.
1081 // Pretected by gclock. 1082 // Pretected by gclock.
1082 static struct 1083 static struct
1083 { 1084 {
1084 G* g; 1085 G* g;
1085 bool parked; 1086 bool parked;
1086 1087
1087 » MSpan**»spans; 1088 » uint32» spanidx;» // background sweeper position
1088 » uint32» nspan;
1089 » uint32» spanidx;
1090 1089
1091 uint32 nbgsweep; 1090 uint32 nbgsweep;
1092 uint32 npausesweep; 1091 uint32 npausesweep;
1093 } sweep; 1092 } sweep;
1094 1093
1095 // background sweeping goroutine 1094 // background sweeping goroutine
1096 static void 1095 static void
1097 bgsweep(void) 1096 bgsweep(void)
1098 { 1097 {
1099 g->issystem = 1; 1098 g->issystem = 1;
(...skipping 24 matching lines...) Expand all
1124 MSpan *s; 1123 MSpan *s;
1125 uint32 idx, sg; 1124 uint32 idx, sg;
1126 uintptr npages; 1125 uintptr npages;
1127 1126
1128 // increment locks to ensure that the goroutine is not preempted 1127 // increment locks to ensure that the goroutine is not preempted
1129 // in the middle of sweep thus leaving the span in an inconsistent state for next GC 1128 // in the middle of sweep thus leaving the span in an inconsistent state for next GC
1130 g->m->locks++; 1129 g->m->locks++;
1131 sg = runtime·mheap.sweepgen; 1130 sg = runtime·mheap.sweepgen;
1132 for(;;) { 1131 for(;;) {
1133 idx = runtime·xadd(&sweep.spanidx, 1) - 1; 1132 idx = runtime·xadd(&sweep.spanidx, 1) - 1;
1134 » » if(idx >= sweep.nspan) { 1133 » » if(idx >= work.nspan) {
1135 runtime·mheap.sweepdone = true; 1134 runtime·mheap.sweepdone = true;
1136 g->m->locks--; 1135 g->m->locks--;
1137 return -1; 1136 return -1;
1138 } 1137 }
1139 » » s = sweep.spans[idx]; 1138 » » s = work.spans[idx];
1140 if(s->state != MSpanInUse) { 1139 if(s->state != MSpanInUse) {
1141 s->sweepgen = sg; 1140 s->sweepgen = sg;
1142 continue; 1141 continue;
1143 } 1142 }
1144 if(s->sweepgen != sg-2 || !runtime·cas(&s->sweepgen, sg-2, sg-1) ) 1143 if(s->sweepgen != sg-2 || !runtime·cas(&s->sweepgen, sg-2, sg-1) )
1145 continue; 1144 continue;
1146 npages = s->npages; 1145 npages = s->npages;
1147 if(!runtime·MSpan_Sweep(s, false)) 1146 if(!runtime·MSpan_Sweep(s, false))
1148 npages = 0; 1147 npages = 0;
1149 g->m->locks--; 1148 g->m->locks--;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 // Flush MCache's to MCentral. 1251 // Flush MCache's to MCentral.
1253 if(g == g->m->g0) 1252 if(g == g->m->g0)
1254 flushallmcaches(); 1253 flushallmcaches();
1255 else 1254 else
1256 runtime·mcall(flushallmcaches_m); 1255 runtime·mcall(flushallmcaches_m);
1257 1256
1258 // Aggregate local stats. 1257 // Aggregate local stats.
1259 cachestats(); 1258 cachestats();
1260 1259
1261 // Scan all spans and count number of alive objects. 1260 // Scan all spans and count number of alive objects.
1261 runtime·lock(&runtime·mheap.lock);
1262 for(i = 0; i < runtime·mheap.nspan; i++) { 1262 for(i = 0; i < runtime·mheap.nspan; i++) {
1263 s = runtime·mheap.allspans[i]; 1263 s = runtime·mheap.allspans[i];
1264 if(s->state != MSpanInUse) 1264 if(s->state != MSpanInUse)
1265 continue; 1265 continue;
1266 if(s->sizeclass == 0) { 1266 if(s->sizeclass == 0) {
1267 mstats.nmalloc++; 1267 mstats.nmalloc++;
1268 mstats.alloc += s->elemsize; 1268 mstats.alloc += s->elemsize;
1269 } else { 1269 } else {
1270 mstats.nmalloc += s->ref; 1270 mstats.nmalloc += s->ref;
1271 mstats.by_size[s->sizeclass].nmalloc += s->ref; 1271 mstats.by_size[s->sizeclass].nmalloc += s->ref;
1272 mstats.alloc += s->ref*s->elemsize; 1272 mstats.alloc += s->ref*s->elemsize;
1273 } 1273 }
1274 } 1274 }
1275 runtime·unlock(&runtime·mheap.lock);
1275 1276
1276 // Aggregate by size class. 1277 // Aggregate by size class.
1277 smallfree = 0; 1278 smallfree = 0;
1278 mstats.nfree = runtime·mheap.nlargefree; 1279 mstats.nfree = runtime·mheap.nlargefree;
1279 for(i = 0; i < nelem(mstats.by_size); i++) { 1280 for(i = 0; i < nelem(mstats.by_size); i++) {
1280 mstats.nfree += runtime·mheap.nsmallfree[i]; 1281 mstats.nfree += runtime·mheap.nsmallfree[i];
1281 mstats.by_size[i].nfree = runtime·mheap.nsmallfree[i]; 1282 mstats.by_size[i].nfree = runtime·mheap.nsmallfree[i];
1282 mstats.by_size[i].nmalloc += runtime·mheap.nsmallfree[i]; 1283 mstats.by_size[i].nmalloc += runtime·mheap.nsmallfree[i];
1283 smallfree += runtime·mheap.nsmallfree[i] * runtime·class_to_size [i]; 1284 smallfree += runtime·mheap.nsmallfree[i] * runtime·class_to_size [i];
1284 } 1285 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 work.tstart = args->start_time;· 1435 work.tstart = args->start_time;·
1435 1436
1436 t1 = 0; 1437 t1 = 0;
1437 if(runtime·debug.gctrace) 1438 if(runtime·debug.gctrace)
1438 t1 = runtime·nanotime(); 1439 t1 = runtime·nanotime();
1439 1440
1440 // Sweep what is not sweeped by bgsweep. 1441 // Sweep what is not sweeped by bgsweep.
1441 while(runtime·sweepone() != -1) 1442 while(runtime·sweepone() != -1)
1442 sweep.npausesweep++; 1443 sweep.npausesweep++;
1443 1444
1445 // Cache runtime.mheap.allspans in work.spans to avoid conflicts with
1446 // resizing/freeing allspans.
1447 // New spans can be created while GC progresses, but they are not garbag e for
1448 // this round:
1449 // - new stack spans can be created even while the world is stopped.
1450 // - new malloc spans can be created during the concurrent sweep
1451
1452 // Even if this is stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
1453 runtime·lock(&runtime·mheap.lock);
1454 // Free the old cached sweep array if necessary.
1455 if(work.spans != nil && work.spans != runtime·mheap.allspans)
1456 runtime·SysFree(work.spans, work.nspan*sizeof(work.spans[0]), &m stats.other_sys);
1457 // Cache the current array for marking.
1458 runtime·mheap.gcspans = runtime·mheap.allspans;
1459 work.spans = runtime·mheap.allspans;
1460 work.nspan = runtime·mheap.nspan;
1461 runtime·unlock(&runtime·mheap.lock);
1462
1444 work.nwait = 0; 1463 work.nwait = 0;
1445 work.ndone = 0; 1464 work.ndone = 0;
1446 work.nproc = runtime·gcprocs(); 1465 work.nproc = runtime·gcprocs();
1447 runtime·parforsetup(work.markfor, work.nproc, RootCount + runtime·allgle n, nil, false, markroot); 1466 runtime·parforsetup(work.markfor, work.nproc, RootCount + runtime·allgle n, nil, false, markroot);
1448 if(work.nproc > 1) { 1467 if(work.nproc > 1) {
1449 runtime·noteclear(&work.alldone); 1468 runtime·noteclear(&work.alldone);
1450 runtime·helpgc(work.nproc); 1469 runtime·helpgc(work.nproc);
1451 } 1470 }
1452 1471
1453 t2 = 0; 1472 t2 = 0;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1493 stats.nprocyield += work.markfor->nprocyield; 1512 stats.nprocyield += work.markfor->nprocyield;
1494 stats.nosyield += work.markfor->nosyield; 1513 stats.nosyield += work.markfor->nosyield;
1495 stats.nsleep += work.markfor->nsleep; 1514 stats.nsleep += work.markfor->nsleep;
1496 1515
1497 runtime·printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D ) objects," 1516 runtime·printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D ) objects,"
1498 " %d/%d/%d sweeps," 1517 " %d/%d/%d sweeps,"
1499 " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\ n", 1518 " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\ n",
1500 mstats.numgc, work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t 3-t2)/1000, (t4-t3)/1000, 1519 mstats.numgc, work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t 3-t2)/1000, (t4-t3)/1000,
1501 heap0>>20, heap1>>20, obj, 1520 heap0>>20, heap1>>20, obj,
1502 mstats.nmalloc, mstats.nfree, 1521 mstats.nmalloc, mstats.nfree,
1503 » » » sweep.nspan, sweep.nbgsweep, sweep.npausesweep, 1522 » » » work.nspan, sweep.nbgsweep, sweep.npausesweep,
1504 stats.nhandoff, stats.nhandoffcnt, 1523 stats.nhandoff, stats.nhandoffcnt,
1505 work.markfor->nsteal, work.markfor->nstealcnt, 1524 work.markfor->nsteal, work.markfor->nstealcnt,
1506 stats.nprocyield, stats.nosyield, stats.nsleep); 1525 stats.nprocyield, stats.nosyield, stats.nsleep);
1507 sweep.nbgsweep = sweep.npausesweep = 0; 1526 sweep.nbgsweep = sweep.npausesweep = 0;
1508 } 1527 }
1509 1528
1510 » // We cache current runtime·mheap.allspans array in sweep.spans, 1529 » // See the comment in the beginning of this function as to why we need t he following.
1511 » // because the former can be resized and freed. 1530 » // Even if this is still stop-the-world, a concurrent exitsyscall can al locate a stack from heap.
1512 » // Otherwise we would need to take heap lock every time 1531 » runtime·lock(&runtime·mheap.lock);
1513 » // we want to convert span index to span pointer. 1532 » // Free the old cached mark array if necessary.
1514 1533 » if(work.spans != nil && work.spans != runtime·mheap.allspans)
1515 » // Free the old cached array if necessary. 1534 » » runtime·SysFree(work.spans, work.nspan*sizeof(work.spans[0]), &m stats.other_sys);
1516 » if(sweep.spans && sweep.spans != runtime·mheap.allspans) 1535 » // Cache the current array for sweeping.
1517 » » runtime·SysFree(sweep.spans, sweep.nspan*sizeof(sweep.spans[0]), &mstats.other_sys); 1536 » runtime·mheap.gcspans = runtime·mheap.allspans;
1518 » // Cache the current array.
1519 » runtime·mheap.sweepspans = runtime·mheap.allspans;
1520 runtime·mheap.sweepgen += 2; 1537 runtime·mheap.sweepgen += 2;
1521 runtime·mheap.sweepdone = false; 1538 runtime·mheap.sweepdone = false;
1522 » sweep.spans = runtime·mheap.allspans; 1539 » work.spans = runtime·mheap.allspans;
1523 » sweep.nspan = runtime·mheap.nspan; 1540 » work.nspan = runtime·mheap.nspan;
1524 sweep.spanidx = 0; 1541 sweep.spanidx = 0;
1542 runtime·unlock(&runtime·mheap.lock);
1525 1543
1526 // Temporary disable concurrent sweep, because we see failures on builde rs. 1544 // Temporary disable concurrent sweep, because we see failures on builde rs.
1527 if(ConcurrentSweep && !args->eagersweep) { 1545 if(ConcurrentSweep && !args->eagersweep) {
1528 runtime·lock(&gclock); 1546 runtime·lock(&gclock);
1529 if(sweep.g == nil) 1547 if(sweep.g == nil)
1530 sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime ·gc); 1548 sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime ·gc);
1531 else if(sweep.parked) { 1549 else if(sweep.parked) {
1532 sweep.parked = false; 1550 sweep.parked = false;
1533 runtime·ready(sweep.g); 1551 runtime·ready(sweep.g);
1534 } 1552 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 for(i=0; i<n; i++) 1614 for(i=0; i<n; i++)
1597 p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns) ]; 1615 p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns) ];
1598 1616
1599 p[n] = mstats.last_gc; 1617 p[n] = mstats.last_gc;
1600 p[n+1] = mstats.numgc; 1618 p[n+1] = mstats.numgc;
1601 p[n+2] = mstats.pause_total_ns;· 1619 p[n+2] = mstats.pause_total_ns;·
1602 runtime·unlock(&runtime·mheap.lock); 1620 runtime·unlock(&runtime·mheap.lock);
1603 pauses->len = n+3; 1621 pauses->len = n+3;
1604 } 1622 }
1605 1623
1606 int32 1624 void
1607 runtime·setgcpercent(int32 in) { 1625 runtime·setgcpercent_m(void) {
1626 » int32 in;
1608 int32 out; 1627 int32 out;
1628
1629 in = (int32)(intptr)g->m->scalararg[0];
1609 1630
1610 runtime·lock(&runtime·mheap.lock); 1631 runtime·lock(&runtime·mheap.lock);
1611 out = runtime·gcpercent; 1632 out = runtime·gcpercent;
1612 if(in < 0) 1633 if(in < 0)
1613 in = -1; 1634 in = -1;
1614 runtime·gcpercent = in; 1635 runtime·gcpercent = in;
1615 runtime·unlock(&runtime·mheap.lock); 1636 runtime·unlock(&runtime·mheap.lock);
1616 » return out; 1637
1638 » g->m->scalararg[0] = (uintptr)(intptr)out;
1617 } 1639 }
1618 1640
1619 static void 1641 static void
1620 gchelperstart(void) 1642 gchelperstart(void)
1621 { 1643 {
1622 if(g->m->helpgc < 0 || g->m->helpgc >= MaxGcproc) 1644 if(g->m->helpgc < 0 || g->m->helpgc >= MaxGcproc)
1623 runtime·throw("gchelperstart: bad m->helpgc"); 1645 runtime·throw("gchelperstart: bad m->helpgc");
1624 if(g != g->m->g0) 1646 if(g != g->m->g0)
1625 runtime·throw("gchelper not running on g0 stack"); 1647 runtime·throw("gchelper not running on g0 stack");
1626 } 1648 }
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
2111 2133
2112 void runtime·gc_unixnanotime(int64 *now); 2134 void runtime·gc_unixnanotime(int64 *now);
2113 2135
2114 int64 runtime·unixnanotime(void) 2136 int64 runtime·unixnanotime(void)
2115 { 2137 {
2116 int64 now; 2138 int64 now;
2117 2139
2118 runtime·gc_unixnanotime(&now); 2140 runtime·gc_unixnanotime(&now);
2119 return now; 2141 return now;
2120 } 2142 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b