Skip to content

Commit f9c0a16

Browse files
runtime: support Pinner.Pin for slice type
Fixes #65286 Change-Id: Ic8749b359bd56ecc43873bf3f3598e398e18847b
1 parent bc5e0a6 commit f9c0a16

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

src/runtime/pinner.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type Pinner struct {
2424
// contains pointers to Go objects, these objects must be pinned separately if they
2525
// are going to be accessed from C code.
2626
//
27-
// The argument must be a pointer of any type or an [unsafe.Pointer].
27+
// The argument must be a pointer of any type or an [unsafe.Pointer] or string or slice.
2828
// It's safe to call Pin on non-Go pointers, in which case Pin will do nothing.
2929
func (p *Pinner) Pin(pointer any) {
3030
if p.pinner == nil {
@@ -114,6 +114,8 @@ func pinnerGetPtr(i *any) unsafe.Pointer {
114114
data = e.data
115115
case kindString:
116116
data = unsafe.Pointer(unsafe.StringData(*(*string)(e.data)))
117+
case kindSlice:
118+
data = unsafe.Pointer(unsafe.SliceData(*(*[]byte)(e.data)))
117119
default:
118120
panic(errorString("runtime.Pinner: argument is not a pointer or string: " + toRType(etyp).string()))
119121
}

src/runtime/pinner_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,20 @@ func TestPinnerPinString(t *testing.T) {
559559
func getHeapStr() string {
560560
return string(byte(fastrand()))
561561
}
562+
563+
func TestPinnerPinSlice(t *testing.T) {
564+
var pinner runtime.Pinner
565+
s := make([]*int, 10)
566+
pinner.Pin(s)
567+
addr := unsafe.Pointer(unsafe.SliceData(s))
568+
if !runtime.IsPinned(addr) {
569+
t.Fatal("not marked as pinned")
570+
}
571+
if runtime.GetPinCounter(addr) != nil {
572+
t.Fatal("pin counter should not exist")
573+
}
574+
pinner.Unpin()
575+
if runtime.IsPinned(addr) {
576+
t.Fatal("still marked as pinned")
577+
}
578+
}

0 commit comments

Comments
 (0)