Source file
src/runtime/os_darwin.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/stringslite"
10 "unsafe"
11 )
12
13 type mOS struct {
14 initialized bool
15 mutex pthreadmutex
16 cond pthreadcond
17 count int
18 }
19
20 func unimplemented(name string) {
21 println(name, "not implemented")
22 *(*int)(unsafe.Pointer(uintptr(1231))) = 1231
23 }
24
25
26 func semacreate(mp *m) {
27 if mp.initialized {
28 return
29 }
30 mp.initialized = true
31 if err := pthread_mutex_init(&mp.mutex, nil); err != 0 {
32 throw("pthread_mutex_init")
33 }
34 if err := pthread_cond_init(&mp.cond, nil); err != 0 {
35 throw("pthread_cond_init")
36 }
37 }
38
39
40 func semasleep(ns int64) int32 {
41 var start int64
42 if ns >= 0 {
43 start = nanotime()
44 }
45 g := getg()
46 mp := g.m
47 if g == mp.gsignal {
48
49 throw("semasleep on Darwin signal stack")
50 }
51 pthread_mutex_lock(&mp.mutex)
52 for {
53 if mp.count > 0 {
54 mp.count--
55 pthread_mutex_unlock(&mp.mutex)
56 return 0
57 }
58 if ns >= 0 {
59 spent := nanotime() - start
60 if spent >= ns {
61 pthread_mutex_unlock(&mp.mutex)
62 return -1
63 }
64 var t timespec
65 t.setNsec(ns - spent)
66 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
67 if err == _ETIMEDOUT {
68 pthread_mutex_unlock(&mp.mutex)
69 return -1
70 }
71 } else {
72 pthread_cond_wait(&mp.cond, &mp.mutex)
73 }
74 }
75 }
76
77
78 func semawakeup(mp *m) {
79 if g := getg(); g == g.m.gsignal {
80 throw("semawakeup on Darwin signal stack")
81 }
82 pthread_mutex_lock(&mp.mutex)
83 mp.count++
84 if mp.count > 0 {
85 pthread_cond_signal(&mp.cond)
86 }
87 pthread_mutex_unlock(&mp.mutex)
88 }
89
90
91 var sigNoteRead, sigNoteWrite int32
92
93
94
95
96
97
98
99
100
101
102
103 func sigNoteSetup(*note) {
104 if sigNoteRead != 0 || sigNoteWrite != 0 {
105
106 throw("duplicate sigNoteSetup")
107 }
108 var errno int32
109 sigNoteRead, sigNoteWrite, errno = pipe()
110 if errno != 0 {
111 throw("pipe failed")
112 }
113 closeonexec(sigNoteRead)
114 closeonexec(sigNoteWrite)
115
116
117
118
119
120 setNonblock(sigNoteWrite)
121 }
122
123
124 func sigNoteWakeup(*note) {
125 var b byte
126 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
127 }
128
129
130 func sigNoteSleep(*note) {
131 for {
132 var b byte
133 entersyscallblock()
134 n := read(sigNoteRead, unsafe.Pointer(&b), 1)
135 exitsyscall()
136 if n != -_EINTR {
137 return
138 }
139 }
140 }
141
142
143 func osinit() {
144
145
146
147 numCPUStartup = getCPUCount()
148 physPageSize = getPageSize()
149
150 osinit_hack()
151 initWorkingDir()
152 }
153
154 func sysctlbynameInt32(name []byte) (int32, int32) {
155 out := int32(0)
156 nout := unsafe.Sizeof(out)
157 ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
158 return ret, out
159 }
160
161 func sysctlbynameBytes(name, out []byte) int32 {
162 nout := uintptr(len(out))
163 ret := sysctlbyname(&name[0], &out[0], &nout, nil, 0)
164 return ret
165 }
166
167
168 func internal_cpu_sysctlbynameInt32(name []byte) (int32, int32) {
169 return sysctlbynameInt32(name)
170 }
171
172
173 func internal_cpu_sysctlbynameBytes(name, out []byte) int32 {
174 return sysctlbynameBytes(name, out)
175 }
176
177 const (
178 _CTL_HW = 6
179 _HW_NCPU = 3
180 _HW_PAGESIZE = 7
181 )
182
183 func getCPUCount() int32 {
184
185 mib := [2]uint32{_CTL_HW, _HW_NCPU}
186 out := uint32(0)
187 nout := unsafe.Sizeof(out)
188 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
189 if ret >= 0 && int32(out) > 0 {
190 return int32(out)
191 }
192 return 1
193 }
194
195 func getPageSize() uintptr {
196
197 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
198 out := uint32(0)
199 nout := unsafe.Sizeof(out)
200 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
201 if ret >= 0 && int32(out) > 0 {
202 return uintptr(out)
203 }
204 return 0
205 }
206
207
208 func readRandom(r []byte) int {
209 arc4random_buf(unsafe.Pointer(&r[0]), int32(len(r)))
210 return len(r)
211 }
212
213 func goenvs() {
214 goenvs_unix()
215 }
216
217
218
219
220 func newosproc(mp *m) {
221 stk := unsafe.Pointer(mp.g0.stack.hi)
222 if false {
223 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
224 }
225
226
227 var attr pthreadattr
228 var err int32
229 err = pthread_attr_init(&attr)
230 if err != 0 {
231 writeErrStr(failthreadcreate)
232 exit(1)
233 }
234
235
236 var stacksize uintptr
237 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
238 writeErrStr(failthreadcreate)
239 exit(1)
240 }
241 mp.g0.stack.hi = stacksize
242
243
244 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
245 writeErrStr(failthreadcreate)
246 exit(1)
247 }
248
249
250
251 var oset sigset
252 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
253 err = retryOnEAGAIN(func() int32 {
254 return pthread_create(&attr, abi.FuncPCABI0(mstart_stub), unsafe.Pointer(mp))
255 })
256 sigprocmask(_SIG_SETMASK, &oset, nil)
257 if err != 0 {
258 writeErrStr(failthreadcreate)
259 exit(1)
260 }
261 }
262
263
264 func mstart_stub()
265
266
267
268
269
270
271
272 func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
273
274 var attr pthreadattr
275 var err int32
276 err = pthread_attr_init(&attr)
277 if err != 0 {
278 writeErrStr(failthreadcreate)
279 exit(1)
280 }
281
282
283
284
285
286
287 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
288 writeErrStr(failthreadcreate)
289 exit(1)
290 }
291 g0.stack.hi = stacksize
292 memstats.stacks_sys.add(int64(stacksize))
293
294
295 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
296 writeErrStr(failthreadcreate)
297 exit(1)
298 }
299
300
301
302 var oset sigset
303 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
304 err = pthread_create(&attr, uintptr(fn), nil)
305 sigprocmask(_SIG_SETMASK, &oset, nil)
306 if err != 0 {
307 writeErrStr(failthreadcreate)
308 exit(1)
309 }
310 }
311
312
313
314
315
316
317
318 func libpreinit() {
319 initsig(true)
320 }
321
322
323
324 func mpreinit(mp *m) {
325 mp.gsignal = malg(32 * 1024)
326 mp.gsignal.m = mp
327 if GOOS == "darwin" && GOARCH == "arm64" {
328
329
330
331 mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize)
332 }
333 }
334
335
336
337 func minit() {
338
339
340 if !(GOOS == "ios" && GOARCH == "arm64") {
341 minitSignalStack()
342 }
343 minitSignalMask()
344 getg().m.procid = uint64(pthread_self())
345 }
346
347
348
349
350 func unminit() {
351
352
353 if !(GOOS == "ios" && GOARCH == "arm64") {
354 unminitSignals()
355 }
356 getg().m.procid = 0
357 }
358
359
360
361
362
363
364
365 func mdestroy(mp *m) {
366 }
367
368
369 func osyield_no_g() {
370 usleep_no_g(1)
371 }
372
373
374 func osyield() {
375 usleep(1)
376 }
377
378 const (
379 _NSIG = 32
380 _SI_USER = 0
381 _SIG_BLOCK = 1
382 _SIG_UNBLOCK = 2
383 _SIG_SETMASK = 3
384 _SS_DISABLE = 4
385 )
386
387
388
389 type sigset uint32
390
391 var sigset_all = ^sigset(0)
392
393
394
395 func setsig(i uint32, fn uintptr) {
396 var sa usigactiont
397 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
398 sa.sa_mask = ^uint32(0)
399 if fn == abi.FuncPCABIInternal(sighandler) {
400 if iscgo {
401 fn = abi.FuncPCABI0(cgoSigtramp)
402 } else {
403 fn = abi.FuncPCABI0(sigtramp)
404 }
405 }
406 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
407 sigaction(i, &sa, nil)
408 }
409
410
411
412 func sigtramp()
413 func cgoSigtramp()
414
415
416
417 func setsigstack(i uint32) {
418 var osa usigactiont
419 sigaction(i, nil, &osa)
420 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
421 if osa.sa_flags&_SA_ONSTACK != 0 {
422 return
423 }
424 var sa usigactiont
425 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
426 sa.sa_mask = osa.sa_mask
427 sa.sa_flags = osa.sa_flags | _SA_ONSTACK
428 sigaction(i, &sa, nil)
429 }
430
431
432
433 func getsig(i uint32) uintptr {
434 var sa usigactiont
435 sigaction(i, nil, &sa)
436 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
437 }
438
439
440
441
442 func setSignalstackSP(s *stackt, sp uintptr) {
443 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
444 }
445
446
447
448 func sigaddset(mask *sigset, i int) {
449 *mask |= 1 << (uint32(i) - 1)
450 }
451
452 func sigdelset(mask *sigset, i int) {
453 *mask &^= 1 << (uint32(i) - 1)
454 }
455
456 func setProcessCPUProfiler(hz int32) {
457 setProcessCPUProfilerTimer(hz)
458 }
459
460 func setThreadCPUProfiler(hz int32) {
461 setThreadCPUProfilerHz(hz)
462 }
463
464
465 func validSIGPROF(mp *m, c *sigctxt) bool {
466 return true
467 }
468
469
470 var executablePath string
471
472 func sysargs(argc int32, argv **byte) {
473
474 n := argc + 1
475 for argv_index(argv, n) != nil {
476 n++
477 }
478 executablePath = gostringnocopy(argv_index(argv, n+1))
479
480
481 executablePath = stringslite.TrimPrefix(executablePath, "executable_path=")
482 }
483
484 func signalM(mp *m, sig int) {
485 pthread_kill(pthread(mp.procid), uint32(sig))
486 }
487
488
489
490 const sigPerThreadSyscall = 1 << 31
491
492
493 func runPerThreadSyscall() {
494 throw("runPerThreadSyscall only valid on linux")
495 }
496
View as plain text