LEFT | RIGHT |
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. | 5 // Garbage collector. |
6 | 6 |
7 #include "runtime.h" | 7 #include "runtime.h" |
8 #include "arch_GOARCH.h" | 8 #include "arch_GOARCH.h" |
9 #include "malloc.h" | 9 #include "malloc.h" |
10 #include "stack.h" | 10 #include "stack.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 LOOP = 2, | 34 LOOP = 2, |
35 PC_BITS = PRECISE | LOOP, | 35 PC_BITS = PRECISE | LOOP, |
36 | 36 |
37 // Pointer map | 37 // Pointer map |
38 BitsPerPointer = 2, | 38 BitsPerPointer = 2, |
39 BitsNoPointer = 0, | 39 BitsNoPointer = 0, |
40 BitsPointer = 1, | 40 BitsPointer = 1, |
41 BitsIface = 2, | 41 BitsIface = 2, |
42 BitsEface = 3, | 42 BitsEface = 3, |
43 }; | 43 }; |
| 44 |
| 45 static struct |
| 46 { |
| 47 Lock;·· |
| 48 void* head; |
| 49 } pools; |
| 50 |
| 51 void |
| 52 sync·runtime_registerPool(void **p) |
| 53 { |
| 54 runtime·lock(&pools); |
| 55 p[0] = pools.head; |
| 56 pools.head = p; |
| 57 runtime·unlock(&pools); |
| 58 } |
| 59 |
| 60 static void |
| 61 clearpools(void) |
| 62 { |
| 63 void **p, **next; |
| 64 |
| 65 for(p = pools.head; p != nil; p = next) { |
| 66 next = p[0]; |
| 67 p[0] = nil; // next |
| 68 p[1] = nil; // slice |
| 69 p[2] = nil; |
| 70 p[3] = nil; |
| 71 } |
| 72 pools.head = nil; |
| 73 } |
44 | 74 |
45 // Bits in per-word bitmap. | 75 // Bits in per-word bitmap. |
46 // #defines because enum might not be able to hold the values. | 76 // #defines because enum might not be able to hold the values. |
47 // | 77 // |
48 // Each word in the bitmap describes wordsPerBitmapWord words | 78 // Each word in the bitmap describes wordsPerBitmapWord words |
49 // of heap memory. There are 4 bitmap bits dedicated to each heap word, | 79 // of heap memory. There are 4 bitmap bits dedicated to each heap word, |
50 // so on a 64-bit system there is one bitmap word per 16 heap words. | 80 // so on a 64-bit system there is one bitmap word per 16 heap words. |
51 // The bits in the word are packed together by type first, then by | 81 // The bits in the word are packed together by type first, then by |
52 // heap location, so each 64-bit bitmap word consists of, from top to bottom, | 82 // heap location, so each 64-bit bitmap word consists of, from top to bottom, |
53 // the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarke
d bits, | 83 // the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarke
d bits, |
(...skipping 1454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1508 } else { | 1538 } else { |
1509 *sbuf->obj.pos++ = (Obj){frame->argp, frame->arglen, 0}; | 1539 *sbuf->obj.pos++ = (Obj){frame->argp, frame->arglen, 0}; |
1510 if(sbuf->obj.pos == sbuf->obj.end) | 1540 if(sbuf->obj.pos == sbuf->obj.end) |
1511 flushobjbuf(sbuf); | 1541 flushobjbuf(sbuf); |
1512 } | 1542 } |
1513 } | 1543 } |
1514 | 1544 |
1515 static void | 1545 static void |
1516 scanstack(G* gp, void *scanbuf) | 1546 scanstack(G* gp, void *scanbuf) |
1517 { | 1547 { |
1518 » uintptr pc; | 1548 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff
, scanframe, scanbuf, false); |
1519 » uintptr sp; | |
1520 » uintptr lr; | |
1521 | |
1522 » if(gp->syscallstack != (uintptr)nil) { | |
1523 » » // Scanning another goroutine that is about to enter or might | |
1524 » » // have just exited a system call. It may be executing code such | |
1525 » » // as schedlock and may have needed to start a new stack segment
. | |
1526 » » // Use the stack segment and stack pointer at the time of | |
1527 » » // the system call instead, since that won't change underfoot. | |
1528 » » sp = gp->syscallsp; | |
1529 » » pc = gp->syscallpc; | |
1530 » » lr = 0; | |
1531 » } else { | |
1532 » » // Scanning another goroutine's stack. | |
1533 » » // The goroutine is usually asleep (the world is stopped). | |
1534 » » sp = gp->sched.sp; | |
1535 » » pc = gp->sched.pc; | |
1536 » » lr = gp->sched.lr; | |
1537 » } | |
1538 » runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, scanframe, scan
buf, false); | |
1539 } | 1549 } |
1540 | 1550 |
1541 static void | 1551 static void |
1542 addstackroots(G *gp) | 1552 addstackroots(G *gp) |
1543 { | 1553 { |
1544 M *mp; | 1554 M *mp; |
1545 int32 n; | 1555 int32 n; |
1546 Stktop *stk; | 1556 Stktop *stk; |
1547 uintptr sp, guard; | 1557 uintptr sp, guard; |
1548 void *base; | 1558 void *base; |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2102 // typically threads which lost the race to grab | 2112 // typically threads which lost the race to grab |
2103 // worldsema exit here when gc is done. | 2113 // worldsema exit here when gc is done. |
2104 runtime·semrelease(&runtime·worldsema); | 2114 runtime·semrelease(&runtime·worldsema); |
2105 return; | 2115 return; |
2106 } | 2116 } |
2107 | 2117 |
2108 // Ok, we're doing it! Stop everybody else | 2118 // Ok, we're doing it! Stop everybody else |
2109 a.start_time = runtime·nanotime(); | 2119 a.start_time = runtime·nanotime(); |
2110 m->gcing = 1; | 2120 m->gcing = 1; |
2111 runtime·stoptheworld(); | 2121 runtime·stoptheworld(); |
2112 » | 2122 |
| 2123 » clearpools(); |
| 2124 |
2113 // Run gc on the g0 stack. We do this so that the g stack | 2125 // Run gc on the g0 stack. We do this so that the g stack |
2114 // we're currently running on will no longer change. Cuts | 2126 // we're currently running on will no longer change. Cuts |
2115 // the root set down a bit (g0 stacks are not scanned, and | 2127 // the root set down a bit (g0 stacks are not scanned, and |
2116 // we don't need to scan gc's internal state). Also an | 2128 // we don't need to scan gc's internal state). Also an |
2117 // enabler for copyable stacks. | 2129 // enabler for copyable stacks. |
2118 for(i = 0; i < (runtime·debug.gctrace > 1 ? 2 : 1); i++) { | 2130 for(i = 0; i < (runtime·debug.gctrace > 1 ? 2 : 1); i++) { |
2119 // switch to g0, call gc(&a), then switch back | 2131 // switch to g0, call gc(&a), then switch back |
2120 g->param = &a; | 2132 g->param = &a; |
2121 g->status = Gwaiting; | 2133 g->status = Gwaiting; |
2122 g->waitreason = "garbage collection"; | 2134 g->waitreason = "garbage collection"; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2326 // from there to go back farther in time. We deliver the times | 2338 // from there to go back farther in time. We deliver the times |
2327 // most recent first (in p[0]). | 2339 // most recent first (in p[0]). |
2328 for(i=0; i<n; i++) | 2340 for(i=0; i<n; i++) |
2329 p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns)
]; | 2341 p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns)
]; |
2330 | 2342 |
2331 p[n] = mstats.last_gc; | 2343 p[n] = mstats.last_gc; |
2332 p[n+1] = mstats.numgc; | 2344 p[n+1] = mstats.numgc; |
2333 p[n+2] = mstats.pause_total_ns;· | 2345 p[n+2] = mstats.pause_total_ns;· |
2334 runtime·unlock(&runtime·mheap); | 2346 runtime·unlock(&runtime·mheap); |
2335 pauses->len = n+3; | 2347 pauses->len = n+3; |
2336 } | |
2337 | |
2338 void | |
2339 sync·readNumGC(uint32 *numgc) | |
2340 { | |
2341 runtime·lock(&runtime·mheap); | |
2342 *numgc = mstats.numgc; | |
2343 runtime·unlock(&runtime·mheap); | |
2344 } | 2348 } |
2345 | 2349 |
2346 void | 2350 void |
2347 runtime∕debug·setGCPercent(intgo in, intgo out) | 2351 runtime∕debug·setGCPercent(intgo in, intgo out) |
2348 { | 2352 { |
2349 runtime·lock(&runtime·mheap); | 2353 runtime·lock(&runtime·mheap); |
2350 if(gcpercent == GcpercentUnknown) | 2354 if(gcpercent == GcpercentUnknown) |
2351 gcpercent = readgogc(); | 2355 gcpercent = readgogc(); |
2352 out = gcpercent; | 2356 out = gcpercent; |
2353 if(in < 0) | 2357 if(in < 0) |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2630 uintptr n; | 2634 uintptr n; |
2631 | 2635 |
2632 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; | 2636 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; |
2633 n = ROUND(n, bitmapChunk); | 2637 n = ROUND(n, bitmapChunk); |
2634 if(h->bitmap_mapped >= n) | 2638 if(h->bitmap_mapped >= n) |
2635 return; | 2639 return; |
2636 | 2640 |
2637 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped, &mstats.gc_sys)
; | 2641 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped, &mstats.gc_sys)
; |
2638 h->bitmap_mapped = n; | 2642 h->bitmap_mapped = n; |
2639 } | 2643 } |
LEFT | RIGHT |