Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 var (
     10 	m0 m
     11 	g0 g
     12 )
     13 
     14 // Goroutine scheduler
     15 // The scheduler's job is to distribute ready-to-run goroutines over worker threads.
     16 //
     17 // The main concepts are:
     18 // G - goroutine.
     19 // M - worker thread, or machine.
     20 // P - processor, a resource that is required to execute Go code.
     21 //     M must have an associated P to execute Go code, however it can be
     22 //     blocked or in a syscall w/o an associated P.
     23 //
     24 // Design doc at https://golang.org/s/go11sched.
     25 
     26 const (
     27 	// Number of goroutine ids to grab from sched.goidgen to local per-P cache at once.
     28 	// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
     29 	_GoidCacheBatch = 16
     30 )
     31 
     32 // The bootstrap sequence is:
     33 //
     34 //	call osinit
     35 //	call schedinit
     36 //	make & queue new G
     37 //	call runtimemstart
     38 //
     39 // The new G calls runtimemain.
     40 func schedinit() {
     41 	// raceinit must be the first call to race detector.
     42 	// In particular, it must be done before mallocinit below calls racemapshadow.
     43 	_g_ := getg()
     44 	if raceenabled {
     45 		_g_.racectx = raceinit()
     46 	}
     47 
     48 	sched.maxmcount = 10000
     49 
     50 	// Cache the framepointer experiment.  This affects stack unwinding.
     51 	framepointer_enabled = haveexperiment("framepointer")
     52 
     53 	tracebackinit()
     54 	moduledataverify()
     55 	stackinit()
     56 	mallocinit()
     57 	mcommoninit(_g_.m)
     58 
     59 	goargs()
     60 	goenvs()
     61 	parsedebugvars()
     62 	gcinit()
     63 
     64 	sched.lastpoll = uint64(nanotime())
     65 	procs := int(ncpu)
     66 	if n := atoi(gogetenv("GOMAXPROCS")); n > 0 {
     67 		if n > _MaxGomaxprocs {
     68 			n = _MaxGomaxprocs
     69 		}
     70 		procs = n
     71 	}
     72 	if procresize(int32(procs)) != nil {
     73 		throw("unknown runnable goroutine during bootstrap")
     74 	}
     75 
     76 	if buildVersion == "" {
     77 		// Condition should never trigger.  This code just serves
     78 		// to ensure runtimebuildVersion is kept in the resulting binary.
     79 		buildVersion = "unknown"
     80 	}
     81 }
     82 
     83 func dumpgstatus(gp *g) {
     84 	_g_ := getg()
     85 	print("runtime: gp: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
     86 	print("runtime:  g:  g=", _g_, ", goid=", _g_.goid, ",  g->atomicstatus=", readgstatus(_g_), "\n")
     87 }
     88 
     89 func checkmcount() {
     90 	// sched lock is held
     91 	if sched.mcount > sched.maxmcount {
     92 		print("runtime: program exceeds ", sched.maxmcount, "-thread limit\n")
     93 		throw("thread exhaustion")
     94 	}
     95 }
     96 
     97 func mcommoninit(mp *m) {
     98 	_g_ := getg()
     99 
    100 	// g0 stack won't make sense for user (and is not necessary unwindable).
    101 	if _g_ != _g_.m.g0 {
    102 		callers(1, mp.createstack[:])
    103 	}
    104 
    105 	mp.fastrand = 0x49f6428a + uint32(mp.id) + uint32(cputicks())
    106 	if mp.fastrand == 0 {
    107 		mp.fastrand = 0x49f6428a
    108 	}
    109 
    110 	lock(&sched.lock)
    111 	mp.id = sched.mcount
    112 	sched.mcount++
    113 	checkmcount()
    114 	mpreinit(mp)
    115 	if mp.gsignal != nil {
    116 		mp.gsignal.stackguard1 = mp.gsignal.stack.lo + _StackGuard
    117 	}
    118 
    119 	// Add to allm so garbage collector doesn't free g->m
    120 	// when it is just in a register or thread-local storage.
    121 	mp.alllink = allm
    122 
    123 	// NumCgoCall() iterates over allm w/o schedlock,
    124 	// so we need to publish it safely.
    125 	atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
    126 	unlock(&sched.lock)
    127 }
    128 
    129 // Mark gp ready to run.
    130 func ready(gp *g, traceskip int) {
    131 	if trace.enabled {
    132 		traceGoUnpark(gp, traceskip)
    133 	}
    134 
    135 	status := readgstatus(gp)
    136 
    137 	// Mark runnable.
    138 	_g_ := getg()
    139 	_g_.m.locks++ // disable preemption because it can be holding p in a local var
    140 	if status&^_Gscan != _Gwaiting {
    141 		dumpgstatus(gp)
    142 		throw("bad g->status in ready")
    143 	}
    144 
    145 	// status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
    146 	casgstatus(gp, _Gwaiting, _Grunnable)
    147 	runqput(_g_.m.p.ptr(), gp, true)
    148 	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 { // TODO: fast atomic
    149 		wakep()
    150 	}
    151 	_g_.m.locks--
    152 	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
    153 		_g_.stackguard0 = stackPreempt
    154 	}
    155 }
    156 
    157 func gcprocs() int32 {
    158 	// Figure out how many CPUs to use during GC.
    159 	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
    160 	lock(&sched.lock)
    161 	n := gomaxprocs
    162 	if n > ncpu {
    163 		n = ncpu
    164 	}
    165 	if n > _MaxGcproc {
    166 		n = _MaxGcproc
    167 	}
    168 	if n > sched.nmidle+1 { // one M is currently running
    169 		n = sched.nmidle + 1
    170 	}
    171 	unlock(&sched.lock)
    172 	return n
    173 }
    174 
    175 func needaddgcproc() bool {
    176 	lock(&sched.lock)
    177 	n := gomaxprocs
    178 	if n > ncpu {
    179 		n = ncpu
    180 	}
    181 	if n > _MaxGcproc {
    182 		n = _MaxGcproc
    183 	}
    184 	n -= sched.nmidle + 1 // one M is currently running
    185 	unlock(&sched.lock)
    186 	return n > 0
    187 }
    188 
    189 func helpgc(nproc int32) {
    190 	_g_ := getg()
    191 	lock(&sched.lock)
    192 	pos := 0
    193 	for n := int32(1); n < nproc; n++ { // one M is currently running
    194 		if allp[pos].mcache == _g_.m.mcache {
    195 			pos++
    196 		}
    197 		mp := mget()
    198 		if mp == nil {
    199 			throw("gcprocs inconsistency")
    200 		}
    201 		mp.helpgc = n
    202 		mp.p.set(allp[pos])
    203 		mp.mcache = allp[pos].mcache
    204 		pos++
    205 		notewakeup(&mp.park)
    206 	}
    207 	unlock(&sched.lock)
    208 }
    209 
    210 // freezeStopWait is a large value that freezetheworld sets
    211 // sched.stopwait to in order to request that all Gs permanently stop.
    212 const freezeStopWait = 0x7fffffff
    213 
    214 // Similar to stopTheWorld but best-effort and can be called several times.
    215 // There is no reverse operation, used during crashing.
    216 // This function must not lock any mutexes.
    217 func freezetheworld() {
    218 	// stopwait and preemption requests can be lost
    219 	// due to races with concurrently executing threads,
    220 	// so try several times
    221 	for i := 0; i < 5; i++ {
    222 		// this should tell the scheduler to not start any new goroutines
    223 		sched.stopwait = freezeStopWait
    224 		atomicstore(&sched.gcwaiting, 1)
    225 		// this should stop running goroutines
    226 		if !preemptall() {
    227 			break // no running goroutines
    228 		}
    229 		usleep(1000)
    230 	}
    231 	// to be sure
    232 	usleep(1000)
    233 	preemptall()
    234 	usleep(1000)
    235 }
    236 
    237 func isscanstatus(status uint32) bool {
    238 	if status == _Gscan {
    239 		throw("isscanstatus: Bad status Gscan")
    240 	}
    241 	return status&_Gscan == _Gscan
    242 }
    243 
    244 // All reads and writes of g's status go through readgstatus, casgstatus
    245 // castogscanstatus, casfrom_Gscanstatus.
    246 //go:nosplit
    247 func readgstatus(gp *g) uint32 {
    248 	return atomicload(&gp.atomicstatus)
    249 }
    250 
    251 // Ownership of gscanvalid:
    252 //
    253 // If gp is running (meaning status == _Grunning or _Grunning|_Gscan),
    254 // then gp owns gp.gscanvalid, and other goroutines must not modify it.
    255 //
    256 // Otherwise, a second goroutine can lock the scan state by setting _Gscan
    257 // in the status bit and then modify gscanvalid, and then unlock the scan state.
    258 //
    259 // Note that the first condition implies an exception to the second:
    260 // if a second goroutine changes gp's status to _Grunning|_Gscan,
    261 // that second goroutine still does not have the right to modify gscanvalid.
    262 
    263 // The Gscanstatuses are acting like locks and this releases them.
    264 // If it proves to be a performance hit we should be able to make these
    265 // simple atomic stores but for now we are going to throw if
    266 // we see an inconsistent state.
    267 func casfrom_Gscanstatus(gp *g, oldval, newval uint32) {
    268 	success := false
    269 
    270 	// Check that transition is valid.
    271 	switch oldval {
    272 	default:
    273 		print("runtime: casfrom_Gscanstatus bad oldval gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
    274 		dumpgstatus(gp)
    275 		throw("casfrom_Gscanstatus:top gp->status is not in scan state")
    276 	case _Gscanrunnable,
    277 		_Gscanwaiting,
    278 		_Gscanrunning,
    279 		_Gscansyscall:
    280 		if newval == oldval&^_Gscan {
    281 			success = cas(&gp.atomicstatus, oldval, newval)
    282 		}
    283 	case _Gscanenqueue:
    284 		if newval == _Gwaiting {
    285 			success = cas(&gp.atomicstatus, oldval, newval)
    286 		}
    287 	}
    288 	if !success {
    289 		print("runtime: casfrom_Gscanstatus failed gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
    290 		dumpgstatus(gp)
    291 		throw("casfrom_Gscanstatus: gp->status is not in scan state")
    292 	}
    293 	if newval == _Grunning {
    294 		gp.gcscanvalid = false
    295 	}
    296 }
    297 
    298 // This will return false if the gp is not in the expected status and the cas fails.
    299 // This acts like a lock acquire while the casfromgstatus acts like a lock release.
    300 func castogscanstatus(gp *g, oldval, newval uint32) bool {
    301 	switch oldval {
    302 	case _Grunnable,
    303 		_Gwaiting,
    304 		_Gsyscall:
    305 		if newval == oldval|_Gscan {
    306 			return cas(&gp.atomicstatus, oldval, newval)
    307 		}
    308 	case _Grunning:
    309 		if newval == _Gscanrunning || newval == _Gscanenqueue {
    310 			return cas(&gp.atomicstatus, oldval, newval)
    311 		}
    312 	}
    313 	print("runtime: castogscanstatus oldval=", hex(oldval), " newval=", hex(newval), "\n")
    314 	throw("castogscanstatus")
    315 	panic("not reached")
    316 }
    317 
    318 // If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
    319 // and casfrom_Gscanstatus instead.
    320 // casgstatus will loop if the g->atomicstatus is in a Gscan status until the routine that
    321 // put it in the Gscan state is finished.
    322 //go:nosplit
    323 func casgstatus(gp *g, oldval, newval uint32) {
    324 	if (oldval&_Gscan != 0) || (newval&_Gscan != 0) || oldval == newval {
    325 		systemstack(func() {
    326 			print("runtime: casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
    327 			throw("casgstatus: bad incoming values")
    328 		})
    329 	}
    330 
    331 	if oldval == _Grunning && gp.gcscanvalid {
    332 		// If oldvall == _Grunning, then the actual status must be
    333 		// _Grunning or _Grunning|_Gscan; either way,
    334 		// we own gp.gcscanvalid, so it's safe to read.
    335 		// gp.gcscanvalid must not be true when we are running.
    336 		print("runtime: casgstatus ", hex(oldval), "->", hex(newval), " gp.status=", hex(gp.atomicstatus), " gp.gcscanvalid=true\n")
    337 		throw("casgstatus")
    338 	}
    339 
    340 	// loop if gp->atomicstatus is in a scan state giving
    341 	// GC time to finish and change the state to oldval.
    342 	for !cas(&gp.atomicstatus, oldval, newval) {
    343 		if oldval == _Gwaiting && gp.atomicstatus == _Grunnable {
    344 			systemstack(func() {
    345 				throw("casgstatus: waiting for Gwaiting but is Grunnable")
    346 			})
    347 		}
    348 		// Help GC if needed.
    349 		// if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) {
    350 		// 	gp.preemptscan = false
    351 		// 	systemstack(func() {
    352 		// 		gcphasework(gp)
    353 		// 	})
    354 		// }
    355 	}
    356 	if newval == _Grunning {
    357 		gp.gcscanvalid = false
    358 	}
    359 }
    360 
    361 // casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable.
    362 // Returns old status. Cannot call casgstatus directly, because we are racing with an
    363 // async wakeup that might come in from netpoll. If we see Gwaiting from the readgstatus,
    364 // it might have become Grunnable by the time we get to the cas. If we called casgstatus,
    365 // it would loop waiting for the status to go back to Gwaiting, which it never will.
    366 //go:nosplit
    367 func casgcopystack(gp *g) uint32 {
    368 	for {
    369 		oldstatus := readgstatus(gp) &^ _Gscan
    370 		if oldstatus != _Gwaiting && oldstatus != _Grunnable {
    371 			throw("copystack: bad status, not Gwaiting or Grunnable")
    372 		}
    373 		if cas(&gp.atomicstatus, oldstatus, _Gcopystack) {
    374 			return oldstatus
    375 		}
    376 	}
    377 }
    378 
    379 // scang blocks until gp's stack has been scanned.
    380 // It might be scanned by scang or it might be scanned by the goroutine itself.
    381 // Either way, the stack scan has completed when scang returns.
    382 func scang(gp *g) {
    383 	// Invariant; we (the caller, markroot for a specific goroutine) own gp.gcscandone.
    384 	// Nothing is racing with us now, but gcscandone might be set to true left over
    385 	// from an earlier round of stack scanning (we scan twice per GC).
    386 	// We use gcscandone to record whether the scan has been done during this round.
    387 	// It is important that the scan happens exactly once: if called twice,
    388 	// the installation of stack barriers will detect the double scan and die.
    389 
    390 	gp.gcscandone = false
    391 
    392 	// Endeavor to get gcscandone set to true,
    393 	// either by doing the stack scan ourselves or by coercing gp to scan itself.
    394 	// gp.gcscandone can transition from false to true when we're not looking
    395 	// (if we asked for preemption), so any time we lock the status using
    396 	// castogscanstatus we have to double-check that the scan is still not done.
    397 	for !gp.gcscandone {
    398 		switch s := readgstatus(gp); s {
    399 		default:
    400 			dumpgstatus(gp)
    401 			throw("stopg: invalid status")
    402 
    403 		case _Gdead:
    404 			// No stack.
    405 			gp.gcscandone = true
    406 
    407 		case _Gcopystack:
    408 			// Stack being switched. Go around again.
    409 
    410 		case _Grunnable, _Gsyscall, _Gwaiting:
    411 			// Claim goroutine by setting scan bit.
    412 			// Racing with execution or readying of gp.
    413 			// The scan bit keeps them from running
    414 			// the goroutine until we're done.
    415 			if castogscanstatus(gp, s, s|_Gscan) {
    416 				if !gp.gcscandone {
    417 					// Coordinate with traceback
    418 					// in sigprof.
    419 					for !cas(&gp.stackLock, 0, 1) {
    420 						osyield()
    421 					}
    422 					scanstack(gp)
    423 					atomicstore(&gp.stackLock, 0)
    424 					gp.gcscandone = true
    425 				}
    426 				restartg(gp)
    427 			}
    428 
    429 		case _Gscanwaiting:
    430 			// newstack is doing a scan for us right now. Wait.
    431 
    432 		case _Grunning:
    433 			// Goroutine running. Try to preempt execution so it can scan itself.
    434 			// The preemption handler (in newstack) does the actual scan.
    435 
    436 			// Optimization: if there is already a pending preemption request
    437 			// (from the previous loop iteration), don't bother with the atomics.
    438 			if gp.preemptscan && gp.preempt && gp.stackguard0 == stackPreempt {
    439 				break
    440 			}
    441 
    442 			// Ask for preemption and self scan.
    443 			if castogscanstatus(gp, _Grunning, _Gscanrunning) {
    444 				if !gp.gcscandone {
    445 					gp.preemptscan = true
    446 					gp.preempt = true
    447 					gp.stackguard0 = stackPreempt
    448 				}
    449 				casfrom_Gscanstatus(gp, _Gscanrunning, _Grunning)
    450 			}
    451 		}
    452 	}
    453 
    454 	gp.preemptscan = false // cancel scan request if no longer needed
    455 }
    456 
    457 // The GC requests that this routine be moved from a scanmumble state to a mumble state.
    458 func restartg(gp *g) {
    459 	s := readgstatus(gp)
    460 	switch s {
    461 	default:
    462 		dumpgstatus(gp)
    463 		throw("restartg: unexpected status")
    464 
    465 	case _Gdead:
    466 		// ok
    467 
    468 	case _Gscanrunnable,
    469 		_Gscanwaiting,
    470 		_Gscansyscall:
    471 		casfrom_Gscanstatus(gp, s, s&^_Gscan)
    472 
    473 	// Scan is now completed.
    474 	// Goroutine now needs to be made runnable.
    475 	// We put it on the global run queue; ready blocks on the global scheduler lock.
    476 	case _Gscanenqueue:
    477 		casfrom_Gscanstatus(gp, _Gscanenqueue, _Gwaiting)
    478 		if gp != getg().m.curg {
    479 			throw("processing Gscanenqueue on wrong m")
    480 		}
    481 		dropg()
    482 		ready(gp, 0)
    483 	}
    484 }
    485 
    486 // stopTheWorld stops all P's from executing goroutines, interrupting
    487 // all goroutines at GC safe points and records reason as the reason
    488 // for the stop. On return, only the current goroutine's P is running.
    489 // stopTheWorld must not be called from a system stack and the caller
    490 // must not hold worldsema. The caller must call startTheWorld when
    491 // other P's should resume execution.
    492 //
    493 // stopTheWorld is safe for multiple goroutines to call at the
    494 // same time. Each will execute its own stop, and the stops will
    495 // be serialized.
    496 //
    497 // This is also used by routines that do stack dumps. If the system is
    498 // in panic or being exited, this may not reliably stop all
    499 // goroutines.
    500 func stopTheWorld(reason string) {
    501 	semacquire(&worldsema, false)
    502 	getg().m.preemptoff = reason
    503 	systemstack(stopTheWorldWithSema)
    504 }
    505 
    506 // startTheWorld undoes the effects of stopTheWorld.
    507 func startTheWorld() {
    508 	systemstack(startTheWorldWithSema)
    509 	// worldsema must be held over startTheWorldWithSema to ensure
    510 	// gomaxprocs cannot change while worldsema is held.
    511 	semrelease(&worldsema)
    512 	getg().m.preemptoff = ""
    513 }
    514 
    515 // Holding worldsema grants an M the right to try to stop the world
    516 // and prevents gomaxprocs from changing concurrently.
    517 var worldsema uint32 = 1
    518 
    519 // stopTheWorldWithSema is the core implementation of stopTheWorld.
    520 // The caller is responsible for acquiring worldsema and disabling
    521 // preemption first and then should stopTheWorldWithSema on the system
    522 // stack:
    523 //
    524 //	semacquire(&worldsema, false)
    525 //	m.preemptoff = "reason"
    526 //	systemstack(stopTheWorldWithSema)
    527 //
    528 // When finished, the caller must either call startTheWorld or undo
    529 // these three operations separately:
    530 //
    531 //	m.preemptoff = ""
    532 //	systemstack(startTheWorldWithSema)
    533 //	semrelease(&worldsema)
    534 //
    535 // It is allowed to acquire worldsema once and then execute multiple
    536 // startTheWorldWithSema/stopTheWorldWithSema pairs.
    537 // Other P's are able to execute between successive calls to
    538 // startTheWorldWithSema and stopTheWorldWithSema.
    539 // Holding worldsema causes any other goroutines invoking
    540 // stopTheWorld to block.
    541 func stopTheWorldWithSema() {
    542 	_g_ := getg()
    543 
    544 	// If we hold a lock, then we won't be able to stop another M
    545 	// that is blocked trying to acquire the lock.
    546 	if _g_.m.locks > 0 {
    547 		throw("stopTheWorld: holding locks")
    548 	}
    549 
    550 	lock(&sched.lock)
    551 	sched.stopwait = gomaxprocs
    552 	atomicstore(&sched.gcwaiting, 1)
    553 	preemptall()
    554 	// stop current P
    555 	_g_.m.p.ptr().status = _Pgcstop // Pgcstop is only diagnostic.
    556 	sched.stopwait--
    557 	// try to retake all P's in Psyscall status
    558 	for i := 0; i < int(gomaxprocs); i++ {
    559 		p := allp[i]
    560 		s := p.status
    561 		if s == _Psyscall && cas(&p.status, s, _Pgcstop) {
    562 			if trace.enabled {
    563 				traceGoSysBlock(p)
    564 				traceProcStop(p)
    565 			}
    566 			p.syscalltick++
    567 			sched.stopwait--
    568 		}
    569 	}
    570 	// stop idle P's
    571 	for {
    572 		p := pidleget()
    573 		if p == nil {
    574 			break
    575 		}
    576 		p.status = _Pgcstop
    577 		sched.stopwait--
    578 	}
    579 	wait := sched.stopwait > 0
    580 	unlock(&sched.lock)
    581 
    582 	// wait for remaining P's to stop voluntarily
    583 	if wait {
    584 		for {
    585 			// wait for 100us, then try to re-preempt in case of any races
    586 			if notetsleep(&sched.stopnote, 100*1000) {
    587 				noteclear(&sched.stopnote)
    588 				break
    589 			}
    590 			preemptall()
    591 		}
    592 	}
    593 	if sched.stopwait != 0 {
    594 		throw("stopTheWorld: not stopped")
    595 	}
    596 	for i := 0; i < int(gomaxprocs); i++ {
    597 		p := allp[i]
    598 		if p.status != _Pgcstop {
    599 			throw("stopTheWorld: not stopped")
    600 		}
    601 	}
    602 }
    603 
    604 func mhelpgc() {
    605 	_g_ := getg()
    606 	_g_.m.helpgc = -1
    607 }
    608 
    609 func startTheWorldWithSema() {
    610 	_g_ := getg()
    611 
    612 	_g_.m.locks++        // disable preemption because it can be holding p in a local var
    613 	gp := netpoll(false) // non-blocking
    614 	injectglist(gp)
    615 	add := needaddgcproc()
    616 	lock(&sched.lock)
    617 
    618 	procs := gomaxprocs
    619 	if newprocs != 0 {
    620 		procs = newprocs
    621 		newprocs = 0
    622 	}
    623 	p1 := procresize(procs)
    624 	sched.gcwaiting = 0
    625 	if sched.sysmonwait != 0 {
    626 		sched.sysmonwait = 0
    627 		notewakeup(&sched.sysmonnote)
    628 	}
    629 	unlock(&sched.lock)
    630 
    631 	for p1 != nil {
    632 		p := p1
    633 		p1 = p1.link.ptr()
    634 		if p.m != 0 {
    635 			mp := p.m.ptr()
    636 			p.m = 0
    637 			if mp.nextp != 0 {
    638 				throw("startTheWorld: inconsistent mp->nextp")
    639 			}
    640 			mp.nextp.set(p)
    641 			notewakeup(&mp.park)
    642 		} else {
    643 			// Start M to run P.  Do not start another M below.
    644 			newm(nil, p)
    645 			add = false
    646 		}
    647 	}
    648 
    649 	// Wakeup an additional proc in case we have excessive runnable goroutines
    650 	// in local queues or in the global queue. If we don't, the proc will park itself.
    651 	// If we have lots of excessive work, resetspinning will unpark additional procs as necessary.
    652 	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 {
    653 		wakep()
    654 	}
    655 
    656 	if add {
    657 		// If GC could have used another helper proc, start one now,
    658 		// in the hope that it will be available next time.
    659 		// It would have been even better to start it before the collection,
    660 		// but doing so requires allocating memory, so it's tricky to
    661 		// coordinate.  This lazy approach works out in practice:
    662 		// we don't mind if the first couple gc rounds don't have quite
    663 		// the maximum number of procs.
    664 		newm(mhelpgc, nil)
    665 	}
    666 	_g_.m.locks--
    667 	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
    668 		_g_.stackguard0 = stackPreempt
    669 	}
    670 }
    671 
    672 // Called to start an M.
    673 //go:nosplit
    674 func mstart() {
    675 	_g_ := getg()
    676 
    677 	if _g_.stack.lo == 0 {
    678 		// Initialize stack bounds from system stack.
    679 		// Cgo may have left stack size in stack.hi.
    680 		size := _g_.stack.hi
    681 		if size == 0 {
    682 			size = 8192 * stackGuardMultiplier
    683 		}
    684 		_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size)))
    685 		_g_.stack.lo = _g_.stack.hi - size + 1024
    686 	}
    687 	// Initialize stack guards so that we can start calling
    688 	// both Go and C functions with stack growth prologues.
    689 	_g_.stackguard0 = _g_.stack.lo + _StackGuard
    690 	_g_.stackguard1 = _g_.stackguard0
    691 	mstart1()
    692 }
    693 
    694 func mstart1() {
    695 	_g_ := getg()
    696 
    697 	if _g_ != _g_.m.g0 {
    698 		throw("bad runtimemstart")
    699 	}
    700 
    701 	// Record top of stack for use by mcall.
    702 	// Once we call schedule we're never coming back,
    703 	// so other calls can reuse this stack space.
    704 	gosave(&_g_.m.g0.sched)
    705 	_g_.m.g0.sched.pc = ^uintptr(0) // make sure it is never used
    706 	asminit()
    707 	minit()
    708 
    709 	// Install signal handlers; after minit so that minit can
    710 	// prepare the thread to be able to handle the signals.
    711 	if _g_.m == &m0 {
    712 		// Create an extra M for callbacks on threads not created by Go.
    713 		if iscgo && !cgoHasExtraM {
    714 			cgoHasExtraM = true
    715 			newextram()
    716 		}
    717 		initsig()
    718 	}
    719 
    720 	if fn := _g_.m.mstartfn; fn != nil {
    721 		fn()
    722 	}
    723 
    724 	if _g_.m.helpgc != 0 {
    725 		_g_.m.helpgc = 0
    726 		stopm()
    727 	} else if _g_.m != &m0 {
    728 		acquirep(_g_.m.nextp.ptr())
    729 		_g_.m.nextp = 0
    730 	}
    731 	schedule()
    732 }
    733 
    734 // forEachP calls fn(p) for every P p when p reaches a GC safe point.
    735 // If a P is currently executing code, this will bring the P to a GC
    736 // safe point and execute fn on that P. If the P is not executing code
    737 // (it is idle or in a syscall), this will call fn(p) directly while
    738 // preventing the P from exiting its state. This does not ensure that
    739 // fn will run on every CPU executing Go code, but it acts as a global
    740 // memory barrier. GC uses this as a "ragged barrier."
    741 //
    742 // The caller must hold worldsema.
    743 func forEachP(fn func(*p)) {
    744 	mp := acquirem()
    745 	_p_ := getg().m.p.ptr()
    746 
    747 	lock(&sched.lock)
    748 	if sched.safePointWait != 0 {
    749 		throw("forEachP: sched.safePointWait != 0")
    750 	}
    751 	sched.safePointWait = gomaxprocs - 1
    752 	sched.safePointFn = fn
    753 
    754 	// Ask all Ps to run the safe point function.
    755 	for _, p := range allp[:gomaxprocs] {
    756 		if p != _p_ {
    757 			atomicstore(&p.runSafePointFn, 1)
    758 		}
    759 	}
    760 	preemptall()
    761 
    762 	// Any P entering _Pidle or _Psyscall from now on will observe
    763 	// p.runSafePointFn == 1 and will call runSafePointFn when
    764 	// changing its status to _Pidle/_Psyscall.
    765 
    766 	// Run safe point function for all idle Ps. sched.pidle will
    767 	// not change because we hold sched.lock.
    768 	for p := sched.pidle.ptr(); p != nil; p = p.link.ptr() {
    769 		if cas(&p.runSafePointFn, 1, 0) {
    770 			fn(p)
    771 			sched.safePointWait--
    772 		}
    773 	}
    774 
    775 	wait := sched.safePointWait > 0
    776 	unlock(&sched.lock)
    777 
    778 	// Run fn for the current P.
    779 	fn(_p_)
    780 
    781 	// Force Ps currently in _Psyscall into _Pidle and hand them
    782 	// off to induce safe point function execution.
    783 	for i := 0; i < int(gomaxprocs); i++ {
    784 		p := allp[i]
    785 		s := p.status
    786 		if s == _Psyscall && p.runSafePointFn == 1 && cas(&p.status, s, _Pidle) {
    787 			if trace.enabled {
    788 				traceGoSysBlock(p)
    789 				traceProcStop(p)
    790 			}
    791 			p.syscalltick++
    792 			handoffp(p)
    793 		}
    794 	}
    795 
    796 	// Wait for remaining Ps to run fn.
    797 	if wait {
    798 		for {
    799 			// Wait for 100us, then try to re-preempt in
    800 			// case of any races.
    801 			if notetsleep(&sched.safePointNote, 100*1000) {
    802 				noteclear(&sched.safePointNote)
    803 				break
    804 			}
    805 			preemptall()
    806 		}
    807 	}
    808 	if sched.safePointWait != 0 {
    809 		throw("forEachP: not done")
    810 	}
    811 	for i := 0; i < int(gomaxprocs); i++ {
    812 		p := allp[i]
    813 		if p.runSafePointFn != 0 {
    814 			throw("forEachP: P did not run fn")
    815 		}
    816 	}
    817 
    818 	lock(&sched.lock)
    819 	sched.safePointFn = nil
    820 	unlock(&sched.lock)
    821 	releasem(mp)
    822 }
    823 
    824 // runSafePointFn runs the safe point function, if any, for this P.
    825 // This should be called like
    826 //
    827 //     if getg().m.p.runSafePointFn != 0 {
    828 //         runSafePointFn()
    829 //     }
    830 //
    831 // runSafePointFn must be checked on any transition in to _Pidle or
    832 // _Psyscall to avoid a race where forEachP sees that the P is running
    833 // just before the P goes into _Pidle/_Psyscall and neither forEachP
    834 // nor the P run the safe-point function.
    835 func runSafePointFn() {
    836 	p := getg().m.p.ptr()
    837 	// Resolve the race between forEachP running the safe-point
    838 	// function on this P's behalf and this P running the
    839 	// safe-point function directly.
    840 	if !cas(&p.runSafePointFn, 1, 0) {
    841 		return
    842 	}
    843 	sched.safePointFn(p)
    844 	lock(&sched.lock)
    845 	sched.safePointWait--
    846 	if sched.safePointWait == 0 {
    847 		notewakeup(&sched.safePointNote)
    848 	}
    849 	unlock(&sched.lock)
    850 }
    851 
    852 // When running with cgo, we call _cgo_thread_start
    853 // to start threads for us so that we can play nicely with
    854 // foreign code.
    855 var cgoThreadStart unsafe.Pointer
    856 
    857 type cgothreadstart struct {
    858 	g   guintptr
    859 	tls *uint64
    860 	fn  unsafe.Pointer
    861 }
    862 
    863 // Allocate a new m unassociated with any thread.
    864 // Can use p for allocation context if needed.
    865 // fn is recorded as the new m's m.mstartfn.
    866 func allocm(_p_ *p, fn func()) *m {
    867 	_g_ := getg()
    868 	_g_.m.locks++ // disable GC because it can be called from sysmon
    869 	if _g_.m.p == 0 {
    870 		acquirep(_p_) // temporarily borrow p for mallocs in this function
    871 	}
    872 	mp := new(m)
    873 	mp.mstartfn = fn
    874 	mcommoninit(mp)
    875 
    876 	// In case of cgo or Solaris, pthread_create will make us a stack.
    877 	// Windows and Plan 9 will layout sched stack on OS stack.
    878 	if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" {
    879 		mp.g0 = malg(-1)
    880 	} else {
    881 		mp.g0 = malg(8192 * stackGuardMultiplier)
    882 	}
    883 	mp.g0.m = mp
    884 
    885 	if _p_ == _g_.m.p.ptr() {
    886 		releasep()
    887 	}
    888 	_g_.m.locks--
    889 	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
    890 		_g_.stackguard0 = stackPreempt
    891 	}
    892 
    893 	return mp
    894 }
    895 
    896 // needm is called when a cgo callback happens on a
    897 // thread without an m (a thread not created by Go).
    898 // In this case, needm is expected to find an m to use
    899 // and return with m, g initialized correctly.
    900 // Since m and g are not set now (likely nil, but see below)
    901 // needm is limited in what routines it can call. In particular
    902 // it can only call nosplit functions (textflag 7) and cannot
    903 // do any scheduling that requires an m.
    904 //
    905 // In order to avoid needing heavy lifting here, we adopt
    906 // the following strategy: there is a stack of available m's
    907 // that can be stolen. Using compare-and-swap
    908 // to pop from the stack has ABA races, so we simulate
    909 // a lock by doing an exchange (via casp) to steal the stack
    910 // head and replace the top pointer with MLOCKED (1).
    911 // This serves as a simple spin lock that we can use even
    912 // without an m. The thread that locks the stack in this way
    913 // unlocks the stack by storing a valid stack head pointer.
    914 //
    915 // In order to make sure that there is always an m structure
    916 // available to be stolen, we maintain the invariant that there
    917 // is always one more than needed. At the beginning of the
    918 // program (if cgo is in use) the list is seeded with a single m.
    919 // If needm finds that it has taken the last m off the list, its job
    920 // is - once it has installed its own m so that it can do things like
    921 // allocate memory - to create a spare m and put it on the list.
    922 //
    923 // Each of these extra m's also has a g0 and a curg that are
    924 // pressed into service as the scheduling stack and current
    925 // goroutine for the duration of the cgo callback.
    926 //
    927 // When the callback is done with the m, it calls dropm to
    928 // put the m back on the list.
    929 //go:nosplit
    930 func needm(x byte) {
    931 	if iscgo && !cgoHasExtraM {
    932 		// Can happen if C/C++ code calls Go from a global ctor.
    933 		// Can not throw, because scheduler is not initialized yet.
    934 		write(2, unsafe.Pointer(&earlycgocallback[0]), int32(len(earlycgocallback)))
    935 		exit(1)
    936 	}
    937 
    938 	// Lock extra list, take head, unlock popped list.
    939 	// nilokay=false is safe here because of the invariant above,
    940 	// that the extra list always contains or will soon contain
    941 	// at least one m.
    942 	mp := lockextra(false)
    943 
    944 	// Set needextram when we've just emptied the list,
    945 	// so that the eventual call into cgocallbackg will
    946 	// allocate a new m for the extra list. We delay the
    947 	// allocation until then so that it can be done
    948 	// after exitsyscall makes sure it is okay to be
    949 	// running at all (that is, there's no garbage collection
    950 	// running right now).
    951 	mp.needextram = mp.schedlink == 0
    952 	unlockextra(mp.schedlink.ptr())
    953 
    954 	// Install g (= m->g0) and set the stack bounds
    955 	// to match the current stack. We don't actually know
    956 	// how big the stack is, like we don't know how big any
    957 	// scheduling stack is, but we assume there's at least 32 kB,
    958 	// which is more than enough for us.
    959 	setg(mp.g0)
    960 	_g_ := getg()
    961 	_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&x))) + 1024
    962 	_g_.stack.lo = uintptr(noescape(unsafe.Pointer(&x))) - 32*1024
    963 	_g_.stackguard0 = _g_.stack.lo + _StackGuard
    964 
    965 	msigsave(mp)
    966 	// Initialize this thread to use the m.
    967 	asminit()
    968 	minit()
    969 }
    970 
    971 var earlycgocallback = []byte("fatal error: cgo callback before cgo call\n")
    972 
    973 // newextram allocates an m and puts it on the extra list.
    974 // It is called with a working local m, so that it can do things
    975 // like call schedlock and allocate.
    976 func newextram() {
    977 	// Create extra goroutine locked to extra m.
    978 	// The goroutine is the context in which the cgo callback will run.
    979 	// The sched.pc will never be returned to, but setting it to
    980 	// goexit makes clear to the traceback routines where
    981 	// the goroutine stack ends.
    982 	mp := allocm(nil, nil)
    983 	gp := malg(4096)
    984 	gp.sched.pc = funcPC(goexit) + _PCQuantum
    985 	gp.sched.sp = gp.stack.hi
    986 	gp.sched.sp -= 4 * regSize // extra space in case of reads slightly beyond frame
    987 	gp.sched.lr = 0
    988 	gp.sched.g = guintptr(unsafe.Pointer(gp))
    989 	gp.syscallpc = gp.sched.pc
    990 	gp.syscallsp = gp.sched.sp
    991 	// malg returns status as Gidle, change to Gsyscall before adding to allg
    992 	// where GC will see it.
    993 	casgstatus(gp, _Gidle, _Gsyscall)
    994 	gp.m = mp
    995 	mp.curg = gp
    996 	mp.locked = _LockInternal
    997 	mp.lockedg = gp
    998 	gp.lockedm = mp
    999 	gp.goid = int64(xadd64(&sched.goidgen, 1))
   1000 	if raceenabled {
   1001 		gp.racectx = racegostart(funcPC(newextram))
   1002 	}
   1003 	// put on allg for garbage collector
   1004 	allgadd(gp)
   1005 
   1006 	// Add m to the extra list.
   1007 	mnext := lockextra(true)
   1008 	mp.schedlink.set(mnext)
   1009 	unlockextra(mp)
   1010 }
   1011 
   1012 // dropm is called when a cgo callback has called needm but is now
   1013 // done with the callback and returning back into the non-Go thread.
   1014 // It puts the current m back onto the extra list.
   1015 //
   1016 // The main expense here is the call to signalstack to release the
   1017 // m's signal stack, and then the call to needm on the next callback
   1018 // from this thread. It is tempting to try to save the m for next time,
   1019 // which would eliminate both these costs, but there might not be
   1020 // a next time: the current thread (which Go does not control) might exit.
   1021 // If we saved the m for that thread, there would be an m leak each time
   1022 // such a thread exited. Instead, we acquire and release an m on each
   1023 // call. These should typically not be scheduling operations, just a few
   1024 // atomics, so the cost should be small.
   1025 //
   1026 // TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
   1027 // variable using pthread_key_create. Unlike the pthread keys we already use
   1028 // on OS X, this dummy key would never be read by Go code. It would exist
   1029 // only so that we could register at thread-exit-time destructor.
   1030 // That destructor would put the m back onto the extra list.
   1031 // This is purely a performance optimization. The current version,
   1032 // in which dropm happens on each cgo call, is still correct too.
   1033 // We may have to keep the current version on systems with cgo
   1034 // but without pthreads, like Windows.
   1035 func dropm() {
   1036 	// Undo whatever initialization minit did during needm.
   1037 	unminit()
   1038 
   1039 	// Clear m and g, and return m to the extra list.
   1040 	// After the call to setg we can only call nosplit functions
   1041 	// with no pointer manipulation.
   1042 	mp := getg().m
   1043 	mnext := lockextra(true)
   1044 	mp.schedlink.set(mnext)
   1045 
   1046 	setg(nil)
   1047 	unlockextra(mp)
   1048 }
   1049 
   1050 var extram uintptr
   1051 
   1052 // lockextra locks the extra list and returns the list head.
   1053 // The caller must unlock the list by storing a new list head
   1054 // to extram. If nilokay is true, then lockextra will
   1055 // return a nil list head if that's what it finds. If nilokay is false,
   1056 // lockextra will keep waiting until the list head is no longer nil.
   1057 //go:nosplit
   1058 func lockextra(nilokay bool) *m {
   1059 	const locked = 1
   1060 
   1061 	for {
   1062 		old := atomicloaduintptr(&extram)
   1063 		if old == locked {
   1064 			yield := osyield
   1065 			yield()
   1066 			continue
   1067 		}
   1068 		if old == 0 && !nilokay {
   1069 			usleep(1)
   1070 			continue
   1071 		}
   1072 		if casuintptr(&extram, old, locked) {
   1073 			return (*m)(unsafe.Pointer(old))
   1074 		}
   1075 		yield := osyield
   1076 		yield()
   1077 		continue
   1078 	}
   1079 }
   1080 
   1081 //go:nosplit
   1082 func unlockextra(mp *m) {
   1083 	atomicstoreuintptr(&extram, uintptr(unsafe.Pointer(mp)))
   1084 }
   1085 
   1086 // Create a new m.  It will start off with a call to fn, or else the scheduler.
   1087 // fn needs to be static and not a heap allocated closure.
   1088 // May run with m.p==nil, so write barriers are not allowed.
   1089 //go:nowritebarrier
   1090 func newm(fn func(), _p_ *p) {
   1091 	mp := allocm(_p_, fn)
   1092 	mp.nextp.set(_p_)
   1093 	msigsave(mp)
   1094 	if iscgo {
   1095 		var ts cgothreadstart
   1096 		if _cgo_thread_start == nil {
   1097 			throw("_cgo_thread_start missing")
   1098 		}
   1099 		ts.g.set(mp.g0)
   1100 		ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
   1101 		ts.fn = unsafe.Pointer(funcPC(mstart))
   1102 		asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
   1103 		return
   1104 	}
   1105 	newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
   1106 }
   1107 
   1108 // Stops execution of the current m until new work is available.
   1109 // Returns with acquired P.
   1110 func stopm() {
   1111 	_g_ := getg()
   1112 
   1113 	if _g_.m.locks != 0 {
   1114 		throw("stopm holding locks")
   1115 	}
   1116 	if _g_.m.p != 0 {
   1117 		throw("stopm holding p")
   1118 	}
   1119 	if _g_.m.spinning {
   1120 		_g_.m.spinning = false
   1121 		xadd(&sched.nmspinning, -1)
   1122 	}
   1123 
   1124 retry:
   1125 	lock(&sched.lock)
   1126 	mput(_g_.m)
   1127 	unlock(&sched.lock)
   1128 	notesleep(&_g_.m.park)
   1129 	noteclear(&_g_.m.park)
   1130 	if _g_.m.helpgc != 0 {
   1131 		gchelper()
   1132 		_g_.m.helpgc = 0
   1133 		_g_.m.mcache = nil
   1134 		_g_.m.p = 0
   1135 		goto retry
   1136 	}
   1137 	acquirep(_g_.m.nextp.ptr())
   1138 	_g_.m.nextp = 0
   1139 }
   1140 
   1141 func mspinning() {
   1142 	gp := getg()
   1143 	if !runqempty(gp.m.nextp.ptr()) {
   1144 		// Something (presumably the GC) was readied while the
   1145 		// runtime was starting up this M, so the M is no
   1146 		// longer spinning.
   1147 		if int32(xadd(&sched.nmspinning, -1)) < 0 {
   1148 			throw("mspinning: nmspinning underflowed")
   1149 		}
   1150 	} else {
   1151 		gp.m.spinning = true
   1152 	}
   1153 }
   1154 
   1155 // Schedules some M to run the p (creates an M if necessary).
   1156 // If p==nil, tries to get an idle P, if no idle P's does nothing.
   1157 // May run with m.p==nil, so write barriers are not allowed.
   1158 //go:nowritebarrier
   1159 func startm(_p_ *p, spinning bool) {
   1160 	lock(&sched.lock)
   1161 	if _p_ == nil {
   1162 		_p_ = pidleget()
   1163 		if _p_ == nil {
   1164 			unlock(&sched.lock)
   1165 			if spinning {
   1166 				xadd(&sched.nmspinning, -1)
   1167 			}
   1168 			return
   1169 		}
   1170 	}
   1171 	mp := mget()
   1172 	unlock(&sched.lock)
   1173 	if mp == nil {
   1174 		var fn func()
   1175 		if spinning {
   1176 			fn = mspinning
   1177 		}
   1178 		newm(fn, _p_)
   1179 		return
   1180 	}
   1181 	if mp.spinning {
   1182 		throw("startm: m is spinning")
   1183 	}
   1184 	if mp.nextp != 0 {
   1185 		throw("startm: m has p")
   1186 	}
   1187 	if spinning && !runqempty(_p_) {
   1188 		throw("startm: p has runnable gs")
   1189 	}
   1190 	mp.spinning = spinning
   1191 	mp.nextp.set(_p_)
   1192 	notewakeup(&mp.park)
   1193 }
   1194 
   1195 // Hands off P from syscall or locked M.
   1196 // Always runs without a P, so write barriers are not allowed.
   1197 //go:nowritebarrier
   1198 func handoffp(_p_ *p) {
   1199 	// if it has local work, start it straight away
   1200 	if !runqempty(_p_) || sched.runqsize != 0 {
   1201 		startm(_p_, false)
   1202 		return
   1203 	}
   1204 	// no local work, check that there are no spinning/idle M's,
   1205 	// otherwise our help is not required
   1206 	if atomicload(&sched.nmspinning)+atomicload(&sched.npidle) == 0 && cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
   1207 		startm(_p_, true)
   1208 		return
   1209 	}
   1210 	lock(&sched.lock)
   1211 	if sched.gcwaiting != 0 {
   1212 		_p_.status = _Pgcstop
   1213 		sched.stopwait--
   1214 		if sched.stopwait == 0 {
   1215 			notewakeup(&sched.stopnote)
   1216 		}
   1217 		unlock(&sched.lock)
   1218 		return
   1219 	}
   1220 	if _p_.runSafePointFn != 0 && cas(&_p_.runSafePointFn, 1, 0) {
   1221 		sched.safePointFn(_p_)
   1222 		sched.safePointWait--
   1223 		if sched.safePointWait == 0 {
   1224 			notewakeup(&sched.safePointNote)
   1225 		}
   1226 	}
   1227 	if sched.runqsize != 0 {
   1228 		unlock(&sched.lock)
   1229 		startm(_p_, false)
   1230 		return
   1231 	}
   1232 	// If this is the last running P and nobody is polling network,
   1233 	// need to wakeup another M to poll network.
   1234 	if sched.npidle == uint32(gomaxprocs-1) && atomicload64(&sched.lastpoll) != 0 {
   1235 		unlock(&sched.lock)
   1236 		startm(_p_, false)
   1237 		return
   1238 	}
   1239 	pidleput(_p_)
   1240 	unlock(&sched.lock)
   1241 }
   1242 
   1243 // Tries to add one more P to execute G's.
   1244 // Called when a G is made runnable (newproc, ready).
   1245 func wakep() {
   1246 	// be conservative about spinning threads
   1247 	if !cas(&sched.nmspinning, 0, 1) {
   1248 		return
   1249 	}
   1250 	startm(nil, true)
   1251 }
   1252 
   1253 // Stops execution of the current m that is locked to a g until the g is runnable again.
   1254 // Returns with acquired P.
   1255 func stoplockedm() {
   1256 	_g_ := getg()
   1257 
   1258 	if _g_.m.lockedg == nil || _g_.m.lockedg.lockedm != _g_.m {
   1259 		throw("stoplockedm: inconsistent locking")
   1260 	}
   1261 	if _g_.m.p != 0 {
   1262 		// Schedule another M to run this p.
   1263 		_p_ := releasep()
   1264 		handoffp(_p_)
   1265 	}
   1266 	incidlelocked(1)
   1267 	// Wait until another thread schedules lockedg again.
   1268 	notesleep(&_g_.m.park)
   1269 	noteclear(&_g_.m.park)
   1270 	status := readgstatus(_g_.m.lockedg)
   1271 	if status&^_Gscan != _Grunnable {
   1272 		print("runtime:stoplockedm: g is not Grunnable or Gscanrunnable\n")
   1273 		dumpgstatus(_g_)
   1274 		throw("stoplockedm: not runnable")
   1275 	}
   1276 	acquirep(_g_.m.nextp.ptr())
   1277 	_g_.m.nextp = 0
   1278 }
   1279 
   1280 // Schedules the locked m to run the locked gp.
   1281 // May run during STW, so write barriers are not allowed.
   1282 //go:nowritebarrier
   1283 func startlockedm(gp *g) {
   1284 	_g_ := getg()
   1285 
   1286 	mp := gp.lockedm
   1287 	if mp == _g_.m {
   1288 		throw("startlockedm: locked to me")
   1289 	}
   1290 	if mp.nextp != 0 {
   1291 		throw("startlockedm: m has p")
   1292 	}
   1293 	// directly handoff current P to the locked m
   1294 	incidlelocked(-1)
   1295 	_p_ := releasep()
   1296 	mp.nextp.set(_p_)
   1297 	notewakeup(&mp.park)
   1298 	stopm()
   1299 }
   1300 
   1301 // Stops the current m for stopTheWorld.
   1302 // Returns when the world is restarted.
   1303 func gcstopm() {
   1304 	_g_ := getg()
   1305 
   1306 	if sched.gcwaiting == 0 {
   1307 		throw("gcstopm: not waiting for gc")
   1308 	}
   1309 	if _g_.m.spinning {
   1310 		_g_.m.spinning = false
   1311 		xadd(&sched.nmspinning, -1)
   1312 	}
   1313 	_p_ := releasep()
   1314 	lock(&sched.lock)
   1315 	_p_.status = _Pgcstop
   1316 	sched.stopwait--
   1317 	if sched.stopwait == 0 {
   1318 		notewakeup(&sched.stopnote)
   1319 	}
   1320 	unlock(&sched.lock)
   1321 	stopm()
   1322 }
   1323 
   1324 // Schedules gp to run on the current M.
   1325 // If inheritTime is true, gp inherits the remaining time in the
   1326 // current time slice. Otherwise, it starts a new time slice.
   1327 // Never returns.
   1328 func execute(gp *g, inheritTime bool) {
   1329 	_g_ := getg()
   1330 
   1331 	casgstatus(gp, _Grunnable, _Grunning)
   1332 	gp.waitsince = 0
   1333 	gp.preempt = false
   1334 	gp.stackguard0 = gp.stack.lo + _StackGuard
   1335 	if !inheritTime {
   1336 		_g_.m.p.ptr().schedtick++
   1337 	}
   1338 	_g_.m.curg = gp
   1339 	gp.m = _g_.m
   1340 
   1341 	// Check whether the profiler needs to be turned on or off.
   1342 	hz := sched.profilehz
   1343 	if _g_.m.profilehz != hz {
   1344 		resetcpuprofiler(hz)
   1345 	}
   1346 
   1347 	if trace.enabled {
   1348 		// GoSysExit has to happen when we have a P, but before GoStart.
   1349 		// So we emit it here.
   1350 		if gp.syscallsp != 0 && gp.sysblocktraced {
   1351 			// Since gp.sysblocktraced is true, we must emit an event.
   1352 			// There is a race between the code that initializes sysexitseq
   1353 			// and sysexitticks (in exitsyscall, which runs without a P,
   1354 			// and therefore is not stopped with the rest of the world)
   1355 			// and the code that initializes a new trace.
   1356 			// The recorded sysexitseq and sysexitticks must therefore
   1357 			// be treated as "best effort". If they are valid for this trace,
   1358 			// then great, use them for greater accuracy.
   1359 			// But if they're not valid for this trace, assume that the
   1360 			// trace was started after the actual syscall exit (but before
   1361 			// we actually managed to start the goroutine, aka right now),
   1362 			// and assign a fresh time stamp to keep the log consistent.
   1363 			seq, ts := gp.sysexitseq, gp.sysexitticks
   1364 			if seq == 0 || int64(seq)-int64(trace.seqStart) < 0 {
   1365 				seq, ts = tracestamp()
   1366 			}
   1367 			traceGoSysExit(seq, ts)
   1368 		}
   1369 		traceGoStart()
   1370 	}
   1371 
   1372 	gogo(&gp.sched)
   1373 }
   1374 
   1375 // Finds a runnable goroutine to execute.
   1376 // Tries to steal from other P's, get g from global queue, poll network.
   1377 func findrunnable() (gp *g, inheritTime bool) {
   1378 	_g_ := getg()
   1379 
   1380 top:
   1381 	if sched.gcwaiting != 0 {
   1382 		gcstopm()
   1383 		goto top
   1384 	}
   1385 	if _g_.m.p.ptr().runSafePointFn != 0 {
   1386 		runSafePointFn()
   1387 	}
   1388 	if fingwait && fingwake {
   1389 		if gp := wakefing(); gp != nil {
   1390 			ready(gp, 0)
   1391 		}
   1392 	}
   1393 
   1394 	// local runq
   1395 	if gp, inheritTime := runqget(_g_.m.p.ptr()); gp != nil {
   1396 		return gp, inheritTime
   1397 	}
   1398 
   1399 	// global runq
   1400 	if sched.runqsize != 0 {
   1401 		lock(&sched.lock)
   1402 		gp := globrunqget(_g_.m.p.ptr(), 0)
   1403 		unlock(&sched.lock)
   1404 		if gp != nil {
   1405 			return gp, false
   1406 		}
   1407 	}
   1408 
   1409 	// Poll network.
   1410 	// This netpoll is only an optimization before we resort to stealing.
   1411 	// We can safely skip it if there a thread blocked in netpoll already.
   1412 	// If there is any kind of logical race with that blocked thread
   1413 	// (e.g. it has already returned from netpoll, but does not set lastpoll yet),
   1414 	// this thread will do blocking netpoll below anyway.
   1415 	if netpollinited() && sched.lastpoll != 0 {
   1416 		if gp := netpoll(false); gp != nil { // non-blocking
   1417 			// netpoll returns list of goroutines linked by schedlink.
   1418 			injectglist(gp.schedlink.ptr())
   1419 			casgstatus(gp, _Gwaiting, _Grunnable)
   1420 			if trace.enabled {
   1421 				traceGoUnpark(gp, 0)
   1422 			}
   1423 			return gp, false
   1424 		}
   1425 	}
   1426 
   1427 	// If number of spinning M's >= number of busy P's, block.
   1428 	// This is necessary to prevent excessive CPU consumption
   1429 	// when GOMAXPROCS>>1 but the program parallelism is low.
   1430 	if !_g_.m.spinning && 2*atomicload(&sched.nmspinning) >= uint32(gomaxprocs)-atomicload(&sched.npidle) { // TODO: fast atomic
   1431 		goto stop
   1432 	}
   1433 	if !_g_.m.spinning {
   1434 		_g_.m.spinning = true
   1435 		xadd(&sched.nmspinning, 1)
   1436 	}
   1437 	// random steal from other P's
   1438 	for i := 0; i < int(4*gomaxprocs); i++ {
   1439 		if sched.gcwaiting != 0 {
   1440 			goto top
   1441 		}
   1442 		_p_ := allp[fastrand1()%uint32(gomaxprocs)]
   1443 		var gp *g
   1444 		if _p_ == _g_.m.p.ptr() {
   1445 			gp, _ = runqget(_p_)
   1446 		} else {
   1447 			stealRunNextG := i > 2*int(gomaxprocs) // first look for ready queues with more than 1 g
   1448 			gp = runqsteal(_g_.m.p.ptr(), _p_, stealRunNextG)
   1449 		}
   1450 		if gp != nil {
   1451 			return gp, false
   1452 		}
   1453 	}
   1454 
   1455 stop:
   1456 
   1457 	// We have nothing to do. If we're in the GC mark phase and can
   1458 	// safely scan and blacken objects, run idle-time marking
   1459 	// rather than give up the P.
   1460 	if _p_ := _g_.m.p.ptr(); gcBlackenEnabled != 0 && _p_.gcBgMarkWorker != nil && gcMarkWorkAvailable(_p_) {
   1461 		_p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
   1462 		gp := _p_.gcBgMarkWorker
   1463 		casgstatus(gp, _Gwaiting, _Grunnable)
   1464 		if trace.enabled {
   1465 			traceGoUnpark(gp, 0)
   1466 		}
   1467 		return gp, false
   1468 	}
   1469 
   1470 	// return P and block
   1471 	lock(&sched.lock)
   1472 	if sched.gcwaiting != 0 || _g_.m.p.ptr().runSafePointFn != 0 {
   1473 		unlock(&sched.lock)
   1474 		goto top
   1475 	}
   1476 	if sched.runqsize != 0 {
   1477 		gp := globrunqget(_g_.m.p.ptr(), 0)
   1478 		unlock(&sched.lock)
   1479 		return gp, false
   1480 	}
   1481 	_p_ := releasep()
   1482 	pidleput(_p_)
   1483 	unlock(&sched.lock)
   1484 	if _g_.m.spinning {
   1485 		_g_.m.spinning = false
   1486 		xadd(&sched.nmspinning, -1)
   1487 	}
   1488 
   1489 	// check all runqueues once again
   1490 	for i := 0; i < int(gomaxprocs); i++ {
   1491 		_p_ := allp[i]
   1492 		if _p_ != nil && !runqempty(_p_) {
   1493 			lock(&sched.lock)
   1494 			_p_ = pidleget()
   1495 			unlock(&sched.lock)
   1496 			if _p_ != nil {
   1497 				acquirep(_p_)
   1498 				goto top
   1499 			}
   1500 			break
   1501 		}
   1502 	}
   1503 
   1504 	// poll network
   1505 	if netpollinited() && xchg64(&sched.lastpoll, 0) != 0 {
   1506 		if _g_.m.p != 0 {
   1507 			throw("findrunnable: netpoll with p")
   1508 		}
   1509 		if _g_.m.spinning {
   1510 			throw("findrunnable: netpoll with spinning")
   1511 		}
   1512 		gp := netpoll(true) // block until new work is available
   1513 		atomicstore64(&sched.lastpoll, uint64(nanotime()))
   1514 		if gp != nil {
   1515 			lock(&sched.lock)
   1516 			_p_ = pidleget()
   1517 			unlock(&sched.lock)
   1518 			if _p_ != nil {
   1519 				acquirep(_p_)
   1520 				injectglist(gp.schedlink.ptr())
   1521 				casgstatus(gp, _Gwaiting, _Grunnable)
   1522 				if trace.enabled {
   1523 					traceGoUnpark(gp, 0)
   1524 				}
   1525 				return gp, false
   1526 			}
   1527 			injectglist(gp)
   1528 		}
   1529 	}
   1530 	stopm()
   1531 	goto top
   1532 }
   1533 
   1534 func resetspinning() {
   1535 	_g_ := getg()
   1536 
   1537 	var nmspinning uint32
   1538 	if _g_.m.spinning {
   1539 		_g_.m.spinning = false
   1540 		nmspinning = xadd(&sched.nmspinning, -1)
   1541 		if nmspinning < 0 {
   1542 			throw("findrunnable: negative nmspinning")
   1543 		}
   1544 	} else {
   1545 		nmspinning = atomicload(&sched.nmspinning)
   1546 	}
   1547 
   1548 	// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
   1549 	// so see if we need to wakeup another P here.
   1550 	if nmspinning == 0 && atomicload(&sched.npidle) > 0 {
   1551 		wakep()
   1552 	}
   1553 }
   1554 
   1555 // Injects the list of runnable G's into the scheduler.
   1556 // Can run concurrently with GC.
   1557 func injectglist(glist *g) {
   1558 	if glist == nil {
   1559 		return
   1560 	}
   1561 	if trace.enabled {
   1562 		for gp := glist; gp != nil; gp = gp.schedlink.ptr() {
   1563 			traceGoUnpark(gp, 0)
   1564 		}
   1565 	}
   1566 	lock(&sched.lock)
   1567 	var n int
   1568 	for n = 0; glist != nil; n++ {
   1569 		gp := glist
   1570 		glist = gp.schedlink.ptr()
   1571 		casgstatus(gp, _Gwaiting, _Grunnable)
   1572 		globrunqput(gp)
   1573 	}
   1574 	unlock(&sched.lock)
   1575 	for ; n != 0 && sched.npidle != 0; n-- {
   1576 		startm(nil, false)
   1577 	}
   1578 }
   1579 
   1580 // One round of scheduler: find a runnable goroutine and execute it.
   1581 // Never returns.
   1582 func schedule() {
   1583 	_g_ := getg()
   1584 
   1585 	if _g_.m.locks != 0 {
   1586 		throw("schedule: holding locks")
   1587 	}
   1588 
   1589 	if _g_.m.lockedg != nil {
   1590 		stoplockedm()
   1591 		execute(_g_.m.lockedg, false) // Never returns.
   1592 	}
   1593 
   1594 top:
   1595 	if sched.gcwaiting != 0 {
   1596 		gcstopm()
   1597 		goto top
   1598 	}
   1599 	if _g_.m.p.ptr().runSafePointFn != 0 {
   1600 		runSafePointFn()
   1601 	}
   1602 
   1603 	var gp *g
   1604 	var inheritTime bool
   1605 	if trace.enabled || trace.shutdown {
   1606 		gp = traceReader()
   1607 		if gp != nil {
   1608 			casgstatus(gp, _Gwaiting, _Grunnable)
   1609 			traceGoUnpark(gp, 0)
   1610 			resetspinning()
   1611 		}
   1612 	}
   1613 	if gp == nil && gcBlackenEnabled != 0 {
   1614 		gp = gcController.findRunnableGCWorker(_g_.m.p.ptr())
   1615 		if gp != nil {
   1616 			resetspinning()
   1617 		}
   1618 	}
   1619 	if gp == nil {
   1620 		// Check the global runnable queue once in a while to ensure fairness.
   1621 		// Otherwise two goroutines can completely occupy the local runqueue
   1622 		// by constantly respawning each other.
   1623 		if _g_.m.p.ptr().schedtick%61 == 0 && sched.runqsize > 0 {
   1624 			lock(&sched.lock)
   1625 			gp = globrunqget(_g_.m.p.ptr(), 1)
   1626 			unlock(&sched.lock)
   1627 			if gp != nil {
   1628 				resetspinning()
   1629 			}
   1630 		}
   1631 	}
   1632 	if gp == nil {
   1633 		gp, inheritTime = runqget(_g_.m.p.ptr())
   1634 		if gp != nil && _g_.m.spinning {
   1635 			throw("schedule: spinning with local work")
   1636 		}
   1637 	}
   1638 	if gp == nil {
   1639 		gp, inheritTime = findrunnable() // blocks until work is available
   1640 		resetspinning()
   1641 	}
   1642 
   1643 	if gp.lockedm != nil {
   1644 		// Hands off own p to the locked m,
   1645 		// then blocks waiting for a new p.
   1646 		startlockedm(gp)
   1647 		goto top
   1648 	}
   1649 
   1650 	execute(gp, inheritTime)
   1651 }
   1652 
   1653 // dropg removes the association between m and the current goroutine m->curg (gp for short).
   1654 // Typically a caller sets gp's status away from Grunning and then
   1655 // immediately calls dropg to finish the job. The caller is also responsible
   1656 // for arranging that gp will be restarted using ready at an
   1657 // appropriate time. After calling dropg and arranging for gp to be
   1658 // readied later, the caller can do other work but eventually should
   1659 // call schedule to restart the scheduling of goroutines on this m.
   1660 func dropg() {
   1661 	_g_ := getg()
   1662 
   1663 	if _g_.m.lockedg == nil {
   1664 		_g_.m.curg.m = nil
   1665 		_g_.m.curg = nil
   1666 	}
   1667 }
   1668 
   1669 func parkunlock_c(gp *g, lock unsafe.Pointer) bool {
   1670 	unlock((*mutex)(lock))
   1671 	return true
   1672 }
   1673 
   1674 // park continuation on g0.
   1675 func park_m(gp *g) {
   1676 	_g_ := getg()
   1677 
   1678 	if trace.enabled {
   1679 		traceGoPark(_g_.m.waittraceev, _g_.m.waittraceskip, gp)
   1680 	}
   1681 
   1682 	casgstatus(gp, _Grunning, _Gwaiting)
   1683 	dropg()
   1684 
   1685 	if _g_.m.waitunlockf != nil {
   1686 		fn := *(*func(*g, unsafe.Pointer) bool)(unsafe.Pointer(&_g_.m.waitunlockf))
   1687 		ok := fn(gp, _g_.m.waitlock)
   1688 		_g_.m.waitunlockf = nil
   1689 		_g_.m.waitlock = nil
   1690 		if !ok {
   1691 			if trace.enabled {
   1692 				traceGoUnpark(gp, 2)
   1693 			}
   1694 			casgstatus(gp, _Gwaiting, _Grunnable)
   1695 			execute(gp, true) // Schedule it back, never returns.
   1696 		}
   1697 	}
   1698 	schedule()
   1699 }
   1700 
   1701 func goschedImpl(gp *g) {
   1702 	status := readgstatus(gp)
   1703 	if status&^_Gscan != _Grunning {
   1704 		dumpgstatus(gp)
   1705 		throw("bad g status")
   1706 	}
   1707 	casgstatus(gp, _Grunning, _Grunnable)
   1708 	dropg()
   1709 	lock(&sched.lock)
   1710 	globrunqput(gp)
   1711 	unlock(&sched.lock)
   1712 
   1713 	schedule()
   1714 }
   1715 
   1716 // Gosched continuation on g0.
   1717 func gosched_m(gp *g) {
   1718 	if trace.enabled {
   1719 		traceGoSched()
   1720 	}
   1721 	goschedImpl(gp)
   1722 }
   1723 
   1724 func gopreempt_m(gp *g) {
   1725 	if trace.enabled {
   1726 		traceGoPreempt()
   1727 	}
   1728 	goschedImpl(gp)
   1729 }
   1730 
   1731 // Finishes execution of the current goroutine.
   1732 func goexit1() {
   1733 	if raceenabled {
   1734 		racegoend()
   1735 	}
   1736 	if trace.enabled {
   1737 		traceGoEnd()
   1738 	}
   1739 	mcall(goexit0)
   1740 }
   1741 
   1742 // goexit continuation on g0.
   1743 func goexit0(gp *g) {
   1744 	_g_ := getg()
   1745 
   1746 	casgstatus(gp, _Grunning, _Gdead)
   1747 	gp.m = nil
   1748 	gp.lockedm = nil
   1749 	_g_.m.lockedg = nil
   1750 	gp.paniconfault = false
   1751 	gp._defer = nil // should be true already but just in case.
   1752 	gp._panic = nil // non-nil for Goexit during panic. points at stack-allocated data.
   1753 	gp.writebuf = nil
   1754 	gp.waitreason = ""
   1755 	gp.param = nil
   1756 
   1757 	dropg()
   1758 
   1759 	if _g_.m.locked&^_LockExternal != 0 {
   1760 		print("invalid m->locked = ", _g_.m.locked, "\n")
   1761 		throw("internal lockOSThread error")
   1762 	}
   1763 	_g_.m.locked = 0
   1764 	gfput(_g_.m.p.ptr(), gp)
   1765 	schedule()
   1766 }
   1767 
   1768 //go:nosplit
   1769 //go:nowritebarrier
   1770 func save(pc, sp uintptr) {
   1771 	_g_ := getg()
   1772 
   1773 	_g_.sched.pc = pc
   1774 	_g_.sched.sp = sp
   1775 	_g_.sched.lr = 0
   1776 	_g_.sched.ret = 0
   1777 	_g_.sched.ctxt = nil
   1778 	_g_.sched.g = guintptr(unsafe.Pointer(_g_))
   1779 }
   1780 
   1781 // The goroutine g is about to enter a system call.
   1782 // Record that it's not using the cpu anymore.
   1783 // This is called only from the go syscall library and cgocall,
   1784 // not from the low-level system calls used by the
   1785 //
   1786 // Entersyscall cannot split the stack: the gosave must
   1787 // make g->sched refer to the caller's stack segment, because
   1788 // entersyscall is going to return immediately after.
   1789 //
   1790 // Nothing entersyscall calls can split the stack either.
   1791 // We cannot safely move the stack during an active call to syscall,
   1792 // because we do not know which of the uintptr arguments are
   1793 // really pointers (back into the stack).
   1794 // In practice, this means that we make the fast path run through
   1795 // entersyscall doing no-split things, and the slow path has to use systemstack
   1796 // to run bigger things on the system stack.
   1797 //
   1798 // reentersyscall is the entry point used by cgo callbacks, where explicitly
   1799 // saved SP and PC are restored. This is needed when exitsyscall will be called
   1800 // from a function further up in the call stack than the parent, as g->syscallsp
   1801 // must always point to a valid stack frame. entersyscall below is the normal
   1802 // entry point for syscalls, which obtains the SP and PC from the caller.
   1803 //
   1804 // Syscall tracing:
   1805 // At the start of a syscall we emit traceGoSysCall to capture the stack trace.
   1806 // If the syscall does not block, that is it, we do not emit any other events.
   1807 // If the syscall blocks (that is, P is retaken), retaker emits traceGoSysBlock;
   1808 // when syscall returns we emit traceGoSysExit and when the goroutine starts running
   1809 // (potentially instantly, if exitsyscallfast returns true) we emit traceGoStart.
   1810 // To ensure that traceGoSysExit is emitted strictly after traceGoSysBlock,
   1811 // we remember current value of syscalltick in m (_g_.m.syscalltick = _g_.m.p.ptr().syscalltick),
   1812 // whoever emits traceGoSysBlock increments p.syscalltick afterwards;
   1813 // and we wait for the increment before emitting traceGoSysExit.
   1814 // Note that the increment is done even if tracing is not enabled,
   1815 // because tracing can be enabled in the middle of syscall. We don't want the wait to hang.
   1816 //
   1817 //go:nosplit
   1818 func reentersyscall(pc, sp uintptr) {
   1819 	_g_ := getg()
   1820 
   1821 	// Disable preemption because during this function g is in Gsyscall status,
   1822 	// but can have inconsistent g->sched, do not let GC observe it.
   1823 	_g_.m.locks++
   1824 
   1825 	if trace.enabled {
   1826 		systemstack(traceGoSysCall)
   1827 	}
   1828 
   1829 	// Entersyscall must not call any function that might split/grow the stack.
   1830 	// (See details in comment above.)
   1831 	// Catch calls that might, by replacing the stack guard with something that
   1832 	// will trip any stack check and leaving a flag to tell newstack to die.
   1833 	_g_.stackguard0 = stackPreempt
   1834 	_g_.throwsplit = true
   1835 
   1836 	// Leave SP around for GC and traceback.
   1837 	save(pc, sp)
   1838 	_g_.syscallsp = sp
   1839 	_g_.syscallpc = pc
   1840 	casgstatus(_g_, _Grunning, _Gsyscall)
   1841 	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
   1842 		systemstack(func() {
   1843 			print("entersyscall inconsistent ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
   1844 			throw("entersyscall")
   1845 		})
   1846 	}
   1847 
   1848 	if atomicload(&sched.sysmonwait) != 0 { // TODO: fast atomic
   1849 		systemstack(entersyscall_sysmon)
   1850 		save(pc, sp)
   1851 	}
   1852 
   1853 	if _g_.m.p.ptr().runSafePointFn != 0 {
   1854 		// runSafePointFn may stack split if run on this stack
   1855 		systemstack(runSafePointFn)
   1856 		save(pc, sp)
   1857 	}
   1858 
   1859 	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
   1860 	_g_.sysblocktraced = true
   1861 	_g_.m.mcache = nil
   1862 	_g_.m.p.ptr().m = 0
   1863 	atomicstore(&_g_.m.p.ptr().status, _Psyscall)
   1864 	if sched.gcwaiting != 0 {
   1865 		systemstack(entersyscall_gcwait)
   1866 		save(pc, sp)
   1867 	}
   1868 
   1869 	// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
   1870 	// We set _StackGuard to StackPreempt so that first split stack check calls morestack.
   1871 	// Morestack detects this case and throws.
   1872 	_g_.stackguard0 = stackPreempt
   1873 	_g_.m.locks--
   1874 }
   1875 
   1876 // Standard syscall entry used by the go syscall library and normal cgo calls.
   1877 //go:nosplit
   1878 func entersyscall(dummy int32) {
   1879 	reentersyscall(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
   1880 }
   1881 
   1882 func entersyscall_sysmon() {
   1883 	lock(&sched.lock)
   1884 	if atomicload(&sched.sysmonwait) != 0 {
   1885 		atomicstore(&sched.sysmonwait, 0)
   1886 		notewakeup(&sched.sysmonnote)
   1887 	}
   1888 	unlock(&sched.lock)
   1889 }
   1890 
   1891 func entersyscall_gcwait() {
   1892 	_g_ := getg()
   1893 	_p_ := _g_.m.p.ptr()
   1894 
   1895 	lock(&sched.lock)
   1896 	if sched.stopwait > 0 && cas(&_p_.status, _Psyscall, _Pgcstop) {
   1897 		if trace.enabled {
   1898 			traceGoSysBlock(_p_)
   1899 			traceProcStop(_p_)
   1900 		}
   1901 		_p_.syscalltick++
   1902 		if sched.stopwait--; sched.stopwait == 0 {
   1903 			notewakeup(&sched.stopnote)
   1904 		}
   1905 	}
   1906 	unlock(&sched.lock)
   1907 }
   1908 
   1909 // The same as entersyscall(), but with a hint that the syscall is blocking.
   1910 //go:nosplit
   1911 func entersyscallblock(dummy int32) {
   1912 	_g_ := getg()
   1913 
   1914 	_g_.m.locks++ // see comment in entersyscall
   1915 	_g_.throwsplit = true
   1916 	_g_.stackguard0 = stackPreempt // see comment in entersyscall
   1917 	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
   1918 	_g_.sysblocktraced = true
   1919 	_g_.m.p.ptr().syscalltick++
   1920 
   1921 	// Leave SP around for GC and traceback.
   1922 	pc := getcallerpc(unsafe.Pointer(&dummy))
   1923 	sp := getcallersp(unsafe.Pointer(&dummy))
   1924 	save(pc, sp)
   1925 	_g_.syscallsp = _g_.sched.sp
   1926 	_g_.syscallpc = _g_.sched.pc
   1927 	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
   1928 		sp1 := sp
   1929 		sp2 := _g_.sched.sp
   1930 		sp3 := _g_.syscallsp
   1931 		systemstack(func() {
   1932 			print("entersyscallblock inconsistent ", hex(sp1), " ", hex(sp2), " ", hex(sp3), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
   1933 			throw("entersyscallblock")
   1934 		})
   1935 	}
   1936 	casgstatus(_g_, _Grunning, _Gsyscall)
   1937 	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
   1938 		systemstack(func() {
   1939 			print("entersyscallblock inconsistent ", hex(sp), " ", hex(_g_.sched.sp), " ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
   1940 			throw("entersyscallblock")
   1941 		})
   1942 	}
   1943 
   1944 	systemstack(entersyscallblock_handoff)
   1945 
   1946 	// Resave for traceback during blocked call.
   1947 	save(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
   1948 
   1949 	_g_.m.locks--
   1950 }
   1951 
   1952 func entersyscallblock_handoff() {
   1953 	if trace.enabled {
   1954 		traceGoSysCall()
   1955 		traceGoSysBlock(getg().m.p.ptr())
   1956 	}
   1957 	handoffp(releasep())
   1958 }
   1959 
   1960 // The goroutine g exited its system call.
   1961 // Arrange for it to run on a cpu again.
   1962 // This is called only from the go syscall library, not
   1963 // from the low-level system calls used by the
   1964 //go:nosplit
   1965 func exitsyscall(dummy int32) {
   1966 	_g_ := getg()
   1967 
   1968 	_g_.m.locks++ // see comment in entersyscall
   1969 	if getcallersp(unsafe.Pointer(&dummy)) > _g_.syscallsp {
   1970 		throw("exitsyscall: syscall frame is no longer valid")
   1971 	}
   1972 
   1973 	_g_.waitsince = 0
   1974 	oldp := _g_.m.p.ptr()
   1975 	if exitsyscallfast() {
   1976 		if _g_.m.mcache == nil {
   1977 			throw("lost mcache")
   1978 		}
   1979 		if trace.enabled {
   1980 			if oldp != _g_.m.p.ptr() || _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
   1981 				systemstack(traceGoStart)
   1982 			}
   1983 		}
   1984 		// There's a cpu for us, so we can run.
   1985 		_g_.m.p.ptr().syscalltick++
   1986 		// We need to cas the status and scan before resuming...
   1987 		casgstatus(_g_, _Gsyscall, _Grunning)
   1988 
   1989 		// Garbage collector isn't running (since we are),
   1990 		// so okay to clear syscallsp.
   1991 		_g_.syscallsp = 0
   1992 		_g_.m.locks--
   1993 		if _g_.preempt {
   1994 			// restore the preemption request in case we've cleared it in newstack
   1995 			_g_.stackguard0 = stackPreempt
   1996 		} else {
   1997 			// otherwise restore the real _StackGuard, we've spoiled it in entersyscall/entersyscallblock
   1998 			_g_.stackguard0 = _g_.stack.lo + _StackGuard
   1999 		}
   2000 		_g_.throwsplit = false
   2001 		return
   2002 	}
   2003 
   2004 	_g_.sysexitticks = 0
   2005 	_g_.sysexitseq = 0
   2006 	if trace.enabled {
   2007 		// Wait till traceGoSysBlock event is emitted.
   2008 		// This ensures consistency of the trace (the goroutine is started after it is blocked).
   2009 		for oldp != nil && oldp.syscalltick == _g_.m.syscalltick {
   2010 			osyield()
   2011 		}
   2012 		// We can't trace syscall exit right now because we don't have a P.
   2013 		// Tracing code can invoke write barriers that cannot run without a P.
   2014 		// So instead we remember the syscall exit time and emit the event
   2015 		// in execute when we have a P.
   2016 		_g_.sysexitseq, _g_.sysexitticks = tracestamp()
   2017 	}
   2018 
   2019 	_g_.m.locks--
   2020 
   2021 	// Call the scheduler.
   2022 	mcall(exitsyscall0)
   2023 
   2024 	if _g_.m.mcache == nil {
   2025 		throw("lost mcache")
   2026 	}
   2027 
   2028 	// Scheduler returned, so we're allowed to run now.
   2029 	// Delete the syscallsp information that we left for
   2030 	// the garbage collector during the system call.
   2031 	// Must wait until now because until gosched returns
   2032 	// we don't know for sure that the garbage collector
   2033 	// is not running.
   2034 	_g_.syscallsp = 0
   2035 	_g_.m.p.ptr().syscalltick++
   2036 	_g_.throwsplit = false
   2037 }
   2038 
   2039 //go:nosplit
   2040 func exitsyscallfast() bool {
   2041 	_g_ := getg()
   2042 
   2043 	// Freezetheworld sets stopwait but does not retake P's.
   2044 	if sched.stopwait == freezeStopWait {
   2045 		_g_.m.mcache = nil
   2046 		_g_.m.p = 0
   2047 		return false
   2048 	}
   2049 
   2050 	// Try to re-acquire the last P.
   2051 	if _g_.m.p != 0 && _g_.m.p.ptr().status == _Psyscall && cas(&_g_.m.p.ptr().status, _Psyscall, _Prunning) {
   2052 		// There's a cpu for us, so we can run.
   2053 		_g_.m.mcache = _g_.m.p.ptr().mcache
   2054 		_g_.m.p.ptr().m.set(_g_.m)
   2055 		if _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
   2056 			if trace.enabled {
   2057 				// The p was retaken and then enter into syscall again (since _g_.m.syscalltick has changed).
   2058 				// traceGoSysBlock for this syscall was already emitted,
   2059 				// but here we effectively retake the p from the new syscall running on the same p.
   2060 				systemstack(func() {
   2061 					// Denote blocking of the new syscall.
   2062 					traceGoSysBlock(_g_.m.p.ptr())
   2063 					// Denote completion of the current syscall.
   2064 					traceGoSysExit(tracestamp())
   2065 				})
   2066 			}
   2067 			_g_.m.p.ptr().syscalltick++
   2068 		}
   2069 		return true
   2070 	}
   2071 
   2072 	// Try to get any other idle P.
   2073 	oldp := _g_.m.p.ptr()
   2074 	_g_.m.mcache = nil
   2075 	_g_.m.p = 0
   2076 	if sched.pidle != 0 {
   2077 		var ok bool
   2078 		systemstack(func() {
   2079 			ok = exitsyscallfast_pidle()
   2080 			if ok && trace.enabled {
   2081 				if oldp != nil {
   2082 					// Wait till traceGoSysBlock event is emitted.
   2083 					// This ensures consistency of the trace (the goroutine is started after it is blocked).
   2084 					for oldp.syscalltick == _g_.m.syscalltick {
   2085 						osyield()
   2086 					}
   2087 				}
   2088 				traceGoSysExit(tracestamp())
   2089 			}
   2090 		})
   2091 		if ok {
   2092 			return true
   2093 		}
   2094 	}
   2095 	return false
   2096 }
   2097 
   2098 func exitsyscallfast_pidle() bool {
   2099 	lock(&sched.lock)
   2100 	_p_ := pidleget()
   2101 	if _p_ != nil && atomicload(&sched.sysmonwait) != 0 {
   2102 		atomicstore(&sched.sysmonwait, 0)
   2103 		notewakeup(&sched.sysmonnote)
   2104 	}
   2105 	unlock(&sched.lock)
   2106 	if _p_ != nil {
   2107 		acquirep(_p_)
   2108 		return true
   2109 	}
   2110 	return false
   2111 }
   2112 
   2113 // exitsyscall slow path on g0.
   2114 // Failed to acquire P, enqueue gp as runnable.
   2115 func exitsyscall0(gp *g) {
   2116 	_g_ := getg()
   2117 
   2118 	casgstatus(gp, _Gsyscall, _Grunnable)
   2119 	dropg()
   2120 	lock(&sched.lock)
   2121 	_p_ := pidleget()
   2122 	if _p_ == nil {
   2123 		globrunqput(gp)
   2124 	} else if atomicload(&sched.sysmonwait) != 0 {
   2125 		atomicstore(&sched.sysmonwait, 0)
   2126 		notewakeup(&sched.sysmonnote)
   2127 	}
   2128 	unlock(&sched.lock)
   2129 	if _p_ != nil {
   2130 		acquirep(_p_)
   2131 		execute(gp, false) // Never returns.
   2132 	}
   2133 	if _g_.m.lockedg != nil {
   2134 		// Wait until another thread schedules gp and so m again.
   2135 		stoplockedm()
   2136 		execute(gp, false) // Never returns.
   2137 	}
   2138 	stopm()
   2139 	schedule() // Never returns.
   2140 }
   2141 
   2142 func beforefork() {
   2143 	gp := getg().m.curg
   2144 
   2145 	// Fork can hang if preempted with signals frequently enough (see issue 5517).
   2146 	// Ensure that we stay on the same M where we disable profiling.
   2147 	gp.m.locks++
   2148 	if gp.m.profilehz != 0 {
   2149 		resetcpuprofiler(0)
   2150 	}
   2151 
   2152 	// This function is called before fork in syscall package.
   2153 	// Code between fork and exec must not allocate memory nor even try to grow stack.
   2154 	// Here we spoil g->_StackGuard to reliably detect any attempts to grow stack.
   2155 	// runtime_AfterFork will undo this in parent process, but not in child.
   2156 	gp.stackguard0 = stackFork
   2157 }
   2158 
   2159 // Called from syscall package before fork.
   2160 //go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork
   2161 //go:nosplit
   2162 func syscall_runtime_BeforeFork() {
   2163 	systemstack(beforefork)
   2164 }
   2165 
   2166 func afterfork() {
   2167 	gp := getg().m.curg
   2168 
   2169 	// See the comment in beforefork.
   2170 	gp.stackguard0 = gp.stack.lo + _StackGuard
   2171 
   2172 	hz := sched.profilehz
   2173 	if hz != 0 {
   2174 		resetcpuprofiler(hz)
   2175 	}
   2176 	gp.m.locks--
   2177 }
   2178 
   2179 // Called from syscall package after fork in parent.
   2180 //go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork
   2181 //go:nosplit
   2182 func syscall_runtime_AfterFork() {
   2183 	systemstack(afterfork)
   2184 }
   2185 
   2186 // Allocate a new g, with a stack big enough for stacksize bytes.
   2187 func malg(stacksize int32) *g {
   2188 	newg := new(g)
   2189 	if stacksize >= 0 {
   2190 		stacksize = round2(_StackSystem + stacksize)
   2191 		systemstack(func() {
   2192 			newg.stack, newg.stkbar = stackalloc(uint32(stacksize))
   2193 		})
   2194 		newg.stackguard0 = newg.stack.lo + _StackGuard
   2195 		newg.stackguard1 = ^uintptr(0)
   2196 		newg.stackAlloc = uintptr(stacksize)
   2197 	}
   2198 	return newg
   2199 }
   2200 
   2201 // Create a new g running fn with siz bytes of arguments.
   2202 // Put it on the queue of g's waiting to run.
   2203 // The compiler turns a go statement into a call to this.
   2204 // Cannot split the stack because it assumes that the arguments
   2205 // are available sequentially after &fn; they would not be
   2206 // copied if a stack split occurred.
   2207 //go:nosplit
   2208 func newproc(siz int32, fn *funcval) {
   2209 	argp := add(unsafe.Pointer(&fn), ptrSize)
   2210 	pc := getcallerpc(unsafe.Pointer(&siz))
   2211 	systemstack(func() {
   2212 		newproc1(fn, (*uint8)(argp), siz, 0, pc)
   2213 	})
   2214 }
   2215 
   2216 // Create a new g running fn with narg bytes of arguments starting
   2217 // at argp and returning nret bytes of results.  callerpc is the
   2218 // address of the go statement that created this.  The new g is put
   2219 // on the queue of g's waiting to run.
   2220 func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr) *g {
   2221 	_g_ := getg()
   2222 
   2223 	if fn == nil {
   2224 		_g_.m.throwing = -1 // do not dump full stacks
   2225 		throw("go of nil func value")
   2226 	}
   2227 	_g_.m.locks++ // disable preemption because it can be holding p in a local var
   2228 	siz := narg + nret
   2229 	siz = (siz + 7) &^ 7
   2230 
   2231 	// We could allocate a larger initial stack if necessary.
   2232 	// Not worth it: this is almost always an error.
   2233 	// 4*sizeof(uintreg): extra space added below
   2234 	// sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
   2235 	if siz >= _StackMin-4*regSize-regSize {
   2236 		throw("newproc: function arguments too large for new goroutine")
   2237 	}
   2238 
   2239 	_p_ := _g_.m.p.ptr()
   2240 	newg := gfget(_p_)
   2241 	if newg == nil {
   2242 		newg = malg(_StackMin)
   2243 		casgstatus(newg, _Gidle, _Gdead)
   2244 		allgadd(newg) // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
   2245 	}
   2246 	if newg.stack.hi == 0 {
   2247 		throw("newproc1: newg missing stack")
   2248 	}
   2249 
   2250 	if readgstatus(newg) != _Gdead {
   2251 		throw("newproc1: new g is not Gdead")
   2252 	}
   2253 
   2254 	totalSize := 4*regSize + uintptr(siz) // extra space in case of reads slightly beyond frame
   2255 	if hasLinkRegister {
   2256 		totalSize += ptrSize
   2257 	}
   2258 	totalSize += -totalSize & (spAlign - 1) // align to spAlign
   2259 	sp := newg.stack.hi - totalSize
   2260 	spArg := sp
   2261 	if hasLinkRegister {
   2262 		// caller's LR
   2263 		*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
   2264 		spArg += ptrSize
   2265 	}
   2266 	memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
   2267 
   2268 	memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
   2269 	newg.sched.sp = sp
   2270 	newg.sched.pc = funcPC(goexit) + _PCQuantum // +PCQuantum so that previous instruction is in same function
   2271 	newg.sched.g = guintptr(unsafe.Pointer(newg))
   2272 	gostartcallfn(&newg.sched, fn)
   2273 	newg.gopc = callerpc
   2274 	newg.startpc = fn.fn
   2275 	casgstatus(newg, _Gdead, _Grunnable)
   2276 
   2277 	if _p_.goidcache == _p_.goidcacheend {
   2278 		// Sched.goidgen is the last allocated id,
   2279 		// this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
   2280 		// At startup sched.goidgen=0, so main goroutine receives goid=1.
   2281 		_p_.goidcache = xadd64(&sched.goidgen, _GoidCacheBatch)
   2282 		_p_.goidcache -= _GoidCacheBatch - 1
   2283 		_p_.goidcacheend = _p_.goidcache + _GoidCacheBatch
   2284 	}
   2285 	newg.goid = int64(_p_.goidcache)
   2286 	_p_.goidcache++
   2287 	if raceenabled {
   2288 		newg.racectx = racegostart(callerpc)
   2289 	}
   2290 	if trace.enabled {
   2291 		traceGoCreate(newg, newg.startpc)
   2292 	}
   2293 	runqput(_p_, newg, true)
   2294 
   2295 	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
   2296 		wakep()
   2297 	}
   2298 	_g_.m.locks--
   2299 	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
   2300 		_g_.stackguard0 = stackPreempt
   2301 	}
   2302 	return newg
   2303 }
   2304 
   2305 // Put on gfree list.
   2306 // If local list is too long, transfer a batch to the global list.
   2307 func gfput(_p_ *p, gp *g) {
   2308 	if readgstatus(gp) != _Gdead {
   2309 		throw("gfput: bad status (not Gdead)")
   2310 	}
   2311 
   2312 	stksize := gp.stackAlloc
   2313 
   2314 	if stksize != _FixedStack {
   2315 		// non-standard stack size - free it.
   2316 		stackfree(gp.stack, gp.stackAlloc)
   2317 		gp.stack.lo = 0
   2318 		gp.stack.hi = 0
   2319 		gp.stackguard0 = 0
   2320 		gp.stkbar = nil
   2321 		gp.stkbarPos = 0
   2322 	} else {
   2323 		// Reset stack barriers.
   2324 		gp.stkbar = gp.stkbar[:0]
   2325 		gp.stkbarPos = 0
   2326 	}
   2327 
   2328 	gp.schedlink.set(_p_.gfree)
   2329 	_p_.gfree = gp
   2330 	_p_.gfreecnt++
   2331 	if _p_.gfreecnt >= 64 {
   2332 		lock(&sched.gflock)
   2333 		for _p_.gfreecnt >= 32 {
   2334 			_p_.gfreecnt--
   2335 			gp = _p_.gfree
   2336 			_p_.gfree = gp.schedlink.ptr()
   2337 			gp.schedlink.set(sched.gfree)
   2338 			sched.gfree = gp
   2339 			sched.ngfree++
   2340 		}
   2341 		unlock(&sched.gflock)
   2342 	}
   2343 }
   2344 
   2345 // Get from gfree list.
   2346 // If local list is empty, grab a batch from global list.
   2347 func gfget(_p_ *p) *g {
   2348 retry:
   2349 	gp := _p_.gfree
   2350 	if gp == nil && sched.gfree != nil {
   2351 		lock(&sched.gflock)
   2352 		for _p_.gfreecnt < 32 && sched.gfree != nil {
   2353 			_p_.gfreecnt++
   2354 			gp = sched.gfree
   2355 			sched.gfree = gp.schedlink.ptr()
   2356 			sched.ngfree--
   2357 			gp.schedlink.set(_p_.gfree)
   2358 			_p_.gfree = gp
   2359 		}
   2360 		unlock(&sched.gflock)
   2361 		goto retry
   2362 	}
   2363 	if gp != nil {
   2364 		_p_.gfree = gp.schedlink.ptr()
   2365 		_p_.gfreecnt--
   2366 		if gp.stack.lo == 0 {
   2367 			// Stack was deallocated in gfput.  Allocate a new one.
   2368 			systemstack(func() {
   2369 				gp.stack, gp.stkbar = stackalloc(_FixedStack)
   2370 			})
   2371 			gp.stackguard0 = gp.stack.lo + _StackGuard
   2372 			gp.stackAlloc = _FixedStack
   2373 		} else {
   2374 			if raceenabled {
   2375 				racemalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
   2376 			}
   2377 		}
   2378 	}
   2379 	return gp
   2380 }
   2381 
   2382 // Purge all cached G's from gfree list to the global list.
   2383 func gfpurge(_p_ *p) {
   2384 	lock(&sched.gflock)
   2385 	for _p_.gfreecnt != 0 {
   2386 		_p_.gfreecnt--
   2387 		gp := _p_.gfree
   2388 		_p_.gfree = gp.schedlink.ptr()
   2389 		gp.schedlink.set(sched.gfree)
   2390 		sched.gfree = gp
   2391 		sched.ngfree++
   2392 	}
   2393 	unlock(&sched.gflock)
   2394 }
   2395 
   2396 // Breakpoint executes a breakpoint trap.
   2397 func Breakpoint() {
   2398 	breakpoint()
   2399 }
   2400 
   2401 // dolockOSThread is called by LockOSThread and lockOSThread below
   2402 // after they modify m.locked. Do not allow preemption during this call,
   2403 // or else the m might be different in this function than in the caller.
   2404 //go:nosplit
   2405 func dolockOSThread() {
   2406 	_g_ := getg()
   2407 	_g_.m.lockedg = _g_
   2408 	_g_.lockedm = _g_.m
   2409 }
   2410 
   2411 //go:nosplit
   2412 
   2413 // LockOSThread wires the calling goroutine to its current operating system thread.
   2414 // Until the calling goroutine exits or calls UnlockOSThread, it will always
   2415 // execute in that thread, and no other goroutine can.
   2416 func LockOSThread() {
   2417 	getg().m.locked |= _LockExternal
   2418 	dolockOSThread()
   2419 }
   2420 
   2421 //go:nosplit
   2422 func lockOSThread() {
   2423 	getg().m.locked += _LockInternal
   2424 	dolockOSThread()
   2425 }
   2426 
   2427 // dounlockOSThread is called by UnlockOSThread and unlockOSThread below
   2428 // after they update m->locked. Do not allow preemption during this call,
   2429 // or else the m might be in different in this function than in the caller.
   2430 //go:nosplit
   2431 func dounlockOSThread() {
   2432 	_g_ := getg()
   2433 	if _g_.m.locked != 0 {
   2434 		return
   2435 	}
   2436 	_g_.m.lockedg = nil
   2437 	_g_.lockedm = nil
   2438 }
   2439 
   2440 //go:nosplit
   2441 
   2442 // UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
   2443 // If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
   2444 func UnlockOSThread() {
   2445 	getg().m.locked &^= _LockExternal
   2446 	dounlockOSThread()
   2447 }
   2448 
   2449 //go:nosplit
   2450 func unlockOSThread() {
   2451 	_g_ := getg()
   2452 	if _g_.m.locked < _LockInternal {
   2453 		systemstack(badunlockosthread)
   2454 	}
   2455 	_g_.m.locked -= _LockInternal
   2456 	dounlockOSThread()
   2457 }
   2458 
   2459 func badunlockosthread() {
   2460 	throw("runtime: internal error: misuse of lockOSThread/unlockOSThread")
   2461 }
   2462 
   2463 func gcount() int32 {
   2464 	n := int32(allglen) - sched.ngfree
   2465 	for i := 0; ; i++ {
   2466 		_p_ := allp[i]
   2467 		if _p_ == nil {
   2468 			break
   2469 		}
   2470 		n -= _p_.gfreecnt
   2471 	}
   2472 
   2473 	// All these variables can be changed concurrently, so the result can be inconsistent.
   2474 	// But at least the current goroutine is running.
   2475 	if n < 1 {
   2476 		n = 1
   2477 	}
   2478 	return n
   2479 }
   2480 
   2481 func mcount() int32 {
   2482 	return sched.mcount
   2483 }
   2484 
   2485 var prof struct {
   2486 	lock uint32
   2487 	hz   int32
   2488 }
   2489 
   2490 func _System()       { _System() }
   2491 func _ExternalCode() { _ExternalCode() }
   2492 func _GC()           { _GC() }
   2493 
   2494 // Called if we receive a SIGPROF signal.
   2495 func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
   2496 	if prof.hz == 0 {
   2497 		return
   2498 	}
   2499 
   2500 	// Profiling runs concurrently with GC, so it must not allocate.
   2501 	mp.mallocing++
   2502 
   2503 	// Coordinate with stack barrier insertion in scanstack.
   2504 	for !cas(&gp.stackLock, 0, 1) {
   2505 		osyield()
   2506 	}
   2507 
   2508 	// Define that a "user g" is a user-created goroutine, and a "system g"
   2509 	// is one that is m->g0 or m->gsignal.
   2510 	//
   2511 	// We might be interrupted for profiling halfway through a
   2512 	// goroutine switch. The switch involves updating three (or four) values:
   2513 	// g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
   2514 	// because once it gets updated the new g is running.
   2515 	//
   2516 	// When switching from a user g to a system g, LR is not considered live,
   2517 	// so the update only affects g, SP, and PC. Since PC must be last, there
   2518 	// the possible partial transitions in ordinary execution are (1) g alone is updated,
   2519 	// (2) both g and SP are updated, and (3) SP alone is updated.
   2520 	// If SP or g alone is updated, we can detect the partial transition by checking
   2521 	// whether the SP is within g's stack bounds. (We could also require that SP
   2522 	// be changed only after g, but the stack bounds check is needed by other
   2523 	// cases, so there is no need to impose an additional requirement.)
   2524 	//
   2525 	// There is one exceptional transition to a system g, not in ordinary execution.
   2526 	// When a signal arrives, the operating system starts the signal handler running
   2527 	// with an updated PC and SP. The g is updated last, at the beginning of the
   2528 	// handler. There are two reasons this is okay. First, until g is updated the
   2529 	// g and SP do not match, so the stack bounds check detects the partial transition.
   2530 	// Second, signal handlers currently run with signals disabled, so a profiling
   2531 	// signal cannot arrive during the handler.
   2532 	//
   2533 	// When switching from a system g to a user g, there are three possibilities.
   2534 	//
   2535 	// First, it may be that the g switch has no PC update, because the SP
   2536 	// either corresponds to a user g throughout (as in asmcgocall)
   2537 	// or because it has been arranged to look like a user g frame
   2538 	// (as in cgocallback_gofunc). In this case, since the entire
   2539 	// transition is a g+SP update, a partial transition updating just one of
   2540 	// those will be detected by the stack bounds check.
   2541 	//
   2542 	// Second, when returning from a signal handler, the PC and SP updates
   2543 	// are performed by the operating system in an atomic update, so the g
   2544 	// update must be done before them. The stack bounds check detects
   2545 	// the partial transition here, and (again) signal handlers run with signals
   2546 	// disabled, so a profiling signal cannot arrive then anyway.
   2547 	//
   2548 	// Third, the common case: it may be that the switch updates g, SP, and PC
   2549 	// separately. If the PC is within any of the functions that does this,
   2550 	// we don't ask for a traceback. C.F. the function setsSP for more about this.
   2551 	//
   2552 	// There is another apparently viable approach, recorded here in case
   2553 	// the "PC within setsSP function" check turns out not to be usable.
   2554 	// It would be possible to delay the update of either g or SP until immediately
   2555 	// before the PC update instruction. Then, because of the stack bounds check,
   2556 	// the only problematic interrupt point is just before that PC update instruction,
   2557 	// and the sigprof handler can detect that instruction and simulate stepping past
   2558 	// it in order to reach a consistent state. On ARM, the update of g must be made
   2559 	// in two places (in R10 and also in a TLS slot), so the delayed update would
   2560 	// need to be the SP update. The sigprof handler must read the instruction at
   2561 	// the current PC and if it was the known instruction (for example, JMP BX or
   2562 	// MOV R2, PC), use that other register in place of the PC value.
   2563 	// The biggest drawback to this solution is that it requires that we can tell
   2564 	// whether it's safe to read from the memory pointed at by PC.
   2565 	// In a correct program, we can test PC == nil and otherwise read,
   2566 	// but if a profiling signal happens at the instant that a program executes
   2567 	// a bad jump (before the program manages to handle the resulting fault)
   2568 	// the profiling handler could fault trying to read nonexistent memory.
   2569 	//
   2570 	// To recap, there are no constraints on the assembly being used for the
   2571 	// transition. We simply require that g and SP match and that the PC is not
   2572 	// in gogo.
   2573 	traceback := true
   2574 	if gp == nil || sp < gp.stack.lo || gp.stack.hi < sp || setsSP(pc) {
   2575 		traceback = false
   2576 	}
   2577 	var stk [maxCPUProfStack]uintptr
   2578 	n := 0
   2579 	if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 {
   2580 		// Cgo, we can't unwind and symbolize arbitrary C code,
   2581 		// so instead collect Go stack that leads to the cgo call.
   2582 		// This is especially important on windows, since all syscalls are cgo calls.
   2583 		n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0)
   2584 	} else if traceback {
   2585 		n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack)
   2586 	}
   2587 	if !traceback || n <= 0 {
   2588 		// Normal traceback is impossible or has failed.
   2589 		// See if it falls into several common cases.
   2590 		n = 0
   2591 		if GOOS == "windows" && n == 0 && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
   2592 			// Libcall, i.e. runtime syscall on windows.
   2593 			// Collect Go stack that leads to the call.
   2594 			n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)
   2595 		}
   2596 		if n == 0 {
   2597 			// If all of the above has failed, account it against abstract "System" or "GC".
   2598 			n = 2
   2599 			// "ExternalCode" is better than "etext".
   2600 			if pc > firstmoduledata.etext {
   2601 				pc = funcPC(_ExternalCode) + _PCQuantum
   2602 			}
   2603 			stk[0] = pc
   2604 			if mp.preemptoff != "" || mp.helpgc != 0 {
   2605 				stk[1] = funcPC(_GC) + _PCQuantum
   2606 			} else {
   2607 				stk[1] = funcPC(_System) + _PCQuantum
   2608 			}
   2609 		}
   2610 	}
   2611 	atomicstore(&gp.stackLock, 0)
   2612 
   2613 	if prof.hz != 0 {
   2614 		// Simple cas-lock to coordinate with setcpuprofilerate.
   2615 		for !cas(&prof.lock, 0, 1) {
   2616 			osyield()
   2617 		}
   2618 		if prof.hz != 0 {
   2619 			cpuprof.add(stk[:n])
   2620 		}
   2621 		atomicstore(&prof.lock, 0)
   2622 	}
   2623 	mp.mallocing--
   2624 }
   2625 
   2626 // Reports whether a function will set the SP
   2627 // to an absolute value. Important that
   2628 // we don't traceback when these are at the bottom
   2629 // of the stack since we can't be sure that we will
   2630 // find the caller.
   2631 //
   2632 // If the function is not on the bottom of the stack
   2633 // we assume that it will have set it up so that traceback will be consistent,
   2634 // either by being a traceback terminating function
   2635 // or putting one on the stack at the right offset.
   2636 func setsSP(pc uintptr) bool {
   2637 	f := findfunc(pc)
   2638 	if f == nil {
   2639 		// couldn't find the function for this PC,
   2640 		// so assume the worst and stop traceback
   2641 		return true
   2642 	}
   2643 	switch f.entry {
   2644 	case gogoPC, systemstackPC, mcallPC, morestackPC:
   2645 		return true
   2646 	}
   2647 	return false
   2648 }
   2649 
   2650 // Arrange to call fn with a traceback hz times a second.
   2651 func setcpuprofilerate_m(hz int32) {
   2652 	// Force sane arguments.
   2653 	if hz < 0 {
   2654 		hz = 0
   2655 	}
   2656 
   2657 	// Disable preemption, otherwise we can be rescheduled to another thread
   2658 	// that has profiling enabled.
   2659 	_g_ := getg()
   2660 	_g_.m.locks++
   2661 
   2662 	// Stop profiler on this thread so that it is safe to lock prof.
   2663 	// if a profiling signal came in while we had prof locked,
   2664 	// it would deadlock.
   2665 	resetcpuprofiler(0)
   2666 
   2667 	for !cas(&prof.lock, 0, 1) {
   2668 		osyield()
   2669 	}
   2670 	prof.hz = hz
   2671 	atomicstore(&prof.lock, 0)
   2672 
   2673 	lock(&sched.lock)
   2674 	sched.profilehz = hz
   2675 	unlock(&sched.lock)
   2676 
   2677 	if hz != 0 {
   2678 		resetcpuprofiler(hz)
   2679 	}
   2680 
   2681 	_g_.m.locks--
   2682 }
   2683 
   2684 // Change number of processors.  The world is stopped, sched is locked.
   2685 // gcworkbufs are not being modified by either the GC or
   2686 // the write barrier code.
   2687 // Returns list of Ps with local work, they need to be scheduled by the caller.
   2688 func procresize(nprocs int32) *p {
   2689 	old := gomaxprocs
   2690 	if old < 0 || old > _MaxGomaxprocs || nprocs <= 0 || nprocs > _MaxGomaxprocs {
   2691 		throw("procresize: invalid arg")
   2692 	}
   2693 	if trace.enabled {
   2694 		traceGomaxprocs(nprocs)
   2695 	}
   2696 
   2697 	// update statistics
   2698 	now := nanotime()
   2699 	if sched.procresizetime != 0 {
   2700 		sched.totaltime += int64(old) * (now - sched.procresizetime)
   2701 	}
   2702 	sched.procresizetime = now
   2703 
   2704 	// initialize new P's
   2705 	for i := int32(0); i < nprocs; i++ {
   2706 		pp := allp[i]
   2707 		if pp == nil {
   2708 			pp = new(p)
   2709 			pp.id = i
   2710 			pp.status = _Pgcstop
   2711 			pp.sudogcache = pp.sudogbuf[:0]
   2712 			for i := range pp.deferpool {
   2713 				pp.deferpool[i] = pp.deferpoolbuf[i][:0]
   2714 			}
   2715 			atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
   2716 		}
   2717 		if pp.mcache == nil {
   2718 			if old == 0 && i == 0 {
   2719 				if getg().m.mcache == nil {
   2720 					throw("missing mcache?")
   2721 				}
   2722 				pp.mcache = getg().m.mcache // bootstrap
   2723 			} else {
   2724 				pp.mcache = allocmcache()
   2725 			}
   2726 		}
   2727 	}
   2728 
   2729 	// free unused P's
   2730 	for i := nprocs; i < old; i++ {
   2731 		p := allp[i]
   2732 		if trace.enabled {
   2733 			if p == getg().m.p.ptr() {
   2734 				// moving to p[0], pretend that we were descheduled
   2735 				// and then scheduled again to keep the trace sane.
   2736 				traceGoSched()
   2737 				traceProcStop(p)
   2738 			}
   2739 		}
   2740 		// move all runnable goroutines to the global queue
   2741 		for p.runqhead != p.runqtail {
   2742 			// pop from tail of local queue
   2743 			p.runqtail--
   2744 			gp := p.runq[p.runqtail%uint32(len(p.runq))]
   2745 			// push onto head of global queue
   2746 			globrunqputhead(gp)
   2747 		}
   2748 		if p.runnext != 0 {
   2749 			globrunqputhead(p.runnext.ptr())
   2750 			p.runnext = 0
   2751 		}
   2752 		// if there's a background worker, make it runnable and put
   2753 		// it on the global queue so it can clean itself up
   2754 		if p.gcBgMarkWorker != nil {
   2755 			casgstatus(p.gcBgMarkWorker, _Gwaiting, _Grunnable)
   2756 			if trace.enabled {
   2757 				traceGoUnpark(p.gcBgMarkWorker, 0)
   2758 			}
   2759 			globrunqput(p.gcBgMarkWorker)
   2760 			p.gcBgMarkWorker = nil
   2761 		}
   2762 		for i := range p.sudogbuf {
   2763 			p.sudogbuf[i] = nil
   2764 		}
   2765 		p.sudogcache = p.sudogbuf[:0]
   2766 		for i := range p.deferpool {
   2767 			for j := range p.deferpoolbuf[i] {
   2768 				p.deferpoolbuf[i][j] = nil
   2769 			}
   2770 			p.deferpool[i] = p.deferpoolbuf[i][:0]
   2771 		}
   2772 		freemcache(p.mcache)
   2773 		p.mcache = nil
   2774 		gfpurge(p)
   2775 		traceProcFree(p)
   2776 		p.status = _Pdead
   2777 		// can't free P itself because it can be referenced by an M in syscall
   2778 	}
   2779 
   2780 	_g_ := getg()
   2781 	if _g_.m.p != 0 && _g_.m.p.ptr().id < nprocs {
   2782 		// continue to use the current P
   2783 		_g_.m.p.ptr().status = _Prunning
   2784 	} else {
   2785 		// release the current P and acquire allp[0]
   2786 		if _g_.m.p != 0 {
   2787 			_g_.m.p.ptr().m = 0
   2788 		}
   2789 		_g_.m.p = 0
   2790 		_g_.m.mcache = nil
   2791 		p := allp[0]
   2792 		p.m = 0
   2793 		p.status = _Pidle
   2794 		acquirep(p)
   2795 		if trace.enabled {
   2796 			traceGoStart()
   2797 		}
   2798 	}
   2799 	var runnablePs *p
   2800 	for i := nprocs - 1; i >= 0; i-- {
   2801 		p := allp[i]
   2802 		if _g_.m.p.ptr() == p {
   2803 			continue
   2804 		}
   2805 		p.status = _Pidle
   2806 		if runqempty(p) {
   2807 			pidleput(p)
   2808 		} else {
   2809 			p.m.set(mget())
   2810 			p.link.set(runnablePs)
   2811 			runnablePs = p
   2812 		}
   2813 	}
   2814 	var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
   2815 	atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
   2816 	return runnablePs
   2817 }
   2818 
   2819 // Associate p and the current m.
   2820 func acquirep(_p_ *p) {
   2821 	acquirep1(_p_)
   2822 
   2823 	// have p; write barriers now allowed
   2824 	_g_ := getg()
   2825 	_g_.m.mcache = _p_.mcache
   2826 
   2827 	if trace.enabled {
   2828 		traceProcStart()
   2829 	}
   2830 }
   2831 
   2832 // May run during STW, so write barriers are not allowed.
   2833 //go:nowritebarrier
   2834 func acquirep1(_p_ *p) {
   2835 	_g_ := getg()
   2836 
   2837 	if _g_.m.p != 0 || _g_.m.mcache != nil {
   2838 		throw("acquirep: already in go")
   2839 	}
   2840 	if _p_.m != 0 || _p_.status != _Pidle {
   2841 		id := int32(0)
   2842 		if _p_.m != 0 {
   2843 			id = _p_.m.ptr().id
   2844 		}
   2845 		print("acquirep: p->m=", _p_.m, "(", id, ") p->status=", _p_.status, "\n")
   2846 		throw("acquirep: invalid p state")
   2847 	}
   2848 	_g_.m.p.set(_p_)
   2849 	_p_.m.set(_g_.m)
   2850 	_p_.status = _Prunning
   2851 }
   2852 
   2853 // Disassociate p and the current m.
   2854 func releasep() *p {
   2855 	_g_ := getg()
   2856 
   2857 	if _g_.m.p == 0 || _g_.m.mcache == nil {
   2858 		throw("releasep: invalid arg")
   2859 	}
   2860 	_p_ := _g_.m.p.ptr()
   2861 	if _p_.m.ptr() != _g_.m || _p_.mcache != _g_.m.mcache || _p_.status != _Prunning {
   2862 		print("releasep: m=", _g_.m, " m->p=", _g_.m.p.ptr(), " p->m=", _p_.m, " m->mcache=", _g_.m.mcache, " p->mcache=", _p_.mcache, " p->status=", _p_.status, "\n")
   2863 		throw("releasep: invalid p state")
   2864 	}
   2865 	if trace.enabled {
   2866 		traceProcStop(_g_.m.p.ptr())
   2867 	}
   2868 	_g_.m.p = 0
   2869 	_g_.m.mcache = nil
   2870 	_p_.m = 0
   2871 	_p_.status = _Pidle
   2872 	return _p_
   2873 }
   2874 
   2875 func incidlelocked(v int32) {
   2876 	lock(&sched.lock)
   2877 	sched.nmidlelocked += v
   2878 	if v > 0 {
   2879 		checkdead()
   2880 	}
   2881 	unlock(&sched.lock)
   2882 }
   2883 
   2884 // Check for deadlock situation.
   2885 // The check is based on number of running M's, if 0 -> deadlock.
   2886 func checkdead() {
   2887 	// For -buildmode=c-shared or -buildmode=c-archive it's OK if
   2888 	// there are no running goroutines.  The calling program is
   2889 	// assumed to be running.
   2890 	if islibrary || isarchive {
   2891 		return
   2892 	}
   2893 
   2894 	// If we are dying because of a signal caught on an already idle thread,
   2895 	// freezetheworld will cause all running threads to block.
   2896 	// And runtime will essentially enter into deadlock state,
   2897 	// except that there is a thread that will call exit soon.
   2898 	if panicking > 0 {
   2899 		return
   2900 	}
   2901 
   2902 	// -1 for sysmon
   2903 	run := sched.mcount - sched.nmidle - sched.nmidlelocked - 1
   2904 	if run > 0 {
   2905 		return
   2906 	}
   2907 	if run < 0 {
   2908 		print("runtime: checkdead: nmidle=", sched.nmidle, " nmidlelocked=", sched.nmidlelocked, " mcount=", sched.mcount, "\n")
   2909 		throw("checkdead: inconsistent counts")
   2910 	}
   2911 
   2912 	grunning := 0
   2913 	lock(&allglock)
   2914 	for i := 0; i < len(allgs); i++ {
   2915 		gp := allgs[i]
   2916 		if isSystemGoroutine(gp) {
   2917 			continue
   2918 		}
   2919 		s := readgstatus(gp)
   2920 		switch s &^ _Gscan {
   2921 		case _Gwaiting:
   2922 			grunning++
   2923 		case _Grunnable,
   2924 			_Grunning,
   2925 			_Gsyscall:
   2926 			unlock(&allglock)
   2927 			print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
   2928 			throw("checkdead: runnable g")
   2929 		}
   2930 	}
   2931 	unlock(&allglock)
   2932 	if grunning == 0 { // possible if main goroutine calls runtimeGoexit()
   2933 		throw("no goroutines (main called runtime.Goexit) - deadlock!")
   2934 	}
   2935 
   2936 	// Maybe jump time forward for playground.
   2937 	gp := timejump()
   2938 	if gp != nil {
   2939 		casgstatus(gp, _Gwaiting, _Grunnable)
   2940 		globrunqput(gp)
   2941 		_p_ := pidleget()
   2942 		if _p_ == nil {
   2943 			throw("checkdead: no p for timer")
   2944 		}
   2945 		mp := mget()
   2946 		if mp == nil {
   2947 			newm(nil, _p_)
   2948 		} else {
   2949 			mp.nextp.set(_p_)
   2950 			notewakeup(&mp.park)
   2951 		}
   2952 		return
   2953 	}
   2954 
   2955 	getg().m.throwing = -1 // do not dump full stacks
   2956 	throw("all goroutines are asleep - deadlock!")
   2957 }
   2958 
   2959 func sysmon() {
   2960 	// If we go two minutes without a garbage collection, force one to run.
   2961 	forcegcperiod := int64(2 * 60 * 1e9)
   2962 
   2963 	// If a heap span goes unused for 5 minutes after a garbage collection,
   2964 	// we hand it back to the operating system.
   2965 	scavengelimit := int64(5 * 60 * 1e9)
   2966 
   2967 	if debug.scavenge > 0 {
   2968 		// Scavenge-a-lot for testing.
   2969 		forcegcperiod = 10 * 1e6
   2970 		scavengelimit = 20 * 1e6
   2971 	}
   2972 
   2973 	lastscavenge := nanotime()
   2974 	nscavenge := 0
   2975 
   2976 	// Make wake-up period small enough for the sampling to be correct.
   2977 	maxsleep := forcegcperiod / 2
   2978 	if scavengelimit < forcegcperiod {
   2979 		maxsleep = scavengelimit / 2
   2980 	}
   2981 
   2982 	lasttrace := int64(0)
   2983 	idle := 0 // how many cycles in succession we had not wokeup somebody
   2984 	delay := uint32(0)
   2985 	for {
   2986 		if idle == 0 { // start with 20us sleep...
   2987 			delay = 20
   2988 		} else if idle > 50 { // start doubling the sleep after 1ms...
   2989 			delay *= 2
   2990 		}
   2991 		if delay > 10*1000 { // up to 10ms
   2992 			delay = 10 * 1000
   2993 		}
   2994 		usleep(delay)
   2995 		if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
   2996 			lock(&sched.lock)
   2997 			if atomicload(&sched.gcwaiting) != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs) {
   2998 				atomicstore(&sched.sysmonwait, 1)
   2999 				unlock(&sched.lock)
   3000 				notetsleep(&sched.sysmonnote, maxsleep)
   3001 				lock(&sched.lock)
   3002 				atomicstore(&sched.sysmonwait, 0)
   3003 				noteclear(&sched.sysmonnote)
   3004 				idle = 0
   3005 				delay = 20
   3006 			}
   3007 			unlock(&sched.lock)
   3008 		}
   3009 		// poll network if not polled for more than 10ms
   3010 		lastpoll := int64(atomicload64(&sched.lastpoll))
   3011 		now := nanotime()
   3012 		unixnow := unixnanotime()
   3013 		if lastpoll != 0 && lastpoll+10*1000*1000 < now {
   3014 			cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
   3015 			gp := netpoll(false) // non-blocking - returns list of goroutines
   3016 			if gp != nil {
   3017 				// Need to decrement number of idle locked M's
   3018 				// (pretending that one more is running) before injectglist.
   3019 				// Otherwise it can lead to the following situation:
   3020 				// injectglist grabs all P's but before it starts M's to run the P's,
   3021 				// another M returns from syscall, finishes running its G,
   3022 				// observes that there is no work to do and no other running M's
   3023 				// and reports deadlock.
   3024 				incidlelocked(-1)
   3025 				injectglist(gp)
   3026 				incidlelocked(1)
   3027 			}
   3028 		}
   3029 		// retake P's blocked in syscalls
   3030 		// and preempt long running G's
   3031 		if retake(now) != 0 {
   3032 			idle = 0
   3033 		} else {
   3034 			idle++
   3035 		}
   3036 		// check if we need to force a GC
   3037 		lastgc := int64(atomicload64(&memstats.last_gc))
   3038 		if lastgc != 0 && unixnow-lastgc > forcegcperiod && atomicload(&forcegc.idle) != 0 && atomicloaduint(&bggc.working) == 0 {
   3039 			lock(&forcegc.lock)
   3040 			forcegc.idle = 0
   3041 			forcegc.g.schedlink = 0
   3042 			injectglist(forcegc.g)
   3043 			unlock(&forcegc.lock)
   3044 		}
   3045 		// scavenge heap once in a while
   3046 		if lastscavenge+scavengelimit/2 < now {
   3047 			mHeap_Scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
   3048 			lastscavenge = now
   3049 			nscavenge++
   3050 		}
   3051 		if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace*1000000) <= now {
   3052 			lasttrace = now
   3053 			schedtrace(debug.scheddetail > 0)
   3054 		}
   3055 	}
   3056 }
   3057 
   3058 var pdesc [_MaxGomaxprocs]struct {
   3059 	schedtick   uint32
   3060 	schedwhen   int64
   3061 	syscalltick uint32
   3062 	syscallwhen int64
   3063 }
   3064 
   3065 // forcePreemptNS is the time slice given to a G before it is
   3066 // preempted.
   3067 const forcePreemptNS = 10 * 1000 * 1000 // 10ms
   3068 
   3069 func retake(now int64) uint32 {
   3070 	n := 0
   3071 	for i := int32(0); i < gomaxprocs; i++ {
   3072 		_p_ := allp[i]
   3073 		if _p_ == nil {
   3074 			continue
   3075 		}
   3076 		pd := &pdesc[i]
   3077 		s := _p_.status
   3078 		if s == _Psyscall {
   3079 			// Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
   3080 			t := int64(_p_.syscalltick)
   3081 			if int64(pd.syscalltick) != t {
   3082 				pd.syscalltick = uint32(t)
   3083 				pd.syscallwhen = now
   3084 				continue
   3085 			}
   3086 			// On the one hand we don't want to retake Ps if there is no other work to do,
   3087 			// but on the other hand we want to retake them eventually
   3088 			// because they can prevent the sysmon thread from deep sleep.
   3089 			if runqempty(_p_) && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
   3090 				continue
   3091 			}
   3092 			// Need to decrement number of idle locked M's
   3093 			// (pretending that one more is running) before the CAS.
   3094 			// Otherwise the M from which we retake can exit the syscall,
   3095 			// increment nmidle and report deadlock.
   3096 			incidlelocked(-1)
   3097 			if cas(&_p_.status, s, _Pidle) {
   3098 				if trace.enabled {
   3099 					traceGoSysBlock(_p_)
   3100 					traceProcStop(_p_)
   3101 				}
   3102 				n++
   3103 				_p_.syscalltick++
   3104 				handoffp(_p_)
   3105 			}
   3106 			incidlelocked(1)
   3107 		} else if s == _Prunning {
   3108 			// Preempt G if it's running for too long.
   3109 			t := int64(_p_.schedtick)
   3110 			if int64(pd.schedtick) != t {
   3111 				pd.schedtick = uint32(t)
   3112 				pd.schedwhen = now
   3113 				continue
   3114 			}
   3115 			if pd.schedwhen+forcePreemptNS > now {
   3116 				continue
   3117 			}
   3118 			preemptone(_p_)
   3119 		}
   3120 	}
   3121 	return uint32(n)
   3122 }
   3123 
   3124 // Tell all goroutines that they have been preempted and they should stop.
   3125 // This function is purely best-effort.  It can fail to inform a goroutine if a
   3126 // processor just started running it.
   3127 // No locks need to be held.
   3128 // Returns true if preemption request was issued to at least one goroutine.
   3129 func preemptall() bool {
   3130 	res := false
   3131 	for i := int32(0); i < gomaxprocs; i++ {
   3132 		_p_ := allp[i]
   3133 		if _p_ == nil || _p_.status != _Prunning {
   3134 			continue
   3135 		}
   3136 		if preemptone(_p_) {
   3137 			res = true
   3138 		}
   3139 	}
   3140 	return res
   3141 }
   3142 
   3143 // Tell the goroutine running on processor P to stop.
   3144 // This function is purely best-effort.  It can incorrectly fail to inform the
   3145 // goroutine.  It can send inform the wrong goroutine.  Even if it informs the
   3146 // correct goroutine, that goroutine might ignore the request if it is
   3147 // simultaneously executing newstack.
   3148 // No lock needs to be held.
   3149 // Returns true if preemption request was issued.
   3150 // The actual preemption will happen at some point in the future
   3151 // and will be indicated by the gp->status no longer being
   3152 // Grunning
   3153 func preemptone(_p_ *p) bool {
   3154 	mp := _p_.m.ptr()
   3155 	if mp == nil || mp == getg().m {
   3156 		return false
   3157 	}
   3158 	gp := mp.curg
   3159 	if gp == nil || gp == mp.g0 {
   3160 		return false
   3161 	}
   3162 
   3163 	gp.preempt = true
   3164 
   3165 	// Every call in a go routine checks for stack overflow by
   3166 	// comparing the current stack pointer to gp->stackguard0.
   3167 	// Setting gp->stackguard0 to StackPreempt folds
   3168 	// preemption into the normal stack overflow check.
   3169 	gp.stackguard0 = stackPreempt
   3170 	return true
   3171 }
   3172 
   3173 var starttime int64
   3174 
   3175 func schedtrace(detailed bool) {
   3176 	now := nanotime()
   3177 	if starttime == 0 {
   3178 		starttime = now
   3179 	}
   3180 
   3181 	lock(&sched.lock)
   3182 	print("SCHED ", (now-starttime)/1e6, "ms: gomaxprocs=", gomaxprocs, " idleprocs=", sched.npidle, " threads=", sched.mcount, " spinningthreads=", sched.nmspinning, " idlethreads=", sched.nmidle, " runqueue=", sched.runqsize)
   3183 	if detailed {
   3184 		print(" gcwaiting=", sched.gcwaiting, " nmidlelocked=", sched.nmidlelocked, " stopwait=", sched.stopwait, " sysmonwait=", sched.sysmonwait, "\n")
   3185 	}
   3186 	// We must be careful while reading data from P's, M's and G's.
   3187 	// Even if we hold schedlock, most data can be changed concurrently.
   3188 	// E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
   3189 	for i := int32(0); i < gomaxprocs; i++ {
   3190 		_p_ := allp[i]
   3191 		if _p_ == nil {
   3192 			continue
   3193 		}
   3194 		mp := _p_.m.ptr()
   3195 		h := atomicload(&_p_.runqhead)
   3196 		t := atomicload(&_p_.runqtail)
   3197 		if detailed {
   3198 			id := int32(-1)
   3199 			if mp != nil {
   3200 				id = mp.id
   3201 			}
   3202 			print("  P", i, ": status=", _p_.status, " schedtick=", _p_.schedtick, " syscalltick=", _p_.syscalltick, " m=", id, " runqsize=", t-h, " gfreecnt=", _p_.gfreecnt, "\n")
   3203 		} else {
   3204 			// In non-detailed mode format lengths of per-P run queues as:
   3205 			// [len1 len2 len3 len4]
   3206 			print(" ")
   3207 			if i == 0 {
   3208 				print("[")
   3209 			}
   3210 			print(t - h)
   3211 			if i == gomaxprocs-1 {
   3212 				print("]\n")
   3213 			}
   3214 		}
   3215 	}
   3216 
   3217 	if !detailed {
   3218 		unlock(&sched.lock)
   3219 		return
   3220 	}
   3221 
   3222 	for mp := allm; mp != nil; mp = mp.alllink {
   3223 		_p_ := mp.p.ptr()
   3224 		gp := mp.curg
   3225 		lockedg := mp.lockedg
   3226 		id1 := int32(-1)
   3227 		if _p_ != nil {
   3228 			id1 = _p_.id
   3229 		}
   3230 		id2 := int64(-1)
   3231 		if gp != nil {
   3232 			id2 = gp.goid
   3233 		}
   3234 		id3 := int64(-1)
   3235 		if lockedg != nil {
   3236 			id3 = lockedg.goid
   3237 		}
   3238 		print("  M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
   3239 	}
   3240 
   3241 	lock(&allglock)
   3242 	for gi := 0; gi < len(allgs); gi++ {
   3243 		gp := allgs[gi]
   3244 		mp := gp.m
   3245 		lockedm := gp.lockedm
   3246 		id1 := int32(-1)
   3247 		if mp != nil {
   3248 			id1 = mp.id
   3249 		}
   3250 		id2 := int32(-1)
   3251 		if lockedm != nil {
   3252 			id2 = lockedm.id
   3253 		}
   3254 		print("  G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason, ") m=", id1, " lockedm=", id2, "\n")
   3255 	}
   3256 	unlock(&allglock)
   3257 	unlock(&sched.lock)
   3258 }
   3259 
   3260 // Put mp on midle list.
   3261 // Sched must be locked.
   3262 // May run during STW, so write barriers are not allowed.
   3263 //go:nowritebarrier
   3264 func mput(mp *m) {
   3265 	mp.schedlink = sched.midle
   3266 	sched.midle.set(mp)
   3267 	sched.nmidle++
   3268 	checkdead()
   3269 }
   3270 
   3271 // Try to get an m from midle list.
   3272 // Sched must be locked.
   3273 // May run during STW, so write barriers are not allowed.
   3274 //go:nowritebarrier
   3275 func mget() *m {
   3276 	mp := sched.midle.ptr()
   3277 	if mp != nil {
   3278 		sched.midle = mp.schedlink
   3279 		sched.nmidle--
   3280 	}
   3281 	return mp
   3282 }
   3283 
   3284 // Put gp on the global runnable queue.
   3285 // Sched must be locked.
   3286 // May run during STW, so write barriers are not allowed.
   3287 //go:nowritebarrier
   3288 func globrunqput(gp *g) {
   3289 	gp.schedlink = 0
   3290 	if sched.runqtail != 0 {
   3291 		sched.runqtail.ptr().schedlink.set(gp)
   3292 	} else {
   3293 		sched.runqhead.set(gp)
   3294 	}
   3295 	sched.runqtail.set(gp)
   3296 	sched.runqsize++
   3297 }
   3298 
   3299 // Put gp at the head of the global runnable queue.
   3300 // Sched must be locked.
   3301 // May run during STW, so write barriers are not allowed.
   3302 //go:nowritebarrier
   3303 func globrunqputhead(gp *g) {
   3304 	gp.schedlink = sched.runqhead
   3305 	sched.runqhead.set(gp)
   3306 	if sched.runqtail == 0 {
   3307 		sched.runqtail.set(gp)
   3308 	}
   3309 	sched.runqsize++
   3310 }
   3311 
   3312 // Put a batch of runnable goroutines on the global runnable queue.
   3313 // Sched must be locked.
   3314 func globrunqputbatch(ghead *g, gtail *g, n int32) {
   3315 	gtail.schedlink = 0
   3316 	if sched.runqtail != 0 {
   3317 		sched.runqtail.ptr().schedlink.set(ghead)
   3318 	} else {
   3319 		sched.runqhead.set(ghead)
   3320 	}
   3321 	sched.runqtail.set(gtail)
   3322 	sched.runqsize += n
   3323 }
   3324 
   3325 // Try get a batch of G's from the global runnable queue.
   3326 // Sched must be locked.
   3327 func globrunqget(_p_ *p, max int32) *g {
   3328 	if sched.runqsize == 0 {
   3329 		return nil
   3330 	}
   3331 
   3332 	n := sched.runqsize/gomaxprocs + 1
   3333 	if n > sched.runqsize {
   3334 		n = sched.runqsize
   3335 	}
   3336 	if max > 0 && n > max {
   3337 		n = max
   3338 	}
   3339 	if n > int32(len(_p_.runq))/2 {
   3340 		n = int32(len(_p_.runq)) / 2
   3341 	}
   3342 
   3343 	sched.runqsize -= n
   3344 	if sched.runqsize == 0 {
   3345 		sched.runqtail = 0
   3346 	}
   3347 
   3348 	gp := sched.runqhead.ptr()
   3349 	sched.runqhead = gp.schedlink
   3350 	n--
   3351 	for ; n > 0; n-- {
   3352 		gp1 := sched.runqhead.ptr()
   3353 		sched.runqhead = gp1.schedlink
   3354 		runqput(_p_, gp1, false)
   3355 	}
   3356 	return gp
   3357 }
   3358 
   3359 // Put p to on _Pidle list.
   3360 // Sched must be locked.
   3361 // May run during STW, so write barriers are not allowed.
   3362 //go:nowritebarrier
   3363 func pidleput(_p_ *p) {
   3364 	if !runqempty(_p_) {
   3365 		throw("pidleput: P has non-empty run queue")
   3366 	}
   3367 	_p_.link = sched.pidle
   3368 	sched.pidle.set(_p_)
   3369 	xadd(&sched.npidle, 1) // TODO: fast atomic
   3370 }
   3371 
   3372 // Try get a p from _Pidle list.
   3373 // Sched must be locked.
   3374 // May run during STW, so write barriers are not allowed.
   3375 //go:nowritebarrier
   3376 func pidleget() *p {
   3377 	_p_ := sched.pidle.ptr()
   3378 	if _p_ != nil {
   3379 		sched.pidle = _p_.link
   3380 		xadd(&sched.npidle, -1) // TODO: fast atomic
   3381 	}
   3382 	return _p_
   3383 }
   3384 
   3385 // runqempty returns true if _p_ has no Gs on its local run queue.
   3386 // Note that this test is generally racy.
   3387 func runqempty(_p_ *p) bool {
   3388 	return _p_.runqhead == _p_.runqtail && _p_.runnext == 0
   3389 }
   3390 
   3391 // To shake out latent assumptions about scheduling order,
   3392 // we introduce some randomness into scheduling decisions
   3393 // when running with the race detector.
   3394 // The need for this was made obvious by changing the
   3395 // (deterministic) scheduling order in Go 1.5 and breaking
   3396 // many poorly-written tests.
   3397 // With the randomness here, as long as the tests pass
   3398 // consistently with -race, they shouldn't have latent scheduling
   3399 // assumptions.
   3400 const randomizeScheduler = raceenabled
   3401 
   3402 // runqput tries to put g on the local runnable queue.
   3403 // If next if false, runqput adds g to the tail of the runnable queue.
   3404 // If next is true, runqput puts g in the _p_.runnext slot.
   3405 // If the run queue is full, runnext puts g on the global queue.
   3406 // Executed only by the owner P.
   3407 func runqput(_p_ *p, gp *g, next bool) {
   3408 	if randomizeScheduler && next && fastrand1()%2 == 0 {
   3409 		next = false
   3410 	}
   3411 
   3412 	if next {
   3413 	retryNext:
   3414 		oldnext := _p_.runnext
   3415 		if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
   3416 			goto retryNext
   3417 		}
   3418 		if oldnext == 0 {
   3419 			return
   3420 		}
   3421 		// Kick the old runnext out to the regular run queue.
   3422 		gp = oldnext.ptr()
   3423 	}
   3424 
   3425 retry:
   3426 	h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
   3427 	t := _p_.runqtail
   3428 	if t-h < uint32(len(_p_.runq)) {
   3429 		_p_.runq[t%uint32(len(_p_.runq))] = gp
   3430 		atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
   3431 		return
   3432 	}
   3433 	if runqputslow(_p_, gp, h, t) {
   3434 		return
   3435 	}
   3436 	// the queue is not full, now the put above must suceed
   3437 	goto retry
   3438 }
   3439 
   3440 // Put g and a batch of work from local runnable queue on global queue.
   3441 // Executed only by the owner P.
   3442 func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
   3443 	var batch [len(_p_.runq)/2 + 1]*g
   3444 
   3445 	// First, grab a batch from local queue.
   3446 	n := t - h
   3447 	n = n / 2
   3448 	if n != uint32(len(_p_.runq)/2) {
   3449 		throw("runqputslow: queue is not full")
   3450 	}
   3451 	for i := uint32(0); i < n; i++ {
   3452 		batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
   3453 	}
   3454 	if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
   3455 		return false
   3456 	}
   3457 	batch[n] = gp
   3458 
   3459 	if randomizeScheduler {
   3460 		for i := uint32(1); i <= n; i++ {
   3461 			j := fastrand1() % (i + 1)
   3462 			batch[i], batch[j] = batch[j], batch[i]
   3463 		}
   3464 	}
   3465 
   3466 	// Link the goroutines.
   3467 	for i := uint32(0); i < n; i++ {
   3468 		batch[i].schedlink.set(batch[i+1])
   3469 	}
   3470 
   3471 	// Now put the batch on global queue.
   3472 	lock(&sched.lock)
   3473 	globrunqputbatch(batch[0], batch[n], int32(n+1))
   3474 	unlock(&sched.lock)
   3475 	return true
   3476 }
   3477 
   3478 // Get g from local runnable queue.
   3479 // If inheritTime is true, gp should inherit the remaining time in the
   3480 // current time slice. Otherwise, it should start a new time slice.
   3481 // Executed only by the owner P.
   3482 func runqget(_p_ *p) (gp *g, inheritTime bool) {
   3483 	// If there's a runnext, it's the next G to run.
   3484 	for {
   3485 		next := _p_.runnext
   3486 		if next == 0 {
   3487 			break
   3488 		}
   3489 		if _p_.runnext.cas(next, 0) {
   3490 			return next.ptr(), true
   3491 		}
   3492 	}
   3493 
   3494 	for {
   3495 		h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
   3496 		t := _p_.runqtail
   3497 		if t == h {
   3498 			return nil, false
   3499 		}
   3500 		gp := _p_.runq[h%uint32(len(_p_.runq))]
   3501 		if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
   3502 			return gp, false
   3503 		}
   3504 	}
   3505 }
   3506 
   3507 // Grabs a batch of goroutines from _p_'s runnable queue into batch.
   3508 // Batch is a ring buffer starting at batchHead.
   3509 // Returns number of grabbed goroutines.
   3510 // Can be executed by any P.
   3511 func runqgrab(_p_ *p, batch *[256]*g, batchHead uint32, stealRunNextG bool) uint32 {
   3512 	for {
   3513 		h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
   3514 		t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
   3515 		n := t - h
   3516 		n = n - n/2
   3517 		if n == 0 {
   3518 			if stealRunNextG {
   3519 				// Try to steal from _p_.runnext.
   3520 				if next := _p_.runnext; next != 0 {
   3521 					// Sleep to ensure that _p_ isn't about to run the g we
   3522 					// are about to steal.
   3523 					// The important use case here is when the g running on _p_
   3524 					// ready()s another g and then almost immediately blocks.
   3525 					// Instead of stealing runnext in this window, back off
   3526 					// to give _p_ a chance to schedule runnext. This will avoid
   3527 					// thrashing gs between different Ps.
   3528 					usleep(100)
   3529 					if !_p_.runnext.cas(next, 0) {
   3530 						continue
   3531 					}
   3532 					batch[batchHead%uint32(len(batch))] = next.ptr()
   3533 					return 1
   3534 				}
   3535 			}
   3536 			return 0
   3537 		}
   3538 		if n > uint32(len(_p_.runq)/2) { // read inconsistent h and t
   3539 			continue
   3540 		}
   3541 		for i := uint32(0); i < n; i++ {
   3542 			g := _p_.runq[(h+i)%uint32(len(_p_.runq))]
   3543 			batch[(batchHead+i)%uint32(len(batch))] = g
   3544 		}
   3545 		if cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
   3546 			return n
   3547 		}
   3548 	}
   3549 }
   3550 
   3551 // Steal half of elements from local runnable queue of p2
   3552 // and put onto local runnable queue of p.
   3553 // Returns one of the stolen elements (or nil if failed).
   3554 func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
   3555 	t := _p_.runqtail
   3556 	n := runqgrab(p2, &_p_.runq, t, stealRunNextG)
   3557 	if n == 0 {
   3558 		return nil
   3559 	}
   3560 	n--
   3561 	gp := _p_.runq[(t+n)%uint32(len(_p_.runq))]
   3562 	if n == 0 {
   3563 		return gp
   3564 	}
   3565 	h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
   3566 	if t-h+n >= uint32(len(_p_.runq)) {
   3567 		throw("runqsteal: runq overflow")
   3568 	}
   3569 	atomicstore(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
   3570 	return gp
   3571 }
   3572 
   3573 func testSchedLocalQueue() {
   3574 	_p_ := new(p)
   3575 	gs := make([]g, len(_p_.runq))
   3576 	for i := 0; i < len(_p_.runq); i++ {
   3577 		if g, _ := runqget(_p_); g != nil {
   3578 			throw("runq is not empty initially")
   3579 		}
   3580 		for j := 0; j < i; j++ {
   3581 			runqput(_p_, &gs[i], false)
   3582 		}
   3583 		for j := 0; j < i; j++ {
   3584 			if g, _ := runqget(_p_); g != &gs[i] {
   3585 				print("bad element at iter ", i, "/", j, "\n")
   3586 				throw("bad element")
   3587 			}
   3588 		}
   3589 		if g, _ := runqget(_p_); g != nil {
   3590 			throw("runq is not empty afterwards")
   3591 		}
   3592 	}
   3593 }
   3594 
   3595 func testSchedLocalQueueSteal() {
   3596 	p1 := new(p)
   3597 	p2 := new(p)
   3598 	gs := make([]g, len(p1.runq))
   3599 	for i := 0; i < len(p1.runq); i++ {
   3600 		for j := 0; j < i; j++ {
   3601 			gs[j].sig = 0
   3602 			runqput(p1, &gs[j], false)
   3603 		}
   3604 		gp := runqsteal(p2, p1, true)
   3605 		s := 0
   3606 		if gp != nil {
   3607 			s++
   3608 			gp.sig++
   3609 		}
   3610 		for {
   3611 			gp, _ = runqget(p2)
   3612 			if gp == nil {
   3613 				break
   3614 			}
   3615 			s++
   3616 			gp.sig++
   3617 		}
   3618 		for {
   3619 			gp, _ = runqget(p1)
   3620 			if gp == nil {
   3621 				break
   3622 			}
   3623 			gp.sig++
   3624 		}
   3625 		for j := 0; j < i; j++ {
   3626 			if gs[j].sig != 1 {
   3627 				print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n")
   3628 				throw("bad element")
   3629 			}
   3630 		}
   3631 		if s != i/2 && s != i/2+1 {
   3632 			print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n")
   3633 			throw("bad steal")
   3634 		}
   3635 	}
   3636 }
   3637 
   3638 func setMaxThreads(in int) (out int) {
   3639 	lock(&sched.lock)
   3640 	out = int(sched.maxmcount)
   3641 	sched.maxmcount = int32(in)
   3642 	checkmcount()
   3643 	unlock(&sched.lock)
   3644 	return
   3645 }
   3646 
   3647 func haveexperiment(name string) bool {
   3648 	x := goexperiment
   3649 	for x != "" {
   3650 		xname := ""
   3651 		i := index(x, ",")
   3652 		if i < 0 {
   3653 			xname, x = x, ""
   3654 		} else {
   3655 			xname, x = x[:i], x[i+1:]
   3656 		}
   3657 		if xname == name {
   3658 			return true
   3659 		}
   3660 	}
   3661 	return false
   3662 }
   3663 
   3664 //go:nosplit
   3665 func procPin() int {
   3666 	_g_ := getg()
   3667 	mp := _g_.m
   3668 
   3669 	mp.locks++
   3670 	return int(mp.p.ptr().id)
   3671 }
   3672 
   3673 //go:nosplit
   3674 func procUnpin() {
   3675 	_g_ := getg()
   3676 	_g_.m.locks--
   3677 }
   3678 
   3679 //go:linkname sync_runtime_procPin sync.runtime_procPin
   3680 //go:nosplit
   3681 func sync_runtime_procPin() int {
   3682 	return procPin()
   3683 }
   3684 
   3685 //go:linkname sync_runtime_procUnpin sync.runtime_procUnpin
   3686 //go:nosplit
   3687 func sync_runtime_procUnpin() {
   3688 	procUnpin()
   3689 }
   3690 
   3691 //go:linkname sync_atomic_runtime_procPin sync/atomic.runtime_procPin
   3692 //go:nosplit
   3693 func sync_atomic_runtime_procPin() int {
   3694 	return procPin()
   3695 }
   3696 
   3697 //go:linkname sync_atomic_runtime_procUnpin sync/atomic.runtime_procUnpin
   3698 //go:nosplit
   3699 func sync_atomic_runtime_procUnpin() {
   3700 	procUnpin()
   3701 }
   3702 
   3703 // Active spinning for sync.Mutex.
   3704 //go:linkname sync_runtime_canSpin sync.runtime_canSpin
   3705 //go:nosplit
   3706 func sync_runtime_canSpin(i int) bool {
   3707 	// sync.Mutex is cooperative, so we are conservative with spinning.
   3708 	// Spin only few times and only if running on a multicore machine and
   3709 	// GOMAXPROCS>1 and there is at least one other running P and local runq is empty.
   3710 	// As opposed to runtime mutex we don't do passive spinning here,
   3711 	// because there can be work on global runq on on other Ps.
   3712 	if i >= active_spin || ncpu <= 1 || gomaxprocs <= int32(sched.npidle+sched.nmspinning)+1 {
   3713 		return false
   3714 	}
   3715 	if p := getg().m.p.ptr(); !runqempty(p) {
   3716 		return false
   3717 	}
   3718 	return true
   3719 }
   3720 
   3721 //go:linkname sync_runtime_doSpin sync.runtime_doSpin
   3722 //go:nosplit
   3723 func sync_runtime_doSpin() {
   3724 	procyield(active_spin_cnt)
   3725 }
   3726