runtime_unsafe.go raw

   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()
 141