github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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, traceEv byte, traceskip int) { 33 gopark(unlockf, lock, reason, traceEv, traceskip) 34 } 35 36 //go:linkname gopark runtime.gopark 37 func gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceEv byte, traceskip int) 38 39 //go:linkname wakep runtime.wakep 40 func wakep() 41 42 // Wakep is runtime.wakep. 43 // 44 //go:nosplit 45 func Wakep() { 46 // This is only supported if we can suppress the wakep called 47 // from Goready below, which is in certain architectures only. 48 if supportsWakeSuppression { 49 wakep() 50 } 51 } 52 53 //go:linkname goready runtime.goready 54 func goready(gp uintptr, traceskip int) 55 56 // Goready is runtime.goready. 57 // 58 // The additional wakep argument controls whether a new thread will be kicked to 59 // execute the P. This should be true in most circumstances. However, if the 60 // current thread is about to sleep, then this can be false for efficiency. 61 // 62 //go:nosplit 63 func Goready(gp uintptr, traceskip int, wakep bool) { 64 if supportsWakeSuppression && !wakep { 65 preGoReadyWakeSuppression() 66 } 67 goready(gp, traceskip) 68 if supportsWakeSuppression && !wakep { 69 postGoReadyWakeSuppression() 70 } 71 } 72 73 // Rand32 returns a non-cryptographically-secure random uint32. 74 func Rand32() uint32 { 75 return fastrand() 76 } 77 78 // Rand64 returns a non-cryptographically-secure random uint64. 79 func Rand64() uint64 { 80 return uint64(fastrand())<<32 | uint64(fastrand()) 81 } 82 83 //go:linkname fastrand runtime.fastrand 84 func fastrand() uint32 85 86 // RandUintptr returns a non-cryptographically-secure random uintptr. 87 func RandUintptr() uintptr { 88 if unsafe.Sizeof(uintptr(0)) == 4 { 89 return uintptr(Rand32()) 90 } 91 return uintptr(Rand64()) 92 } 93 94 // MapKeyHasher returns a hash function for pointers of m's key type. 95 // 96 // Preconditions: m must be a map. 97 func MapKeyHasher(m any) func(unsafe.Pointer, uintptr) uintptr { 98 if rtyp := reflect.TypeOf(m); rtyp.Kind() != reflect.Map { 99 panic(fmt.Sprintf("sync.MapKeyHasher: m is %v, not map", rtyp)) 100 } 101 mtyp := *(**maptype)(unsafe.Pointer(&m)) 102 return mtyp.Hasher 103 } 104 105 // maptype is equivalent to the beginning of internal/abi.MapType. 106 type maptype struct { 107 size uintptr 108 ptrdata uintptr 109 hash uint32 110 tflag uint8 111 align uint8 112 fieldAlign uint8 113 kind uint8 114 equal func(unsafe.Pointer, unsafe.Pointer) bool 115 gcdata *byte 116 str int32 117 ptrToThis int32 118 key unsafe.Pointer 119 elem unsafe.Pointer 120 bucket unsafe.Pointer 121 Hasher func(unsafe.Pointer, uintptr) uintptr 122 // more fields 123 } 124 125 // These functions are only used within the sync package. 126 127 //go:linkname semacquire sync.runtime_Semacquire 128 func semacquire(addr *uint32) 129 130 //go:linkname semrelease sync.runtime_Semrelease 131 func semrelease(addr *uint32, handoff bool, skipframes int) 132 133 //go:linkname canSpin sync.runtime_canSpin 134 func canSpin(i int) bool 135 136 //go:linkname doSpin sync.runtime_doSpin 137 func doSpin()