gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sync/runtime_unsafe.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 // //go:linkname directives type-checked by checklinkname. 7 // Runtime type copies checked by checkoffset. 8 9 package sync 10 11 import ( 12 "fmt" 13 "reflect" 14 "unsafe" 15 ) 16 17 // Goyield is runtime.goyield, which is similar to runtime.Gosched but only 18 // yields the processor to other goroutines already on the processor's 19 // runqueue. 20 // 21 //go:nosplit 22 func Goyield() { 23 goyield() 24 } 25 26 // Gopark is runtime.gopark. Gopark calls unlockf(pointer to runtime.g, lock); 27 // if unlockf returns true, Gopark blocks until Goready(pointer to runtime.g) 28 // is called. unlockf and its callees must be nosplit and norace, since stack 29 // splitting and race context are not available where it is called. 30 // 31 //go:nosplit 32 func Gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceReason TraceBlockReason, traceskip int) { 33 gopark(unlockf, lock, reason, traceReason, traceskip) 34 } 35 36 //go:linkname gopark runtime.gopark 37 func gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceReason TraceBlockReason, traceskip int) 38 39 // TraceBlockReason is equivalent to runtime.traceBlockReason. 40 type TraceBlockReason uint8 41 42 //go:linkname wakep runtime.wakep 43 func wakep() 44 45 // Wakep is runtime.wakep. 46 // 47 //go:nosplit 48 func Wakep() { 49 // This is only supported if we can suppress the wakep called 50 // from Goready below, which is in certain architectures only. 51 if supportsWakeSuppression { 52 wakep() 53 } 54 } 55 56 //go:linkname goready runtime.goready 57 func goready(gp uintptr, traceskip int) 58 59 // Goready is runtime.goready. 60 // 61 // The additional wakep argument controls whether a new thread will be kicked to 62 // execute the P. This should be true in most circumstances. However, if the 63 // current thread is about to sleep, then this can be false for efficiency. 64 // 65 //go:nosplit 66 func Goready(gp uintptr, traceskip int, wakep bool) { 67 if supportsWakeSuppression && !wakep { 68 preGoReadyWakeSuppression() 69 } 70 goready(gp, traceskip) 71 if supportsWakeSuppression && !wakep { 72 postGoReadyWakeSuppression() 73 } 74 } 75 76 // Rand32 returns a non-cryptographically-secure random uint32. 77 func Rand32() uint32 { 78 return fastrand() 79 } 80 81 // Rand64 returns a non-cryptographically-secure random uint64. 82 func Rand64() uint64 { 83 return uint64(fastrand())<<32 | uint64(fastrand()) 84 } 85 86 //go:linkname fastrand runtime.fastrand 87 func fastrand() uint32 88 89 // RandUintptr returns a non-cryptographically-secure random uintptr. 90 func RandUintptr() uintptr { 91 if unsafe.Sizeof(uintptr(0)) == 4 { 92 return uintptr(Rand32()) 93 } 94 return uintptr(Rand64()) 95 } 96 97 // MapKeyHasher returns a hash function for pointers of m's key type. 98 // 99 // Preconditions: m must be a map. 100 func MapKeyHasher(m any) func(unsafe.Pointer, uintptr) uintptr { 101 if rtyp := reflect.TypeOf(m); rtyp.Kind() != reflect.Map { 102 panic(fmt.Sprintf("sync.MapKeyHasher: m is %v, not map", rtyp)) 103 } 104 mtyp := *(**maptype)(unsafe.Pointer(&m)) 105 return mtyp.Hasher 106 } 107 108 // maptype is equivalent to the beginning of internal/abi.MapType. 109 type maptype struct { 110 size uintptr 111 ptrdata uintptr 112 hash uint32 113 tflag uint8 114 align uint8 115 fieldAlign uint8 116 kind uint8 117 equal func(unsafe.Pointer, unsafe.Pointer) bool 118 gcdata *byte 119 str int32 120 ptrToThis int32 121 key unsafe.Pointer 122 elem unsafe.Pointer 123 bucket unsafe.Pointer 124 Hasher func(unsafe.Pointer, uintptr) uintptr 125 // more fields 126 } 127 128 // These functions are only used within the sync package. 129 130 //go:linkname semacquire sync.runtime_Semacquire 131 func semacquire(addr *uint32) 132 133 //go:linkname semrelease sync.runtime_Semrelease 134 func semrelease(addr *uint32, handoff bool, skipframes int) 135 136 //go:linkname canSpin sync.runtime_canSpin 137 func canSpin(i int) bool 138 139 //go:linkname doSpin sync.runtime_doSpin 140 func doSpin()