File: runtime_unsafe.go

package info (click to toggle)
golang-gvisor-gvisor 0.0~20221219.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 17,136 kB
  • sloc: asm: 2,860; cpp: 348; python: 89; sh: 40; makefile: 34; ansic: 21
file content (159 lines) | stat: -rw-r--r-- 4,419 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// 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.

//go:build go1.13 && !go1.21
// +build go1.13,!go1.21

// //go:linkname directives type-checked by checklinkname. Any other
// non-linkname assumptions outside the Go 1 compatibility guarantee should
// have an accompanied vet check or version guard build tag.

// Check type definitions and constants when updating Go version.
//
// TODO(b/165820485): add these checks to checklinkname.

package sync

import (
	"fmt"
	"reflect"
	"unsafe"
)

// Goyield is runtime.goyield, which is similar to runtime.Gosched but only
// yields the processor to other goroutines already on the processor's
// runqueue.
//
//go:nosplit
func Goyield() {
	goyield()
}

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

//go:linkname wakep runtime.wakep
func wakep()

// Wakep is runtime.wakep.
//
//go:nosplit
func Wakep() {
	// This is only supported if we can suppress the wakep called
	// from  Goready below, which is in certain architectures only.
	if supportsWakeSuppression {
		wakep()
	}
}

//go:linkname goready runtime.goready
func goready(gp uintptr, traceskip int)

// Goready is runtime.goready.
//
// The additional wakep argument controls whether a new thread will be kicked to
// execute the P. This should be true in most circumstances. However, if the
// current thread is about to sleep, then this can be false for efficiency.
//
//go:nosplit
func Goready(gp uintptr, traceskip int, wakep bool) {
	if supportsWakeSuppression && !wakep {
		preGoReadyWakeSuppression()
	}
	goready(gp, traceskip)
	if supportsWakeSuppression && !wakep {
		postGoReadyWakeSuppression()
	}
}

// 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 any) 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(addr *uint32)

//go:linkname semrelease sync.runtime_Semrelease
func semrelease(addr *uint32, handoff bool, skipframes int)

//go:linkname canSpin sync.runtime_canSpin
func canSpin(i int) bool

//go:linkname doSpin sync.runtime_doSpin
func doSpin()