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