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