Skip to content

Commit 7601c6d

Browse files
committed
runtime: make conservative and precise GC MT-safe
Using a global lock may be slow, but it is certainly simple and safe. If this global lock becomes a bottleneck, we can of course look into making the GC truly support multithreading.
1 parent e13f0c4 commit 7601c6d

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

src/runtime/gc_blocks.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ var (
5757
gcMallocs uint64 // total number of allocations
5858
gcFrees uint64 // total number of objects freed
5959
gcFreedBlocks uint64 // total number of freed blocks
60+
gcLock task.PMutex // lock to avoid race conditions on multicore systems
6061
)
6162

6263
// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.
@@ -283,6 +284,10 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
283284
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
284285
}
285286

287+
// Make sure there are no concurrent allocations. The heap is not currently
288+
// designed for concurrent alloc/GC.
289+
gcLock.Lock()
290+
286291
gcTotalAlloc += uint64(size)
287292
gcMallocs++
288293

@@ -365,6 +370,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
365370
i.setState(blockStateTail)
366371
}
367372

373+
// We've claimed this allocation, now we can unlock the heap.
374+
gcLock.Unlock()
375+
368376
// Return a pointer to this allocation.
369377
pointer := thisAlloc.pointer()
370378
if preciseHeap {
@@ -410,7 +418,9 @@ func free(ptr unsafe.Pointer) {
410418

411419
// GC performs a garbage collection cycle.
412420
func GC() {
421+
gcLock.Lock()
413422
runGC()
423+
gcLock.Unlock()
414424
}
415425

416426
// runGC performs a garbage collection cycle. It is the internal implementation
@@ -679,6 +689,7 @@ func dumpHeap() {
679689
// The returned memory statistics are up to date as of the
680690
// call to ReadMemStats. This would not do GC implicitly for you.
681691
func ReadMemStats(m *MemStats) {
692+
gcLock.Lock()
682693
m.HeapIdle = 0
683694
m.HeapInuse = 0
684695
for block := gcBlock(0); block < endBlock; block++ {
@@ -698,6 +709,7 @@ func ReadMemStats(m *MemStats) {
698709
m.Sys = uint64(heapEnd - heapStart)
699710
m.HeapAlloc = (gcTotalBlocks - gcFreedBlocks) * uint64(bytesPerBlock)
700711
m.Alloc = m.HeapAlloc
712+
gcLock.Unlock()
701713
}
702714

703715
func SetFinalizer(obj interface{}, finalizer interface{}) {

0 commit comments

Comments
 (0)