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