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