136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
// Copyright 2020 The gVisor Authors.
|
|
//
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build go1.13
|
|
// +build !go1.18
|
|
|
|
// Check go:linkname function signatures, type definitions, and constants when
|
|
// updating Go version.
|
|
|
|
package sync
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
// Note that go:linkname silently doesn't work if the local name is exported,
|
|
// necessitating an indirection for exported functions.
|
|
|
|
// Memmove is runtime.memmove, exported for SeqAtomicLoad/SeqAtomicTryLoad<T>.
|
|
//
|
|
//go:nosplit
|
|
func Memmove(to, from unsafe.Pointer, n uintptr) {
|
|
memmove(to, from, n)
|
|
}
|
|
|
|
//go:linkname memmove runtime.memmove
|
|
//go:noescape
|
|
func memmove(to, from unsafe.Pointer, n uintptr)
|
|
|
|
// Gopark is runtime.gopark. Gopark calls unlockf(pointer to runtime.g, lock);
|
|
// if unlockf returns true, Gopark blocks until Goready(pointer to runtime.g)
|
|
// is called. unlockf and its callees must be nosplit and norace, since stack
|
|
// splitting and race context are not available where it is called.
|
|
//
|
|
//go:nosplit
|
|
func Gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceEv byte, traceskip int) {
|
|
gopark(unlockf, lock, reason, traceEv, traceskip)
|
|
}
|
|
|
|
//go:linkname gopark runtime.gopark
|
|
func gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceEv byte, traceskip int)
|
|
|
|
// Goready is runtime.goready.
|
|
//
|
|
//go:nosplit
|
|
func Goready(gp uintptr, traceskip int) {
|
|
goready(gp, traceskip)
|
|
}
|
|
|
|
//go:linkname goready runtime.goready
|
|
func goready(gp uintptr, traceskip int)
|
|
|
|
// Values for the reason argument to gopark, from Go's src/runtime/runtime2.go.
|
|
const (
|
|
WaitReasonSelect uint8 = 9
|
|
WaitReasonChanReceive uint8 = 14
|
|
WaitReasonSemacquire uint8 = 18
|
|
)
|
|
|
|
// Values for the traceEv argument to gopark, from Go's src/runtime/trace.go.
|
|
const (
|
|
TraceEvGoBlockRecv byte = 23
|
|
TraceEvGoBlockSelect byte = 24
|
|
TraceEvGoBlockSync byte = 25
|
|
)
|
|
|
|
// Rand32 returns a non-cryptographically-secure random uint32.
|
|
func Rand32() uint32 {
|
|
return fastrand()
|
|
}
|
|
|
|
// Rand64 returns a non-cryptographically-secure random uint64.
|
|
func Rand64() uint64 {
|
|
return uint64(fastrand())<<32 | uint64(fastrand())
|
|
}
|
|
|
|
//go:linkname fastrand runtime.fastrand
|
|
func fastrand() uint32
|
|
|
|
// RandUintptr returns a non-cryptographically-secure random uintptr.
|
|
func RandUintptr() uintptr {
|
|
if unsafe.Sizeof(uintptr(0)) == 4 {
|
|
return uintptr(Rand32())
|
|
}
|
|
return uintptr(Rand64())
|
|
}
|
|
|
|
// MapKeyHasher returns a hash function for pointers of m's key type.
|
|
//
|
|
// Preconditions: m must be a map.
|
|
func MapKeyHasher(m interface{}) func(unsafe.Pointer, uintptr) uintptr {
|
|
if rtyp := reflect.TypeOf(m); rtyp.Kind() != reflect.Map {
|
|
panic(fmt.Sprintf("sync.MapKeyHasher: m is %v, not map", rtyp))
|
|
}
|
|
mtyp := *(**maptype)(unsafe.Pointer(&m))
|
|
return mtyp.hasher
|
|
}
|
|
|
|
// maptype is equivalent to the beginning of runtime.maptype.
|
|
type maptype struct {
|
|
size uintptr
|
|
ptrdata uintptr
|
|
hash uint32
|
|
tflag uint8
|
|
align uint8
|
|
fieldAlign uint8
|
|
kind uint8
|
|
equal func(unsafe.Pointer, unsafe.Pointer) bool
|
|
gcdata *byte
|
|
str int32
|
|
ptrToThis int32
|
|
key unsafe.Pointer
|
|
elem unsafe.Pointer
|
|
bucket unsafe.Pointer
|
|
hasher func(unsafe.Pointer, uintptr) uintptr
|
|
// more fields
|
|
}
|
|
|
|
// These functions are only used within the sync package.
|
|
|
|
//go:linkname semacquire sync.runtime_Semacquire
|
|
func semacquire(s *uint32)
|
|
|
|
//go:linkname semrelease sync.runtime_Semrelease
|
|
func semrelease(s *uint32, handoff bool, skipframes int)
|
|
|
|
//go:linkname canSpin sync.runtime_canSpin
|
|
func canSpin(i int) bool
|
|
|
|
//go:linkname doSpin sync.runtime_doSpin
|
|
func doSpin()
|