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