Skip to content

Commit c9bb33a

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 8659b18 commit c9bb33a

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.
@@ -317,6 +318,10 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
317318
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
318319
}
319320

321+
// Make sure there are no concurrent allocations. The heap is not currently
322+
// designed for concurrent alloc/GC.
323+
gcLock.Lock()
324+
320325
gcTotalAlloc += uint64(size)
321326
gcMallocs++
322327

@@ -399,6 +404,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
399404
i.setState(blockStateTail)
400405
}
401406

407+
// We've claimed this allocation, now we can unlock the heap.
408+
gcLock.Unlock()
409+
402410
// Return a pointer to this allocation.
403411
pointer := thisAlloc.pointer()
404412
if preciseHeap {
@@ -444,7 +452,9 @@ func free(ptr unsafe.Pointer) {
444452

445453
// GC performs a garbage collection cycle.
446454
func GC() {
455+
gcLock.Lock()
447456
runGC()
457+
gcLock.Unlock()
448458
}
449459

450460
// runGC performs a garbage collection cycle. It is the internal implementation
@@ -713,6 +723,7 @@ func dumpHeap() {
713723
// The returned memory statistics are up to date as of the
714724
// call to ReadMemStats. This would not do GC implicitly for you.
715725
func ReadMemStats(m *MemStats) {
726+
gcLock.Lock()
716727
m.HeapIdle = 0
717728
m.HeapInuse = 0
718729
for block := gcBlock(0); block < endBlock; block++ {
@@ -732,6 +743,7 @@ func ReadMemStats(m *MemStats) {
732743
m.Sys = uint64(heapEnd - heapStart)
733744
m.HeapAlloc = (gcTotalBlocks - gcFreedBlocks) * uint64(bytesPerBlock)
734745
m.Alloc = m.HeapAlloc
746+
gcLock.Unlock()
735747
}
736748

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

0 commit comments

Comments
 (0)