github.com/primecitizens/pcz/std@v0.2.1/builtin/go/g.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2009 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package stdgo 9 10 import ( 11 "unsafe" 12 13 stdtype "github.com/primecitizens/pcz/std/builtin/type" 14 "github.com/primecitizens/pcz/std/core/abi" 15 "github.com/primecitizens/pcz/std/core/alloc" 16 "github.com/primecitizens/pcz/std/core/mark" 17 ) 18 19 // G defines required methods for a goroutine implementation. 20 type G interface { 21 ID() uint64 22 Rand32() uint32 23 Rand64() uint64 24 25 // Status returns the status of this goroutine. 26 Status() Status 27 28 // DefaultAlloc returns the default allocator in this goroutine. 29 DefaultAlloc() alloc.M 30 31 // PersistantAlloc returns the persistant allocator in this goroutine. 32 PersistantAlloc() alloc.P 33 34 // TODO: 35 // StackAllocator() alloc.S 36 // HeapAllocator() alloc.H 37 // ArenaAllocator() alloc.A 38 39 // // Park puts the current goroutine into a waiting state and calls unlockf 40 // // on the system stack. 41 // // 42 // // If unlockf returns false, the goroutine is resumed. 43 // // 44 // // unlockf must not access this G's stack, as it may be moved between 45 // // the call to gopark and the call to unlockf. 46 // // 47 // // Note that because unlockf is called after putting the G into a waiting 48 // // state, the G may have already been readied by the time unlockf is called 49 // // unless there is external synchronization preventing the G from being 50 // // readied. If unlockf returns false, it must guarantee that the G cannot be 51 // // externally readied. 52 // // 53 // // Reason explains why the goroutine has been parked. It is displayed in stack 54 // // traces and heap dumps. Reasons should be unique and descriptive. Do not 55 // // re-use reasons, add new ones. 56 // Park(unlockf func(g G, lock unsafe.Pointer) bool, lock unsafe.Pointer, reason WaitReason, traceReason trace.BlockReason) 57 } 58 59 // GHead contains required per-G data. 60 // 61 // See ${GOROOT}/src/runtime/runtime2.go#type:g 62 // 63 // NOTE: 64 // - unsafe.Offsetof(T.GHead.Stack) MUST be 0. 65 // - (dev) MUST be kept as non-generic struct type. 66 type GHead struct { 67 // Stack parameters. 68 // 69 // Stack describes the actual Stack memory: [Stack.lo, Stack.hi). 70 // stackguard0 is the Stack pointer compared in the Go Stack growth prologue. 71 // It is Stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption. 72 // stackguard1 is the Stack pointer compared in the C Stack growth prologue. 73 // It is Stack.lo+StackGuard on g0 and gsignal stacks. 74 // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash). 75 Stack Stack // offset known to runtime/cgo 76 Stackguard0 uintptr // offset known to liblink 77 Stackguard1 uintptr // offset known to liblink 78 79 Panic *Panic // innermost panic - offset known to liblink 80 Defer *Defer // innermost defer 81 M unsafe.Pointer // current m; offset known to arm liblink 82 Sched Gobuf 83 SyscallSP uintptr // if status==Gsyscall, syscallsp = Sched.sp to use during gc 84 SyscallPC uintptr // if status==Gsyscall, syscallpc = Sched.pc to use during gc 85 StacktopSP uintptr // expected sp at top of stack, to check in traceback 86 87 // NOTE(pcz): following fields are not known to compiler/link 88 89 ID_ uint64 90 91 // Itab for the G interface value. 92 Itab *abi.Itab 93 } 94 95 func (gp *GHead) Guintptr() Guintptr { return Guintptr(unsafe.Pointer(gp)) } 96 97 // G returns the G implementation 98 // 99 //go:nosplit 100 func (gp *GHead) G() G { 101 var g G 102 iface := stdtype.IfaceOf(mark.NoEscape(&g)) 103 iface.Itab, iface.Data = mark.NoEscape(gp.Itab), unsafe.Pointer(mark.NoEscape(gp)) 104 return g 105 } 106 107 func (gp *GHead) ID() uint64 { return gp.ID_ } 108 109 // Stack describes a Go execution Stack. 110 // The bounds of the Stack are exactly [lo, hi), 111 // with no implicit data structures on either side. 112 type Stack struct { 113 Lo uintptr 114 Hi uintptr 115 } 116 117 func (stk Stack) PointerOnStack(ptr uintptr) bool { 118 return stk.Lo <= ptr && ptr < stk.Hi 119 } 120 121 // A Guintptr holds a goroutine pointer, but typed as a uintptr 122 // to bypass write barriers. It is used in the Gobuf goroutine state 123 // and in scheduling lists that are manipulated without a P. 124 // 125 // The Gobuf.G goroutine pointer is almost always updated by assembly code. 126 // In one of the few places it is updated by Go code - func save - it must be 127 // treated as a uintptr to avoid a write barrier being emitted at a bad time. 128 // Instead of figuring out how to emit the write barriers missing in the 129 // assembly manipulation, we change the type of the field to uintptr, 130 // so that it does not require write barriers at all. 131 // 132 // Goroutine structs are published in the allg list and never freed. 133 // That will keep the goroutine structs from being collected. 134 // There is never a time that Gobuf.g's contain the only references 135 // to a goroutine: the publishing of the goroutine in allg comes first. 136 // Goroutine pointers are also kept in non-GC-visible places like TLS, 137 // so I can't see them ever moving. If we did want to start moving data 138 // in the GC, we'd need to allocate the goroutine structs from an 139 // alternate arena. Using Guintptr doesn't make that problem any worse. 140 // Note that pollDesc.rg, pollDesc.wg also store g in uintptr form, 141 // so they would need to be updated too if g's start moving. 142 type Guintptr uintptr 143 144 //go:nosplit 145 func (gp Guintptr) Ptr() *GHead { return (*GHead)(unsafe.Pointer(gp)) } 146 147 //go:nosplit 148 func (gp *Guintptr) Set(g *GHead) { *gp = Guintptr(unsafe.Pointer(g)) } 149 150 // See ${GOROOT}/src/runtime/runtime2.go#type:gobuf 151 type Gobuf struct { 152 // The offsets of SP, PC, and G are known to (hard-coded in) libmach. 153 // 154 // Ctxt is unusual with respect to GC: it may be a 155 // heap-allocated funcval, so GC needs to track it, but it 156 // needs to be set and cleared from assembly, where it's 157 // difficult to have write barriers. However, ctxt is really a 158 // saved, live register, and we only ever exchange it between 159 // the real register and the gobuf. Hence, we treat it as a 160 // root during stack scanning, which means assembly that saves 161 // and restores it doesn't need write barriers. It's still 162 // typed as a pointer so that any other writes from Go get 163 // write barriers. 164 SP uintptr 165 PC uintptr 166 G Guintptr 167 Ctxt unsafe.Pointer 168 Ret uintptr 169 LR uintptr 170 BP uintptr // for framepointer-enabled architectures 171 } 172 173 // Sudog represents a g in a wait list, such as for sending/receiving 174 // on a channel. 175 // 176 // Sudog is necessary because the g ↔ synchronization object relation 177 // is many-to-many. A g can be on many wait lists, so there may be 178 // many sudogs for one g; and many gs may be waiting on the same 179 // synchronization object, so there may be many sudogs for one object. 180 // 181 // sudogs are allocated from a special pool. Use acquireSudog and 182 // releaseSudog to allocate and free them. 183 // 184 // See ${GOROOT}/src/runtime/runtime2.go#type:sudog 185 type Sudog struct { 186 187 // The following fields are protected by the hchan.lock of the 188 // channel this sudog is blocking on. shrinkstack depends on 189 // this for sudogs involved in channel ops. 190 191 g *GHead 192 193 next *Sudog 194 prev *Sudog 195 196 // NOTE: linker checks `elem` field for dwarf 197 // DO NOT CHANGE THESE NAMES 198 elem unsafe.Pointer // data element (may point to stack) 199 200 // The following fields are never accessed concurrently. 201 // For channels, waitlink is only accessed by g. 202 // For semaphores, all fields (including the ones above) 203 // are only accessed when holding a semaRoot lock. 204 205 acquiretime int64 206 releasetime int64 207 ticket uint32 208 209 // isSelect indicates g is participating in a select, so 210 // g.selectDone must be CAS'd to win the wake-up race. 211 isSelect bool 212 213 // success indicates whether communication over channel c 214 // succeeded. It is true if the goroutine was awoken because a 215 // value was delivered over channel c, and false if awoken 216 // because c was closed. 217 success bool 218 219 parent *Sudog // semaRoot binary tree 220 waitlink *Sudog // g.waiting list or semaRoot 221 waittail *Sudog // semaRoot 222 c *hchan // channel 223 } 224 225 // G status 226 // 227 // Beyond indicating the general state of a G, the G status 228 // acts like a lock on the goroutine's stack (and hence its 229 // ability to execute user code). 230 // 231 // If you add to this list, add to the list 232 // of "okay during garbage collection" status 233 // in mgcmark.go too. 234 // 235 // TODO(austin): The StatusGscan bit could be much lighter-weight. 236 // For example, we could choose not to run StatusGscanrunnable 237 // goroutines found in the run queue, rather than CAS-looping 238 // until they become StatusGrunnable. And transitions like 239 // StatusGscanwaiting -> StatusGscanrunnable are actually okay because 240 // they don't affect stack ownership. 241 type Status = uint32 242 243 const ( 244 // StatusGidle means this goroutine was just allocated and has not 245 // yet been initialized. 246 StatusGidle Status = iota // 0 247 248 // StatusGrunnable means this goroutine is on a run queue. It is 249 // not currently executing user code. The stack is not owned. 250 StatusGrunnable // 1 251 252 // StatusGrunning means this goroutine may execute user code. The 253 // stack is owned by this goroutine. It is not on a run queue. 254 // It is assigned an M and a P (g.m and g.m.p are valid). 255 StatusGrunning // 2 256 257 // StatusGsyscall means this goroutine is executing a system call. 258 // It is not executing user code. The stack is owned by this 259 // goroutine. It is not on a run queue. It is assigned an M. 260 StatusGsyscall // 3 261 262 // StatusGwaiting means this goroutine is blocked in the runtime. 263 // It is not executing user code. It is not on a run queue, 264 // but should be recorded somewhere (e.g., a channel wait 265 // queue) so it can be ready()d when necessary. The stack is 266 // not owned *except* that a channel operation may read or 267 // write parts of the stack under the appropriate channel 268 // lock. Otherwise, it is not safe to access the stack after a 269 // goroutine enters StatusGwaiting (e.g., it may get moved). 270 StatusGwaiting // 4 271 272 // StatusGmoribund_unused is currently unused, but hardcoded in gdb 273 // scripts. 274 StatusGmoribund_unused // 5 275 276 // StatusGdead means this goroutine is currently unused. It may be 277 // just exited, on a free list, or just being initialized. It 278 // is not executing user code. It may or may not have a stack 279 // allocated. The G and its stack (if any) are owned by the M 280 // that is exiting the G or that obtained the G from the free 281 // list. 282 StatusGdead // 6 283 284 // StatusGenqueue_unused is currently unused. 285 StatusGenqueue_unused // 7 286 287 // StatusGcopystack means this goroutine's stack is being moved. It 288 // is not executing user code and is not on a run queue. The 289 // stack is owned by the goroutine that put it in StatusGcopystack. 290 StatusGcopystack // 8 291 292 // StatusGpreempted means this goroutine stopped itself for a 293 // suspendG preemption. It is like StatusGwaiting, but nothing is 294 // yet responsible for ready()ing it. Some suspendG must CAS 295 // the status to StatusGwaiting to take responsibility for 296 // ready()ing this G. 297 StatusGpreempted // 9 298 299 // StatusGscan combined with one of the above states other than 300 // StatusGrunning indicates that GC is scanning the stack. The 301 // goroutine is not executing user code and the stack is owned 302 // by the goroutine that set the StatusGscan bit. 303 // 304 // StatusGscanrunning is different: it is used to briefly block 305 // state transitions while GC signals the G to scan its own 306 // stack. This is otherwise like StatusGrunning. 307 // 308 // atomicstatus&~Gscan gives the state the goroutine will 309 // return to when the scan completes. 310 StatusGscan Status = 0x1000 311 StatusGscanrunnable Status = StatusGscan + StatusGrunnable // 0x1001 312 StatusGscanrunning Status = StatusGscan + StatusGrunning // 0x1002 313 StatusGscansyscall Status = StatusGscan + StatusGsyscall // 0x1003 314 StatusGscanwaiting Status = StatusGscan + StatusGwaiting // 0x1004 315 StatusGscanpreempted Status = StatusGscan + StatusGpreempted // 0x1009 316 ) 317 318 // A WaitReason explains why a goroutine has been stopped. 319 // See gopark. Do not re-use waitReasons, add new ones. 320 type WaitReason uint8 321 322 const ( 323 WaitReasonZero WaitReason = iota // "" 324 WaitReasonGCAssistMarking // "GC assist marking" 325 WaitReasonIOWait // "IO wait" 326 WaitReasonChanReceiveNilChan // "chan receive (nil chan)" 327 WaitReasonChanSendNilChan // "chan send (nil chan)" 328 WaitReasonDumpingHeap // "dumping heap" 329 WaitReasonGarbageCollection // "garbage collection" 330 WaitReasonGarbageCollectionScan // "garbage collection scan" 331 WaitReasonPanicWait // "panicwait" 332 WaitReasonSelect // "select" 333 WaitReasonSelectNoCases // "select (no cases)" 334 WaitReasonGCAssistWait // "GC assist wait" 335 WaitReasonGCSweepWait // "GC sweep wait" 336 WaitReasonGCScavengeWait // "GC scavenge wait" 337 WaitReasonChanReceive // "chan receive" 338 WaitReasonChanSend // "chan send" 339 WaitReasonFinalizerWait // "finalizer wait" 340 WaitReasonForceGCIdle // "force gc (idle)" 341 WaitReasonSemacquire // "semacquire" 342 WaitReasonSleep // "sleep" 343 WaitReasonSyncCondWait // "sync.Cond.Wait" 344 WaitReasonSyncMutexLock // "sync.Mutex.Lock" 345 WaitReasonSyncRWMutexRLock // "sync.RWMutex.RLock" 346 WaitReasonSyncRWMutexLock // "sync.RWMutex.Lock" 347 WaitReasonTraceReaderBlocked // "trace reader (blocked)" 348 WaitReasonWaitForGCCycle // "wait for GC cycle" 349 WaitReasonGCWorkerIdle // "GC worker (idle)" 350 WaitReasonGCWorkerActive // "GC worker (active)" 351 WaitReasonPreempted // "preempted" 352 WaitReasonDebugCall // "debug call" 353 WaitReasonGCMarkTermination // "GC mark termination" 354 WaitReasonStoppingTheWorld // "stopping the world" 355 ) 356 357 func (w WaitReason) IsMutexWait() bool { 358 return w == WaitReasonSyncMutexLock || 359 w == WaitReasonSyncRWMutexRLock || 360 w == WaitReasonSyncRWMutexLock 361 }