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
166 func internal_cpu_getsysctlbyname(name []byte) (int32, int32) {
167 return sysctlbynameInt32(name)
168 }
169
170 const (
171 _CTL_HW = 6
172 _HW_NCPU = 3
173 _HW_PAGESIZE = 7
174 )
175
176 func getCPUCount() int32 {
177
178 mib := [2]uint32{_CTL_HW, _HW_NCPU}
179 out := uint32(0)
180 nout := unsafe.Sizeof(out)
181 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
182 if ret >= 0 && int32(out) > 0 {
183 return int32(out)
184 }
185 return 1
186 }
187
188 func getPageSize() uintptr {
189
190 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
191 out := uint32(0)
192 nout := unsafe.Sizeof(out)
193 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
194 if ret >= 0 && int32(out) > 0 {
195 return uintptr(out)
196 }
197 return 0
198 }
199
200
201 func readRandom(r []byte) int {
202 arc4random_buf(unsafe.Pointer(&r[0]), int32(len(r)))
203 return len(r)
204 }
205
206 func goenvs() {
207 goenvs_unix()
208 }
209
210
211
212
213 func newosproc(mp *m) {
214 stk := unsafe.Pointer(mp.g0.stack.hi)
215 if false {
216 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
217 }
218
219
220 var attr pthreadattr
221 var err int32
222 err = pthread_attr_init(&attr)
223 if err != 0 {
224 writeErrStr(failthreadcreate)
225 exit(1)
226 }
227
228
229 var stacksize uintptr
230 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
231 writeErrStr(failthreadcreate)
232 exit(1)
233 }
234 mp.g0.stack.hi = stacksize
235
236
237 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
238 writeErrStr(failthreadcreate)
239 exit(1)
240 }
241
242
243
244 var oset sigset
245 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
246 err = retryOnEAGAIN(func() int32 {
247 return pthread_create(&attr, abi.FuncPCABI0(mstart_stub), unsafe.Pointer(mp))
248 })
249 sigprocmask(_SIG_SETMASK, &oset, nil)
250 if err != 0 {
251 writeErrStr(failthreadcreate)
252 exit(1)
253 }
254 }
255
256
257 func mstart_stub()
258
259
260
261
262
263
264
265 func newosproc0(stacksize uintptr, fn uintptr) {
266
267 var attr pthreadattr
268 var err int32
269 err = pthread_attr_init(&attr)
270 if err != 0 {
271 writeErrStr(failthreadcreate)
272 exit(1)
273 }
274
275
276
277
278
279
280 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
281 writeErrStr(failthreadcreate)
282 exit(1)
283 }
284 g0.stack.hi = stacksize
285 memstats.stacks_sys.add(int64(stacksize))
286
287
288 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
289 writeErrStr(failthreadcreate)
290 exit(1)
291 }
292
293
294
295 var oset sigset
296 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
297 err = pthread_create(&attr, fn, nil)
298 sigprocmask(_SIG_SETMASK, &oset, nil)
299 if err != 0 {
300 writeErrStr(failthreadcreate)
301 exit(1)
302 }
303 }
304
305
306
307
308
309
310
311 func libpreinit() {
312 initsig(true)
313 }
314
315
316
317 func mpreinit(mp *m) {
318 mp.gsignal = malg(32 * 1024)
319 mp.gsignal.m = mp
320 if GOOS == "darwin" && GOARCH == "arm64" {
321
322
323
324 mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize)
325 }
326 }
327
328
329
330 func minit() {
331
332
333 if !(GOOS == "ios" && GOARCH == "arm64") {
334 minitSignalStack()
335 }
336 minitSignalMask()
337 getg().m.procid = uint64(pthread_self())
338 libc_error_addr(&getg().m.errnoAddr)
339 }
340
341
342
343
344 func unminit() {
345
346
347 if !(GOOS == "ios" && GOARCH == "arm64") {
348 unminitSignals()
349 }
350 getg().m.procid = 0
351 }
352
353
354
355
356
357
358
359 func mdestroy(mp *m) {
360 }
361
362
363 func osyield_no_g() {
364 usleep_no_g(1)
365 }
366
367
368 func osyield() {
369 usleep(1)
370 }
371
372 const (
373 _NSIG = 32
374 _SI_USER = 0
375 _SIG_BLOCK = 1
376 _SIG_UNBLOCK = 2
377 _SIG_SETMASK = 3
378 _SS_DISABLE = 4
379 )
380
381
382
383 type sigset uint32
384
385 var sigset_all = ^sigset(0)
386
387
388
389 func setsig(i uint32, fn uintptr) {
390 var sa usigactiont
391 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
392 sa.sa_mask = ^uint32(0)
393 if fn == abi.FuncPCABIInternal(sighandler) {
394 if iscgo {
395 fn = abi.FuncPCABI0(cgoSigtramp)
396 } else {
397 fn = abi.FuncPCABI0(sigtramp)
398 }
399 }
400 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
401 sigaction(i, &sa, nil)
402 }
403
404
405
406 func sigtramp()
407 func cgoSigtramp()
408
409
410
411 func setsigstack(i uint32) {
412 var osa usigactiont
413 sigaction(i, nil, &osa)
414 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
415 if osa.sa_flags&_SA_ONSTACK != 0 {
416 return
417 }
418 var sa usigactiont
419 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
420 sa.sa_mask = osa.sa_mask
421 sa.sa_flags = osa.sa_flags | _SA_ONSTACK
422 sigaction(i, &sa, nil)
423 }
424
425
426
427 func getsig(i uint32) uintptr {
428 var sa usigactiont
429 sigaction(i, nil, &sa)
430 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
431 }
432
433
434
435
436 func setSignalstackSP(s *stackt, sp uintptr) {
437 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
438 }
439
440
441
442 func sigaddset(mask *sigset, i int) {
443 *mask |= 1 << (uint32(i) - 1)
444 }
445
446 func sigdelset(mask *sigset, i int) {
447 *mask &^= 1 << (uint32(i) - 1)
448 }
449
450 func setProcessCPUProfiler(hz int32) {
451 setProcessCPUProfilerTimer(hz)
452 }
453
454 func setThreadCPUProfiler(hz int32) {
455 setThreadCPUProfilerHz(hz)
456 }
457
458
459 func validSIGPROF(mp *m, c *sigctxt) bool {
460 return true
461 }
462
463
464 var executablePath string
465
466 func sysargs(argc int32, argv **byte) {
467
468 n := argc + 1
469 for argv_index(argv, n) != nil {
470 n++
471 }
472 executablePath = gostringnocopy(argv_index(argv, n+1))
473
474
475 executablePath = stringslite.TrimPrefix(executablePath, "executable_path=")
476 }
477
478 func signalM(mp *m, sig int) {
479 pthread_kill(pthread(mp.procid), uint32(sig))
480 }
481
482
483
484 const sigPerThreadSyscall = 1 << 31
485
486
487 func runPerThreadSyscall() {
488 throw("runPerThreadSyscall only valid on linux")
489 }
490
View as plain text