Source file
src/runtime/os_linux.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/sys"
9 "unsafe"
10 )
11
12 type mOS struct{}
13
14
15 func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
16
17
18
19
20
21
22
23
24
25
26 const (
27 _FUTEX_WAIT = 0
28 _FUTEX_WAKE = 1
29 )
30
31
32
33
34
35
36 func futexsleep(addr *uint32, val uint32, ns int64) {
37 var ts timespec
38
39
40
41
42
43
44 if ns < 0 {
45 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
46 return
47 }
48
49
50
51
52
53
54
55 if sys.PtrSize == 8 {
56 ts.set_sec(ns / 1000000000)
57 ts.set_nsec(int32(ns % 1000000000))
58 } else {
59 ts.tv_nsec = 0
60 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
61 }
62 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
63 }
64
65
66
67 func futexwakeup(addr *uint32, cnt uint32) {
68 ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
69 if ret >= 0 {
70 return
71 }
72
73
74
75
76 systemstack(func() {
77 print("futexwakeup addr=", addr, " returned ", ret, "\n")
78 })
79
80 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
81 }
82
83 func getproccount() int32 {
84
85
86
87
88
89
90
91 const maxCPUs = 64 * 1024
92 var buf [maxCPUs / 8]byte
93 r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
94 if r < 0 {
95 return 1
96 }
97 n := int32(0)
98 for _, v := range buf[:r] {
99 for v != 0 {
100 n += int32(v & 1)
101 v >>= 1
102 }
103 }
104 if n == 0 {
105 n = 1
106 }
107 return n
108 }
109
110
111 const (
112 _CLONE_VM = 0x100
113 _CLONE_FS = 0x200
114 _CLONE_FILES = 0x400
115 _CLONE_SIGHAND = 0x800
116 _CLONE_PTRACE = 0x2000
117 _CLONE_VFORK = 0x4000
118 _CLONE_PARENT = 0x8000
119 _CLONE_THREAD = 0x10000
120 _CLONE_NEWNS = 0x20000
121 _CLONE_SYSVSEM = 0x40000
122 _CLONE_SETTLS = 0x80000
123 _CLONE_PARENT_SETTID = 0x100000
124 _CLONE_CHILD_CLEARTID = 0x200000
125 _CLONE_UNTRACED = 0x800000
126 _CLONE_CHILD_SETTID = 0x1000000
127 _CLONE_STOPPED = 0x2000000
128 _CLONE_NEWUTS = 0x4000000
129 _CLONE_NEWIPC = 0x8000000
130
131 cloneFlags = _CLONE_VM |
132 _CLONE_FS |
133 _CLONE_FILES |
134 _CLONE_SIGHAND |
135 _CLONE_SYSVSEM |
136 _CLONE_THREAD
137 )
138
139
140 func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32
141
142
143
144 func newosproc(mp *m, stk unsafe.Pointer) {
145
148 if false {
149 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n")
150 }
151
152
153
154 var oset sigset
155 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
156 ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
157 sigprocmask(_SIG_SETMASK, &oset, nil)
158
159 if ret < 0 {
160 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
161 if ret == -_EAGAIN {
162 println("runtime: may need to increase max user processes (ulimit -u)")
163 }
164 throw("newosproc")
165 }
166 }
167
168
169
170 func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
171 stack := sysAlloc(stacksize, &memstats.stacks_sys)
172 if stack == nil {
173 write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
174 exit(1)
175 }
176 ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn)
177 if ret < 0 {
178 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
179 exit(1)
180 }
181 }
182
183 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
184 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
185
186 const (
187 _AT_NULL = 0
188 _AT_PAGESZ = 6
189 _AT_HWCAP = 16
190 _AT_RANDOM = 25
191 _AT_HWCAP2 = 26
192 )
193
194 var procAuxv = []byte("/proc/self/auxv\x00")
195
196 func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
197
198 func sysargs(argc int32, argv **byte) {
199 n := argc + 1
200
201
202 for argv_index(argv, n) != nil {
203 n++
204 }
205
206
207 n++
208
209
210 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
211 if sysauxv(auxv[:]) != 0 {
212 return
213 }
214
215
216
217 fd := open(&procAuxv[0], 0 , 0)
218 if fd < 0 {
219
220
221
222 const size = 256 << 10
223 p, err := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
224 if err != 0 {
225 return
226 }
227 var n uintptr
228 for n = 4 << 10; n < size; n <<= 1 {
229 err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0])
230 if err == 0 {
231 physPageSize = n
232 break
233 }
234 }
235 if physPageSize == 0 {
236 physPageSize = size
237 }
238 munmap(p, size)
239 return
240 }
241 var buf [128]uintptr
242 n = read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
243 closefd(fd)
244 if n < 0 {
245 return
246 }
247
248
249 buf[len(buf)-2] = _AT_NULL
250 sysauxv(buf[:])
251 }
252
253 func sysauxv(auxv []uintptr) int {
254 var i int
255 for ; auxv[i] != _AT_NULL; i += 2 {
256 tag, val := auxv[i], auxv[i+1]
257 switch tag {
258 case _AT_RANDOM:
259
260
261 startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:]
262
263 case _AT_PAGESZ:
264 physPageSize = val
265 }
266
267 archauxv(tag, val)
268 }
269 return i / 2
270 }
271
272 func osinit() {
273 ncpu = getproccount()
274 }
275
276 var urandom_dev = []byte("/dev/urandom\x00")
277
278 func getRandomData(r []byte) {
279 if startupRandomData != nil {
280 n := copy(r, startupRandomData)
281 extendRandom(r, n)
282 return
283 }
284 fd := open(&urandom_dev[0], 0 , 0)
285 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
286 closefd(fd)
287 extendRandom(r, int(n))
288 }
289
290 func goenvs() {
291 goenvs_unix()
292 }
293
294
295
296
297
298
299 func libpreinit() {
300 initsig(true)
301 }
302
303
304
305 func mpreinit(mp *m) {
306 mp.gsignal = malg(32 * 1024)
307 mp.gsignal.m = mp
308 }
309
310 func gettid() uint32
311
312
313
314 func minit() {
315 minitSignals()
316
317
318 getg().m.procid = uint64(gettid())
319 }
320
321
322
323 func unminit() {
324 unminitSignals()
325 }
326
327 func memlimit() uintptr {
328
355
356 return 0
357 }
358
359
360
361
362
363 func sigreturn()
364 func sigtramp(sig uint32, info *siginfo, ctx unsafe.Pointer)
365 func cgoSigtramp()
366
367
368 func sigaltstack(new, old *stackt)
369
370
371 func setitimer(mode int32, new, old *itimerval)
372
373
374 func rtsigprocmask(how int32, new, old *sigset, size int32)
375
376
377
378 func sigprocmask(how int32, new, old *sigset) {
379 rtsigprocmask(how, new, old, int32(unsafe.Sizeof(*new)))
380 }
381
382
383 func getrlimit(kind int32, limit unsafe.Pointer) int32
384 func raise(sig uint32)
385 func raiseproc(sig uint32)
386
387
388 func sched_getaffinity(pid, len uintptr, buf *byte) int32
389 func osyield()
390
391
392
393 func setsig(i uint32, fn uintptr) {
394 var sa sigactiont
395 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER | _SA_RESTART
396 sigfillset(&sa.sa_mask)
397
398
399
400 if GOARCH == "386" || GOARCH == "amd64" {
401 sa.sa_restorer = funcPC(sigreturn)
402 }
403 if fn == funcPC(sighandler) {
404 if iscgo {
405 fn = funcPC(cgoSigtramp)
406 } else {
407 fn = funcPC(sigtramp)
408 }
409 }
410 sa.sa_handler = fn
411 rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
412 }
413
414
415
416 func setsigstack(i uint32) {
417 var sa sigactiont
418 rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask))
419 if sa.sa_flags&_SA_ONSTACK != 0 {
420 return
421 }
422 sa.sa_flags |= _SA_ONSTACK
423 rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
424 }
425
426
427
428 func getsig(i uint32) uintptr {
429 var sa sigactiont
430 if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
431 throw("rt_sigaction read failure")
432 }
433 return sa.sa_handler
434 }
435
436
437
438 func setSignalstackSP(s *stackt, sp uintptr) {
439 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
440 }
441
442 func (c *sigctxt) fixsigcode(sig uint32) {
443 }
444
View as plain text