runtime: prepare the leaking GC for concurrent operations

This uses the task.PMutex parallel-only-mutex type to make the leaking
GC parallelism safe. The task.PMutex type is currently a no-op but will
become a real mutex once we add true parallelism.
This commit is contained in:
Ayke van Laethem
2024-11-18 09:24:08 +01:00
committed by Ayke
parent f75187392d
commit 8d04821639
+11
View File
@@ -7,6 +7,7 @@ package runtime
// may be the only memory allocator possible.
import (
"internal/task"
"unsafe"
)
@@ -19,6 +20,9 @@ var gcTotalAlloc uint64
// Total number of calls to alloc()
var gcMallocs uint64
// Heap lock for parallel goroutines. No-op when single threaded.
var gcLock task.PMutex
// Total number of objected freed; for leaking collector this stays 0
const gcFrees = 0
@@ -30,6 +34,7 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
// TODO: this can be optimized by not casting between pointers and ints so
// much. And by using platform-native data types (e.g. *uint8 for 8-bit
// systems).
gcLock.Lock()
size = align(size)
addr := heapptr
gcTotalAlloc += uint64(size)
@@ -43,6 +48,8 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
// Failed to make the heap bigger, so we must really be out of memory.
runtimePanic("out of memory")
}
gcLock.Unlock()
pointer := unsafe.Pointer(addr)
zero_new_alloc(pointer, size)
return pointer
@@ -69,6 +76,8 @@ func free(ptr unsafe.Pointer) {
// 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 = gcTotalAlloc
m.HeapReleased = 0 // always 0, we don't currently release memory back to the OS.
@@ -82,6 +91,8 @@ func ReadMemStats(m *MemStats) {
// no free -- current in use heap is the total allocated
m.HeapAlloc = gcTotalAlloc
m.Alloc = m.HeapAlloc
gcLock.Unlock()
}
func GC() {