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  )