Skip to content

Commit 418b1ad

Browse files
committed
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
1 parent ee788db commit 418b1ad

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

src/runtime/pinner.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ func (p *Pinner) Pin(pointer any) {
5959
}
6060
}
6161
ptr := pinnerGetPtr(&pointer)
62-
setPinned(ptr, true)
63-
p.refs = append(p.refs, ptr)
62+
if setPinned(ptr, true) {
63+
p.refs = append(p.refs, ptr)
64+
}
6465
}
6566

6667
// Unpin unpins all pinned objects of the Pinner.
@@ -144,14 +145,15 @@ func isPinned(ptr unsafe.Pointer) bool {
144145
}
145146

146147
// setPinned marks or unmarks a Go pointer as pinned.
147-
func setPinned(ptr unsafe.Pointer, pin bool) {
148+
func setPinned(ptr unsafe.Pointer, pin bool) bool {
148149
span := spanOfHeap(uintptr(ptr))
149150
if span == nil {
150-
if isGoPointerWithoutSpan(ptr) {
151-
// this is a linker-allocated or zero size object, nothing to do.
152-
return
151+
if !pin {
152+
panic(errorString("runtime.Pinner.Unpin: unexpected non Go pointer"))
153153
}
154-
panic(errorString("runtime.Pinner.Pin: argument is not a Go pointer"))
154+
// this is a linker-allocated, zero size object or other object,
155+
// nothing to do, silently ignore it.
156+
return false
155157
}
156158

157159
// ensure that the span is swept, b/c sweeping accesses the specials list
@@ -209,7 +211,7 @@ func setPinned(ptr unsafe.Pointer, pin bool) {
209211
}
210212
unlock(&span.speciallock)
211213
releasem(mp)
212-
return
214+
return true
213215
}
214216

215217
type pinState struct {

src/runtime/pinner_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,19 @@ func BenchmarkPinnerIsPinnedOnUnpinnedParallel(b *testing.B) {
522522
}
523523
})
524524
}
525+
526+
// const string data is not in span.
527+
func TestPinnerConstStringData(t *testing.T) {
528+
var pinner runtime.Pinner
529+
str := "test-const-string"
530+
p := unsafe.StringData(str)
531+
addr := unsafe.Pointer(p)
532+
if !runtime.IsPinned(addr) {
533+
t.Fatal("not marked as pinned")
534+
}
535+
pinner.Pin(p)
536+
pinner.Unpin()
537+
if !runtime.IsPinned(addr) {
538+
t.Fatal("not marked as pinned")
539+
}
540+
}

0 commit comments

Comments
 (0)