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
350
351
352 func mdestroy(mp *m) {
353 }
354
355
356 func osyield_no_g() {
357 usleep_no_g(1)
358 }
359
360
361 func osyield() {
362 usleep(1)
363 }
364
365 const (
366 _NSIG = 32
367 _SI_USER = 0
368 _SIG_BLOCK = 1
369 _SIG_UNBLOCK = 2
370 _SIG_SETMASK = 3
371 _SS_DISABLE = 4
372 )
373
374
375
376 type sigset uint32
377
378 var sigset_all = ^sigset(0)
379
380
381
382 func setsig(i uint32, fn uintptr) {
383 var sa usigactiont
384 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
385 sa.sa_mask = ^uint32(0)
386 if fn == abi.FuncPCABIInternal(sighandler) {
387 if iscgo {
388 fn = abi.FuncPCABI0(cgoSigtramp)
389 } else {
390 fn = abi.FuncPCABI0(sigtramp)
391 }
392 }
393 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
394 sigaction(i, &sa, nil)
395 }
396
397
398
399 func sigtramp()
400 func cgoSigtramp()
401
402
403
404 func setsigstack(i uint32) {
405 var osa usigactiont
406 sigaction(i, nil, &osa)
407 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
408 if osa.sa_flags&_SA_ONSTACK != 0 {
409 return
410 }
411 var sa usigactiont
412 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
413 sa.sa_mask = osa.sa_mask
414 sa.sa_flags = osa.sa_flags | _SA_ONSTACK
415 sigaction(i, &sa, nil)
416 }
417
418
419
420 func getsig(i uint32) uintptr {
421 var sa usigactiont
422 sigaction(i, nil, &sa)
423 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
424 }
425
426
427
428
429 func setSignalstackSP(s *stackt, sp uintptr) {
430 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
431 }
432
433
434
435 func sigaddset(mask *sigset, i int) {
436 *mask |= 1 << (uint32(i) - 1)
437 }
438
439 func sigdelset(mask *sigset, i int) {
440 *mask &^= 1 << (uint32(i) - 1)
441 }
442
443 func setProcessCPUProfiler(hz int32) {
444 setProcessCPUProfilerTimer(hz)
445 }
446
447 func setThreadCPUProfiler(hz int32) {
448 setThreadCPUProfilerHz(hz)
449 }
450
451
452 func validSIGPROF(mp *m, c *sigctxt) bool {
453 return true
454 }
455
456
457 var executablePath string
458
459 func sysargs(argc int32, argv **byte) {
460
461 n := argc + 1
462 for argv_index(argv, n) != nil {
463 n++
464 }
465 executablePath = gostringnocopy(argv_index(argv, n+1))
466
467
468 executablePath = stringslite.TrimPrefix(executablePath, "executable_path=")
469 }
470
471 func signalM(mp *m, sig int) {
472 pthread_kill(pthread(mp.procid), uint32(sig))
473 }
474
475
476
477 const sigPerThreadSyscall = 1 << 31
478
479
480 func runPerThreadSyscall() {
481 throw("runPerThreadSyscall only valid on linux")
482 }
483
View as plain text