1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
13 // The main goroutine.
17 // Racectx of m0->g0 is used only as the parent of the main goroutine.
18 // It must not be used for anything else.
21 // Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
22 // Using decimal instead of binary GB and MB because
23 // they look nicer in the stack overflow failure message.
25 maxstacksize = 1000000000
27 maxstacksize = 250000000
30 systemstack(newsysmon)
32 // Lock the main goroutine onto this, the main OS thread,
33 // during initialization. Most programs won't care, but a few
34 // do require certain calls to be made by the main thread.
35 // Those can arrange for main.main to run in the main thread
36 // by calling runtime.LockOSThread during initialization
37 // to preserve the lock.
41 gothrow("runtime.main not on m0")
44 runtime_init() // must be before defer
46 // Defer unlock so that runtime.Goexit during init does the unlock too.
54 memstats.enablegc = true // now that runtime is initialized, GC is okay
57 if _cgo_thread_start == nil {
58 gothrow("_cgo_thread_start missing")
60 if _cgo_malloc == nil {
61 gothrow("_cgo_malloc missing")
64 gothrow("_cgo_free missing")
66 if GOOS != "windows" {
67 if _cgo_setenv == nil {
68 gothrow("_cgo_setenv missing")
70 if _cgo_unsetenv == nil {
71 gothrow("_cgo_unsetenv missing")
86 // Make racy client program work: if panicking on
87 // another goroutine at the same time as main returns,
88 // let the other goroutine finish printing the panic trace.
89 // Once it does, it will exit. See issue 3934.
91 gopark(nil, nil, "panicwait")
101 // start forcegc helper goroutine
106 func forcegchelper() {
108 forcegc.g.issystem = true
111 if forcegc.idle != 0 {
112 gothrow("forcegc: phase error")
114 atomicstore(&forcegc.idle, 1)
115 goparkunlock(&forcegc.lock, "force gc (idle)")
116 // this goroutine is explicitly resumed by sysmon
117 if debug.gctrace > 0 {
126 // Gosched yields the processor, allowing other goroutines to run. It does not
127 // suspend the current goroutine, so execution resumes automatically.
132 // Puts the current goroutine into a waiting state and calls unlockf.
133 // If unlockf returns false, the goroutine is resumed.
134 func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
137 status := readgstatus(gp)
138 if status != _Grunning && status != _Gscanrunning {
139 gothrow("gopark: bad g status")
142 mp.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
143 gp.waitreason = reason
145 // can't do anything that might move the G between Ms here.
149 // Puts the current goroutine into a waiting state and unlocks the lock.
150 // The goroutine can be made runnable again by calling goready(gp).
151 func goparkunlock(lock *mutex, reason string) {
152 gopark(parkunlock_c, unsafe.Pointer(lock), reason)
155 func goready(gp *g) {
162 func acquireSudog() *sudog {
167 gothrow("acquireSudog: found s.elem != nil in cache")
169 c.sudogcache = s.next
174 // Delicate dance: the semaphore implementation calls
175 // acquireSudog, acquireSudog calls new(sudog),
176 // new calls malloc, malloc can call the garbage collector,
177 // and the garbage collector calls the semaphore implementation
179 // Break the cycle by doing acquirem/releasem around new(sudog).
180 // The acquirem/releasem increments m.locks during new(sudog),
181 // which keeps the garbage collector from being invoked.
185 gothrow("acquireSudog: found p.elem != nil after new")
192 func releaseSudog(s *sudog) {
194 gothrow("runtime: sudog with non-nil elem")
196 if s.selectdone != nil {
197 gothrow("runtime: sudog with non-nil selectdone")
200 gothrow("runtime: sudog with non-nil next")
203 gothrow("runtime: sudog with non-nil prev")
205 if s.waitlink != nil {
206 gothrow("runtime: sudog with non-nil waitlink")
210 gothrow("runtime: releaseSudog with non-nil gp.param")
213 s.next = c.sudogcache
217 // funcPC returns the entry PC of the function f.
218 // It assumes that f is a func value. Otherwise the behavior is undefined.
220 func funcPC(f interface{}) uintptr {
221 return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
224 // called from assembly
225 func badmcall(fn func(*g)) {
226 gothrow("runtime: mcall called on m->g0 stack")
229 func badmcall2(fn func(*g)) {
230 gothrow("runtime: mcall function returned")
233 func badreflectcall() {
234 panic("runtime: arg size to reflect.call more than 1GB")
237 func lockedOSThread() bool {
239 return gp.lockedm != nil && gp.m.lockedg != nil
259 func allgadd(gp *g) {
260 if readgstatus(gp) == _Gidle {
261 gothrow("allgadd: bad status Gidle")
265 allgs = append(allgs, gp)
267 allglen = uintptr(len(allgs))