]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/proc.go
[dev.garbage] all: merge dev.cc into dev.garbage
[gostls13.git] / src / runtime / proc.go
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package runtime
6
7 import "unsafe"
8
9 func runtime_init()
10 func main_init()
11 func main_main()
12
13 // The main goroutine.
14 func main() {
15         g := getg()
16
17         // Racectx of m0->g0 is used only as the parent of the main goroutine.
18         // It must not be used for anything else.
19         g.m.g0.racectx = 0
20
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.
24         if ptrSize == 8 {
25                 maxstacksize = 1000000000
26         } else {
27                 maxstacksize = 250000000
28         }
29
30         systemstack(newsysmon)
31
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.
38         lockOSThread()
39
40         if g.m != &m0 {
41                 gothrow("runtime.main not on m0")
42         }
43
44         runtime_init() // must be before defer
45
46         // Defer unlock so that runtime.Goexit during init does the unlock too.
47         needUnlock := true
48         defer func() {
49                 if needUnlock {
50                         unlockOSThread()
51                 }
52         }()
53
54         memstats.enablegc = true // now that runtime is initialized, GC is okay
55
56         if iscgo {
57                 if _cgo_thread_start == nil {
58                         gothrow("_cgo_thread_start missing")
59                 }
60                 if _cgo_malloc == nil {
61                         gothrow("_cgo_malloc missing")
62                 }
63                 if _cgo_free == nil {
64                         gothrow("_cgo_free missing")
65                 }
66                 if _cgo_setenv == nil {
67                         gothrow("_cgo_setenv missing")
68                 }
69                 if _cgo_unsetenv == nil {
70                         gothrow("_cgo_unsetenv missing")
71                 }
72         }
73
74         main_init()
75
76         needUnlock = false
77         unlockOSThread()
78
79         main_main()
80         if raceenabled {
81                 racefini()
82         }
83
84         // Make racy client program work: if panicking on
85         // another goroutine at the same time as main returns,
86         // let the other goroutine finish printing the panic trace.
87         // Once it does, it will exit. See issue 3934.
88         if panicking != 0 {
89                 gopark(nil, nil, "panicwait")
90         }
91
92         exit(0)
93         for {
94                 var x *int32
95                 *x = 0
96         }
97 }
98
99 // start forcegc helper goroutine
100 func init() {
101         go forcegchelper()
102 }
103
104 func forcegchelper() {
105         forcegc.g = getg()
106         forcegc.g.issystem = true
107         for {
108                 lock(&forcegc.lock)
109                 if forcegc.idle != 0 {
110                         gothrow("forcegc: phase error")
111                 }
112                 atomicstore(&forcegc.idle, 1)
113                 goparkunlock(&forcegc.lock, "force gc (idle)")
114                 // this goroutine is explicitly resumed by sysmon
115                 if debug.gctrace > 0 {
116                         println("GC forced")
117                 }
118                 gogc(1)
119         }
120 }
121
122 //go:nosplit
123
124 // Gosched yields the processor, allowing other goroutines to run.  It does not
125 // suspend the current goroutine, so execution resumes automatically.
126 func Gosched() {
127         mcall(gosched_m)
128 }
129
130 // Puts the current goroutine into a waiting state and calls unlockf.
131 // If unlockf returns false, the goroutine is resumed.
132 func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
133         mp := acquirem()
134         gp := mp.curg
135         status := readgstatus(gp)
136         if status != _Grunning && status != _Gscanrunning {
137                 gothrow("gopark: bad g status")
138         }
139         mp.waitlock = lock
140         mp.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
141         gp.waitreason = reason
142         releasem(mp)
143         // can't do anything that might move the G between Ms here.
144         mcall(park_m)
145 }
146
147 // Puts the current goroutine into a waiting state and unlocks the lock.
148 // The goroutine can be made runnable again by calling goready(gp).
149 func goparkunlock(lock *mutex, reason string) {
150         gopark(parkunlock_c, unsafe.Pointer(lock), reason)
151 }
152
153 func goready(gp *g) {
154         systemstack(func() {
155                 ready(gp)
156         })
157 }
158
159 //go:nosplit
160 func acquireSudog() *sudog {
161         c := gomcache()
162         s := c.sudogcache
163         if s != nil {
164                 if s.elem != nil {
165                         gothrow("acquireSudog: found s.elem != nil in cache")
166                 }
167                 c.sudogcache = s.next
168                 return s
169         }
170
171         // Delicate dance: the semaphore implementation calls
172         // acquireSudog, acquireSudog calls new(sudog),
173         // new calls malloc, malloc can call the garbage collector,
174         // and the garbage collector calls the semaphore implementation
175         // in stoptheworld.
176         // Break the cycle by doing acquirem/releasem around new(sudog).
177         // The acquirem/releasem increments m.locks during new(sudog),
178         // which keeps the garbage collector from being invoked.
179         mp := acquirem()
180         p := new(sudog)
181         if p.elem != nil {
182                 gothrow("acquireSudog: found p.elem != nil after new")
183         }
184         releasem(mp)
185         return p
186 }
187
188 //go:nosplit
189 func releaseSudog(s *sudog) {
190         if s.elem != nil {
191                 gothrow("runtime: sudog with non-nil elem")
192         }
193         if s.selectdone != nil {
194                 gothrow("runtime: sudog with non-nil selectdone")
195         }
196         gp := getg()
197         if gp.param != nil {
198                 gothrow("runtime: releaseSudog with non-nil gp.param")
199         }
200         c := gomcache()
201         s.next = c.sudogcache
202         c.sudogcache = s
203 }
204
205 // funcPC returns the entry PC of the function f.
206 // It assumes that f is a func value. Otherwise the behavior is undefined.
207 //go:nosplit
208 func funcPC(f interface{}) uintptr {
209         return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
210 }
211
212 // called from assembly
213 func badmcall(fn func(*g)) {
214         gothrow("runtime: mcall called on m->g0 stack")
215 }
216
217 func badmcall2(fn func(*g)) {
218         gothrow("runtime: mcall function returned")
219 }
220
221 func badreflectcall() {
222         panic("runtime: arg size to reflect.call more than 1GB")
223 }
224
225 func lockedOSThread() bool {
226         gp := getg()
227         return gp.lockedm != nil && gp.m.lockedg != nil
228 }
229
230 func newP() *p {
231         return new(p)
232 }
233
234 func newM() *m {
235         return new(m)
236 }
237
238 func newG() *g {
239         return new(g)
240 }
241
242 var (
243         allgs    []*g
244         allglock mutex
245 )
246
247 func allgadd(gp *g) {
248         if readgstatus(gp) == _Gidle {
249                 gothrow("allgadd: bad status Gidle")
250         }
251
252         lock(&allglock)
253         allgs = append(allgs, gp)
254         allg = &allgs[0]
255         allglen = uintptr(len(allgs))
256         unlock(&allglock)
257 }