1
0
mirror of https://github.com/golang/go synced 2024-11-05 17:46:16 -07:00

runtime: Pin silently allow pinning of non-Go pointers

People may don't know the detail of a pointer, this make the
runtime.Pinner.Pin API easier to use.

Fixes #62356
This commit is contained in:
doujiang24 2023-09-09 21:24:58 +08:00
parent ee788dbae0
commit 418b1ad7f2
2 changed files with 26 additions and 8 deletions

View File

@ -59,8 +59,9 @@ func (p *Pinner) Pin(pointer any) {
}
}
ptr := pinnerGetPtr(&pointer)
setPinned(ptr, true)
p.refs = append(p.refs, ptr)
if setPinned(ptr, true) {
p.refs = append(p.refs, ptr)
}
}
// Unpin unpins all pinned objects of the Pinner.
@ -144,14 +145,15 @@ func isPinned(ptr unsafe.Pointer) bool {
}
// setPinned marks or unmarks a Go pointer as pinned.
func setPinned(ptr unsafe.Pointer, pin bool) {
func setPinned(ptr unsafe.Pointer, pin bool) bool {
span := spanOfHeap(uintptr(ptr))
if span == nil {
if isGoPointerWithoutSpan(ptr) {
// this is a linker-allocated or zero size object, nothing to do.
return
if !pin {
panic(errorString("runtime.Pinner.Unpin: unexpected non Go pointer"))
}
panic(errorString("runtime.Pinner.Pin: argument is not a Go pointer"))
// this is a linker-allocated, zero size object or other object,
// nothing to do, silently ignore it.
return false
}
// ensure that the span is swept, b/c sweeping accesses the specials list
@ -209,7 +211,7 @@ func setPinned(ptr unsafe.Pointer, pin bool) {
}
unlock(&span.speciallock)
releasem(mp)
return
return true
}
type pinState struct {

View File

@ -522,3 +522,19 @@ func BenchmarkPinnerIsPinnedOnUnpinnedParallel(b *testing.B) {
}
})
}
// const string data is not in span.
func TestPinnerConstStringData(t *testing.T) {
var pinner runtime.Pinner
str := "test-const-string"
p := unsafe.StringData(str)
addr := unsafe.Pointer(p)
if !runtime.IsPinned(addr) {
t.Fatal("not marked as pinned")
}
pinner.Pin(p)
pinner.Unpin()
if !runtime.IsPinned(addr) {
t.Fatal("not marked as pinned")
}
}