mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-19 12:04:03 +00:00
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:
@@ -7,6 +7,7 @@ package runtime
|
|||||||
// may be the only memory allocator possible.
|
// may be the only memory allocator possible.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"internal/task"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,6 +20,9 @@ var gcTotalAlloc uint64
|
|||||||
// Total number of calls to alloc()
|
// Total number of calls to alloc()
|
||||||
var gcMallocs uint64
|
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
|
// Total number of objected freed; for leaking collector this stays 0
|
||||||
const gcFrees = 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
|
// 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
|
// much. And by using platform-native data types (e.g. *uint8 for 8-bit
|
||||||
// systems).
|
// systems).
|
||||||
|
gcLock.Lock()
|
||||||
size = align(size)
|
size = align(size)
|
||||||
addr := heapptr
|
addr := heapptr
|
||||||
gcTotalAlloc += uint64(size)
|
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.
|
// Failed to make the heap bigger, so we must really be out of memory.
|
||||||
runtimePanic("out of memory")
|
runtimePanic("out of memory")
|
||||||
}
|
}
|
||||||
|
gcLock.Unlock()
|
||||||
|
|
||||||
pointer := unsafe.Pointer(addr)
|
pointer := unsafe.Pointer(addr)
|
||||||
zero_new_alloc(pointer, size)
|
zero_new_alloc(pointer, size)
|
||||||
return pointer
|
return pointer
|
||||||
@@ -69,6 +76,8 @@ func free(ptr unsafe.Pointer) {
|
|||||||
// The returned memory statistics are up to date as of the
|
// The returned memory statistics are up to date as of the
|
||||||
// call to ReadMemStats. This would not do GC implicitly for you.
|
// call to ReadMemStats. This would not do GC implicitly for you.
|
||||||
func ReadMemStats(m *MemStats) {
|
func ReadMemStats(m *MemStats) {
|
||||||
|
gcLock.Lock()
|
||||||
|
|
||||||
m.HeapIdle = 0
|
m.HeapIdle = 0
|
||||||
m.HeapInuse = gcTotalAlloc
|
m.HeapInuse = gcTotalAlloc
|
||||||
m.HeapReleased = 0 // always 0, we don't currently release memory back to the OS.
|
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
|
// no free -- current in use heap is the total allocated
|
||||||
m.HeapAlloc = gcTotalAlloc
|
m.HeapAlloc = gcTotalAlloc
|
||||||
m.Alloc = m.HeapAlloc
|
m.Alloc = m.HeapAlloc
|
||||||
|
|
||||||
|
gcLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GC() {
|
func GC() {
|
||||||
|
|||||||
Reference in New Issue
Block a user