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.
This commit is contained in:
Ayke van Laethem
2024-11-02 11:08:02 +01:00
parent 8659b18d6f
commit c9bb33a73c
+12
View File
@@ -57,6 +57,7 @@ var (
gcMallocs uint64 // total number of allocations
gcFrees uint64 // total number of objects freed
gcFreedBlocks uint64 // total number of freed blocks
gcLock task.PMutex // lock to avoid race conditions on multicore systems
)
// 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 {
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
}
// Make sure there are no concurrent allocations. The heap is not currently
// designed for concurrent alloc/GC.
gcLock.Lock()
gcTotalAlloc += uint64(size)
gcMallocs++
@@ -399,6 +404,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
i.setState(blockStateTail)
}
// We've claimed this allocation, now we can unlock the heap.
gcLock.Unlock()
// Return a pointer to this allocation.
pointer := thisAlloc.pointer()
if preciseHeap {
@@ -444,7 +452,9 @@ func free(ptr unsafe.Pointer) {
// GC performs a garbage collection cycle.
func GC() {
gcLock.Lock()
runGC()
gcLock.Unlock()
}
// runGC performs a garbage collection cycle. It is the internal implementation
@@ -713,6 +723,7 @@ func dumpHeap() {
// The returned memory statistics are up to date as of the
// call to ReadMemStats. This would not do GC implicitly for you.
func ReadMemStats(m *MemStats) {
gcLock.Lock()
m.HeapIdle = 0
m.HeapInuse = 0
for block := gcBlock(0); block < endBlock; block++ {
@@ -732,6 +743,7 @@ func ReadMemStats(m *MemStats) {
m.Sys = uint64(heapEnd - heapStart)
m.HeapAlloc = (gcTotalBlocks - gcFreedBlocks) * uint64(bytesPerBlock)
m.Alloc = m.HeapAlloc
gcLock.Unlock()
}
func SetFinalizer(obj interface{}, finalizer interface{}) {