github.com/alphadose/zenq/v2@v2.8.2/lib_runtime_linkage.go (about) 1 package zenq 2 3 import ( 4 "runtime" 5 "unsafe" 6 _ "unsafe" 7 8 "github.com/alphadose/zenq/v2/constants" 9 ) 10 11 type cacheLinePadding struct { 12 _ [constants.CacheLinePadSize]byte 13 } 14 15 // Linking ZenQ with golang internal runtime library to allow usage of scheduling primitives 16 // like goready(), mcall() etc to allow low-level scheduling of goroutines 17 18 type mutex struct { 19 // Futex-based impl treats it as uint32 key, 20 // while sema-based impl as M* waitm. 21 // Used to be a union, but unions break precise GC. 22 key uintptr 23 } 24 25 // The functions below are used for scheduling goroutines with exclusive control 26 // Shifting to the below flow will remove the spinning and mutex lock implementations 27 28 //go:linkname lock runtime.lock 29 func lock(l *mutex) 30 31 //go:linkname nanotime runtime.nanotime 32 func nanotime() int64 33 34 //go:linkname unlock runtime.unlock 35 func unlock(l *mutex) 36 37 //go:linkname goparkunlock runtime.goparkunlock 38 func goparkunlock(lock *mutex, reason waitReason, traceEv byte, traceskip int) 39 40 // GetG returns the pointer to the current goroutine 41 // defined in the asm files 42 func GetG() unsafe.Pointer 43 44 //go:linkname Fastrand runtime.fastrand 45 func Fastrand() uint32 46 47 //go:linkname Fastlog2 runtime.fastlog2 48 func Fastlog2(x float64) float64 49 50 //go:linkname goready runtime.goready 51 func goready(goroutinePtr unsafe.Pointer, traceskip int) 52 53 //go:linkname gopark runtime.gopark 54 func gopark(unlockf func(unsafe.Pointer, unsafe.Pointer) bool, lock unsafe.Pointer, reason waitReason, traceEv byte, traceskip int) 55 56 // Active spinning runtime support. 57 // runtime_canSpin reports whether spinning makes sense at the moment. 58 //go:linkname runtime_canSpin sync.runtime_canSpin 59 func runtime_canSpin(i int) bool 60 61 // runtime_doSpin does active spinning. 62 // //go:linkname runtime_doSpin sync.runtime_doSpin 63 // func runtime_doSpin() 64 65 func runtime_doSpin() { 66 spin(30) 67 } 68 69 //go:linkname osyield runtime.osyield 70 func osyield() 71 72 //go:linkname runtime_nanotime sync.runtime_nanotime 73 func runtime_nanotime() int64 74 75 // Semacquire waits until *s > 0 and then atomically decrements it. 76 // It is intended as a simple sleep primitive for use by the synchronization 77 // library and should not be used directly. 78 //go:linkname runtime_Semacquire sync.runtime_Semacquire 79 func runtime_Semacquire(s *uint32) 80 81 // SemacquireMutex is like Semacquire, but for profiling contended Mutexes. 82 // If lifo is true, queue waiter at the head of wait queue. 83 // skipframes is the number of frames to omit during tracing, counting from 84 // runtime_SemacquireMutex's caller. 85 //go:linkname runtime_SemacquireMutex sync.runtime_SemacquireMutex 86 func runtime_SemacquireMutex(s *uint32, lifo bool, skipframes int) 87 88 // Semrelease atomically increments *s and notifies a waiting goroutine 89 // if one is blocked in Semacquire. 90 // It is intended as a simple wakeup primitive for use by the synchronization 91 // library and should not be used directly. 92 // If handoff is true, pass count directly to the first waiter. 93 // skipframes is the number of frames to omit during tracing, counting from 94 // runtime_Semrelease's caller. 95 //go:linkname runtime_Semrelease sync.runtime_Semrelease 96 func runtime_Semrelease(s *uint32, handoff bool, skipframes int) 97 98 //go:linkname goyield runtime.goyield 99 func goyield() 100 101 //go:linkname mcall runtime.mcall 102 func mcall(fn func(unsafe.Pointer)) 103 104 //go:linkname park_m runtime.park_m 105 func park_m(gp unsafe.Pointer) 106 107 //go:linkname fastrandn runtime.fastrandn 108 func fastrandn(n uint32) uint32 109 110 //go:linkname throw runtime.throw 111 func throw(s string) 112 113 //go:linkname Readgstatus runtime.readgstatus 114 func Readgstatus(gp unsafe.Pointer) uint32 115 116 //go:linkname casgstatus runtime.casgstatus 117 func casgstatus(gp unsafe.Pointer, oldval, newval uint32) 118 119 //go:linkname dropg runtime.dropg 120 func dropg() 121 122 //go:linkname schedule runtime.schedule 123 func schedule() 124 125 //go:linkname mallocgc runtime.mallocgc 126 func mallocgc(size uintptr, typ unsafe.Pointer, needzero bool) unsafe.Pointer 127 128 //go:linkname sysFree runtime.sysFree 129 func sysFree(v unsafe.Pointer, n uintptr, sysStat unsafe.Pointer) 130 131 //go:linkname sysFreeOS runtime.sysFreeOS 132 func sysFreeOS(v unsafe.Pointer, n uintptr) 133 134 //go:linkname gosched_m runtime.gosched_m 135 func gosched_m(gp unsafe.Pointer) 136 137 //go:linkname spin runtime.procyield 138 func spin(cycles uint32) 139 140 //go:linkname noescape runtime.noescape 141 func noescape(p unsafe.Pointer) unsafe.Pointer 142 143 // ProcPin and ProcUnpin disable pre-emption for any calling goroutine 144 // can be used to guarantee consistent latency 145 //go:linkname ProcPin runtime.procPin 146 func ProcPin() int 147 148 //go:linkname ProcUnpin runtime.procUnpin 149 func ProcUnpin() 150 151 //go:linkname memequal runtime.memequal 152 func memequal(a, b unsafe.Pointer, size uintptr) bool 153 154 //go:linkname Load8 runtime/internal/atomic.Load8 155 func Load8(ptr *uint8) uint8 156 157 //go:linkname And8 runtime/internal/atomic.And8 158 func And8(ptr *uint8, val uint8) 159 160 //go:linkname Or8 runtime/internal/atomic.Or8 161 func Or8(ptr *uint8, val uint8) 162 163 //go:linkname Store8 runtime/internal/atomic.Store8 164 func Store8(ptr *uint8, val uint8) 165 166 // custom parking function 167 func fast_park(gp unsafe.Pointer) { 168 dropg() 169 casgstatus(gp, _Grunning, _Gwaiting) 170 schedule() 171 } 172 173 // whether the system has multiple cores or a single core 174 var multicore = runtime.NumCPU() > 1 175 176 // call ready after ensuring the goroutine is parked 177 func safe_ready(gp unsafe.Pointer) { 178 // for better microprocessor branch prediction 179 if multicore { 180 for Readgstatus(gp)&^_Gscan != _Gwaiting { 181 spin(20) 182 } 183 } else { 184 for Readgstatus(gp)&^_Gscan != _Gwaiting { 185 mcall(gosched_m) 186 } 187 } 188 goready(gp, 1) 189 } 190 191 // simple wait 192 func wait() { 193 if multicore { 194 spin(20) 195 } else { 196 mcall(gosched_m) 197 } 198 } 199 200 type waitReason uint8 201 202 const ( 203 waitReasonZero waitReason = iota // "" 204 waitReasonGCAssistMarking // "GC assist marking" 205 waitReasonIOWait // "IO wait" 206 waitReasonChanReceiveNilChan // "chan receive (nil chan)" 207 waitReasonChanSendNilChan // "chan send (nil chan)" 208 waitReasonDumpingHeap // "dumping heap" 209 waitReasonGarbageCollection // "garbage collection" 210 waitReasonGarbageCollectionScan // "garbage collection scan" 211 waitReasonPanicWait // "panicwait" 212 waitReasonSelect // "select" 213 waitReasonSelectNoCases // "select (no cases)" 214 waitReasonGCAssistWait // "GC assist wait" 215 waitReasonGCSweepWait // "GC sweep wait" 216 waitReasonGCScavengeWait // "GC scavenge wait" 217 waitReasonChanReceive // "chan receive" 218 waitReasonChanSend // "chan send" 219 waitReasonFinalizerWait // "finalizer wait" 220 waitReasonForceGCIdle // "force gc (idle)" 221 waitReasonSemacquire // "semacquire" 222 waitReasonSleep // "sleep" 223 waitReasonSyncCondWait // "sync.Cond.Wait" 224 waitReasonTimerGoroutineIdle // "timer goroutine (idle)" 225 waitReasonTraceReaderBlocked // "trace reader (blocked)" 226 waitReasonWaitForGCCycle // "wait for GC cycle" 227 waitReasonGCWorkerIdle // "GC worker (idle)" 228 waitReasonPreempted // "preempted" 229 waitReasonDebugCall // "debug call" 230 ) 231 232 // Event types in the trace, args are given in square brackets. 233 const ( 234 traceEvNone = 0 // unused 235 traceEvBatch = 1 // start of per-P batch of events [pid, timestamp] 236 traceEvFrequency = 2 // contains tracer timer frequency [frequency (ticks per second)] 237 traceEvStack = 3 // stack [stack id, number of PCs, array of {PC, func string ID, file string ID, line}] 238 traceEvGomaxprocs = 4 // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack id] 239 traceEvProcStart = 5 // start of P [timestamp, thread id] 240 traceEvProcStop = 6 // stop of P [timestamp] 241 traceEvGCStart = 7 // GC start [timestamp, seq, stack id] 242 traceEvGCDone = 8 // GC done [timestamp] 243 traceEvGCSTWStart = 9 // GC STW start [timestamp, kind] 244 traceEvGCSTWDone = 10 // GC STW done [timestamp] 245 traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id] 246 traceEvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed] 247 traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id] 248 traceEvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq] 249 traceEvGoEnd = 15 // goroutine ends [timestamp] 250 traceEvGoStop = 16 // goroutine stops (like in select{}) [timestamp, stack] 251 traceEvGoSched = 17 // goroutine calls Gosched [timestamp, stack] 252 traceEvGoPreempt = 18 // goroutine is preempted [timestamp, stack] 253 traceEvGoSleep = 19 // goroutine calls Sleep [timestamp, stack] 254 traceEvGoBlock = 20 // goroutine blocks [timestamp, stack] 255 traceEvGoUnblock = 21 // goroutine is unblocked [timestamp, goroutine id, seq, stack] 256 traceEvGoBlockSend = 22 // goroutine blocks on chan send [timestamp, stack] 257 traceEvGoBlockRecv = 23 // goroutine blocks on chan recv [timestamp, stack] 258 traceEvGoBlockSelect = 24 // goroutine blocks on select [timestamp, stack] 259 traceEvGoBlockSync = 25 // goroutine blocks on Mutex/RWMutex [timestamp, stack] 260 traceEvGoBlockCond = 26 // goroutine blocks on Cond [timestamp, stack] 261 traceEvGoBlockNet = 27 // goroutine blocks on network [timestamp, stack] 262 traceEvGoSysCall = 28 // syscall enter [timestamp, stack] 263 traceEvGoSysExit = 29 // syscall exit [timestamp, goroutine id, seq, real timestamp] 264 traceEvGoSysBlock = 30 // syscall blocks [timestamp] 265 traceEvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id] 266 traceEvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id] 267 traceEvHeapAlloc = 33 // gcController.heapLive change [timestamp, heap_alloc] 268 traceEvHeapGoal = 34 // gcController.heapGoal (formerly next_gc) change [timestamp, heap goal in bytes] 269 traceEvTimerGoroutine = 35 // not currently used; previously denoted timer goroutine [timer goroutine id] 270 traceEvFutileWakeup = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp] 271 traceEvString = 37 // string dictionary entry [ID, length, string] 272 traceEvGoStartLocal = 38 // goroutine starts running on the same P as the last event [timestamp, goroutine id] 273 traceEvGoUnblockLocal = 39 // goroutine is unblocked on the same P as the last event [timestamp, goroutine id, stack] 274 traceEvGoSysExitLocal = 40 // syscall exit on the same P as the last event [timestamp, goroutine id, real timestamp] 275 traceEvGoStartLabel = 41 // goroutine starts running with label [timestamp, goroutine id, seq, label string id] 276 traceEvGoBlockGC = 42 // goroutine blocks on GC assist [timestamp, stack] 277 traceEvGCMarkAssistStart = 43 // GC mark assist start [timestamp, stack] 278 traceEvGCMarkAssistDone = 44 // GC mark assist done [timestamp] 279 traceEvUserTaskCreate = 45 // trace.NewContext [timestamp, internal task id, internal parent task id, stack, name string] 280 traceEvUserTaskEnd = 46 // end of a task [timestamp, internal task id, stack] 281 traceEvUserRegion = 47 // trace.WithRegion [timestamp, internal task id, mode(0:start, 1:end), stack, name string] 282 traceEvUserLog = 48 // trace.Log [timestamp, internal task id, key string id, stack, value string] 283 traceEvCount = 49 284 // Byte is used but only 6 bits are available for event type. 285 // The remaining 2 bits are used to specify the number of arguments. 286 // That means, the max event type value is 63. 287 ) 288 289 // defined constants 290 const ( 291 // G status 292 // 293 // Beyond indicating the general state of a G, the G status 294 // acts like a lock on the goroutine's stack (and hence its 295 // ability to execute user code). 296 // 297 // If you add to this list, add to the list 298 // of "okay during garbage collection" status 299 // in mgcmark.go too. 300 // 301 // TODO(austin): The _Gscan bit could be much lighter-weight. 302 // For example, we could choose not to run _Gscanrunnable 303 // goroutines found in the run queue, rather than CAS-looping 304 // until they become _Grunnable. And transitions like 305 // _Gscanwaiting -> _Gscanrunnable are actually okay because 306 // they don't affect stack ownership. 307 308 // _Gidle means this goroutine was just allocated and has not 309 // yet been initialized. 310 _Gidle = iota // 0 311 312 // _Grunnable means this goroutine is on a run queue. It is 313 // not currently executing user code. The stack is not owned. 314 _Grunnable // 1 315 316 // _Grunning means this goroutine may execute user code. The 317 // stack is owned by this goroutine. It is not on a run queue. 318 // It is assigned an M and a P (g.m and g.m.p are valid). 319 _Grunning // 2 320 321 // _Gsyscall means this goroutine is executing a system call. 322 // It is not executing user code. The stack is owned by this 323 // goroutine. It is not on a run queue. It is assigned an M. 324 _Gsyscall // 3 325 326 // _Gwaiting means this goroutine is blocked in the runtime. 327 // It is not executing user code. It is not on a run queue, 328 // but should be recorded somewhere (e.g., a channel wait 329 // queue) so it can be ready()d when necessary. The stack is 330 // not owned *except* that a channel operation may read or 331 // write parts of the stack under the appropriate channel 332 // lock. Otherwise, it is not safe to access the stack after a 333 // goroutine enters _Gwaiting (e.g., it may get moved). 334 _Gwaiting // 4 335 336 // _Gmoribund_unused is currently unused, but hardcoded in gdb 337 // scripts. 338 _Gmoribund_unused // 5 339 340 // _Gdead means this goroutine is currently unused. It may be 341 // just exited, on a free list, or just being initialized. It 342 // is not executing user code. It may or may not have a stack 343 // allocated. The G and its stack (if any) are owned by the M 344 // that is exiting the G or that obtained the G from the free 345 // list. 346 _Gdead // 6 347 348 // _Genqueue_unused is currently unused. 349 _Genqueue_unused // 7 350 351 // _Gcopystack means this goroutine's stack is being moved. It 352 // is not executing user code and is not on a run queue. The 353 // stack is owned by the goroutine that put it in _Gcopystack. 354 _Gcopystack // 8 355 356 // _Gpreempted means this goroutine stopped itself for a 357 // suspendG preemption. It is like _Gwaiting, but nothing is 358 // yet responsible for ready()ing it. Some suspendG must CAS 359 // the status to _Gwaiting to take responsibility for 360 // ready()ing this G. 361 _Gpreempted // 9 362 363 // _Gscan combined with one of the above states other than 364 // _Grunning indicates that GC is scanning the stack. The 365 // goroutine is not executing user code and the stack is owned 366 // by the goroutine that set the _Gscan bit. 367 // 368 // _Gscanrunning is different: it is used to briefly block 369 // state transitions while GC signals the G to scan its own 370 // stack. This is otherwise like _Grunning. 371 // 372 // atomicstatus&~Gscan gives the state the goroutine will 373 // return to when the scan completes. 374 _Gscan = 0x1000 375 _Gscanrunnable = _Gscan + _Grunnable // 0x1001 376 _Gscanrunning = _Gscan + _Grunning // 0x1002 377 _Gscansyscall = _Gscan + _Gsyscall // 0x1003 378 _Gscanwaiting = _Gscan + _Gwaiting // 0x1004 379 _Gscanpreempted = _Gscan + _Gpreempted // 0x1009 380 )