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