Skip to content

Commit 870f002

Browse files
aykevldeadprogram
authored andcommitted
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 5b243f6 commit 870f002

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
@@ -58,6 +58,7 @@ var (
5858
gcMallocs uint64 // total number of allocations
5959
gcFrees uint64 // total number of objects freed
6060
gcFreedBlocks uint64 // total number of freed blocks
61+
gcLock task.PMutex // lock to avoid race conditions on multicore systems
6162
)
6263

6364
// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.
@@ -318,6 +319,10 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
318319
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
319320
}
320321

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

@@ -400,6 +405,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
400405
i.setState(blockStateTail)
401406
}
402407

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

446454
// GC performs a garbage collection cycle.
447455
func GC() {
456+
gcLock.Lock()
448457
runGC()
458+
gcLock.Unlock()
449459
}
450460

451461
// runGC performs a garbage collection cycle. It is the internal implementation
@@ -721,6 +731,7 @@ func dumpHeap() {
721731
// The returned memory statistics are up to date as of the
722732
// call to ReadMemStats. This would not do GC implicitly for you.
723733
func ReadMemStats(m *MemStats) {
734+
gcLock.Lock()
724735
m.HeapIdle = 0
725736
m.HeapInuse = 0
726737
for block := gcBlock(0); block < endBlock; block++ {
@@ -740,6 +751,7 @@ func ReadMemStats(m *MemStats) {
740751
m.Sys = uint64(heapEnd - heapStart)
741752
m.HeapAlloc = (gcTotalBlocks - gcFreedBlocks) * uint64(bytesPerBlock)
742753
m.Alloc = m.HeapAlloc
754+
gcLock.Unlock()
743755
}
744756

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

0 commit comments

Comments
 (0)