Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare leaking GC for multithreading #4560

Merged
merged 2 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/internal/task/pmutex-cooperative.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package task

// PMutex is a real mutex on systems that can be either preemptive or threaded,
// and a dummy lock on other (purely cooperative) systems.
//
// It is mainly useful for short operations that need a lock when threading may
// be involved, but which do not need a lock with a purely cooperative
// scheduler.
type PMutex struct {
}

func (m *PMutex) Lock() {
}

func (m *PMutex) Unlock() {
}
11 changes: 11 additions & 0 deletions src/runtime/gc_leaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package runtime
// may be the only memory allocator possible.

import (
"internal/task"
"unsafe"
)

Expand All @@ -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

Expand All @@ -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)
Expand All @@ -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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlock mutex before throwing panic?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a runtime panic, which cannot be recovered from. So unlocking the mutex won't help anybody.

}
gcLock.Unlock()

pointer := unsafe.Pointer(addr)
zero_new_alloc(pointer, size)
return pointer
Expand All @@ -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.
Expand All @@ -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() {
Expand Down
Loading