Source file
src/runtime/os_darwin.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "unsafe"
10 )
11
12 type mOS struct {
13 initialized bool
14 mutex pthreadmutex
15 cond pthreadcond
16 count int
17 }
18
19 func unimplemented(name string) {
20 println(name, "not implemented")
21 *(*int)(unsafe.Pointer(uintptr(1231))) = 1231
22 }
23
24
25 func semacreate(mp *m) {
26 if mp.initialized {
27 return
28 }
29 mp.initialized = true
30 if err := pthread_mutex_init(&mp.mutex, nil); err != 0 {
31 throw("pthread_mutex_init")
32 }
33 if err := pthread_cond_init(&mp.cond, nil); err != 0 {
34 throw("pthread_cond_init")
35 }
36 }
37
38
39 func semasleep(ns int64) int32 {
40 var start int64
41 if ns >= 0 {
42 start = nanotime()
43 }
44 g := getg()
45 mp := g.m
46 if g == mp.gsignal {
47
48 throw("semasleep on Darwin signal stack")
49 }
50 pthread_mutex_lock(&mp.mutex)
51 for {
52 if mp.count > 0 {
53 mp.count--
54 pthread_mutex_unlock(&mp.mutex)
55 return 0
56 }
57 if ns >= 0 {
58 spent := nanotime() - start
59 if spent >= ns {
60 pthread_mutex_unlock(&mp.mutex)
61 return -1
62 }
63 var t timespec
64 t.setNsec(ns - spent)
65 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
66 if err == _ETIMEDOUT {
67 pthread_mutex_unlock(&mp.mutex)
68 return -1
69 }
70 } else {
71 pthread_cond_wait(&mp.cond, &mp.mutex)
72 }
73 }
74 }
75
76
77 func semawakeup(mp *m) {
78 if g := getg(); g == g.m.gsignal {
79 throw("semawakeup on Darwin signal stack")
80 }
81 pthread_mutex_lock(&mp.mutex)
82 mp.count++
83 if mp.count > 0 {
84 pthread_cond_signal(&mp.cond)
85 }
86 pthread_mutex_unlock(&mp.mutex)
87 }
88
89
90 var sigNoteRead, sigNoteWrite int32
91
92
93
94
95
96
97
98
99
100
101
102 func sigNoteSetup(*note) {
103 if sigNoteRead != 0 || sigNoteWrite != 0 {
104
105 throw("duplicate sigNoteSetup")
106 }
107 var errno int32
108 sigNoteRead, sigNoteWrite, errno = pipe()
109 if errno != 0 {
110 throw("pipe failed")
111 }
112 closeonexec(sigNoteRead)
113 closeonexec(sigNoteWrite)
114
115
116
117
118
119 setNonblock(sigNoteWrite)
120 }
121
122
123 func sigNoteWakeup(*note) {
124 var b byte
125 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
126 }
127
128
129 func sigNoteSleep(*note) {
130 for {
131 var b byte
132 entersyscallblock()
133 n := read(sigNoteRead, unsafe.Pointer(&b), 1)
134 exitsyscall()
135 if n != -_EINTR {
136 return
137 }
138 }
139 }
140
141
142 func osinit() {
143
144
145
146 ncpu = getncpu()
147 physPageSize = getPageSize()
148
149 osinit_hack()
150 }
151
152 func sysctlbynameInt32(name []byte) (int32, int32) {
153 out := int32(0)
154 nout := unsafe.Sizeof(out)
155 ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
156 return ret, out
157 }
158
159
160 func internal_cpu_getsysctlbyname(name []byte) (int32, int32) {
161 return sysctlbynameInt32(name)
162 }
163
164 const (
165 _CTL_HW = 6
166 _HW_NCPU = 3
167 _HW_PAGESIZE = 7
168 )
169
170 func getncpu() int32 {
171
172 mib := [2]uint32{_CTL_HW, _HW_NCPU}
173 out := uint32(0)
174 nout := unsafe.Sizeof(out)
175 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
176 if ret >= 0 && int32(out) > 0 {
177 return int32(out)
178 }
179 return 1
180 }
181
182 func getPageSize() uintptr {
183
184 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
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 uintptr(out)
190 }
191 return 0
192 }
193
194 var urandom_dev = []byte("/dev/urandom\x00")
195
196
197 func readRandom(r []byte) int {
198 fd := open(&urandom_dev[0], 0 , 0)
199 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
200 closefd(fd)
201 return int(n)
202 }
203
204 func goenvs() {
205 goenvs_unix()
206 }
207
208
209
210
211 func newosproc(mp *m) {
212 stk := unsafe.Pointer(mp.g0.stack.hi)
213 if false {
214 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
215 }
216
217
218 var attr pthreadattr
219 var err int32
220 err = pthread_attr_init(&attr)
221 if err != 0 {
222 writeErrStr(failthreadcreate)
223 exit(1)
224 }
225
226
227 var stacksize uintptr
228 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
229 writeErrStr(failthreadcreate)
230 exit(1)
231 }
232 mp.g0.stack.hi = stacksize
233
234
235 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
236 writeErrStr(failthreadcreate)
237 exit(1)
238 }
239
240
241
242 var oset sigset
243 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
244 err = retryOnEAGAIN(func() int32 {
245 return pthread_create(&attr, abi.FuncPCABI0(mstart_stub), unsafe.Pointer(mp))
246 })
247 sigprocmask(_SIG_SETMASK, &oset, nil)
248 if err != 0 {
249 writeErrStr(failthreadcreate)
250 exit(1)
251 }
252 }
253
254
255 func mstart_stub()
256
257
258
259
260
261
262
263 func newosproc0(stacksize uintptr, fn uintptr) {
264
265 var attr pthreadattr
266 var err int32
267 err = pthread_attr_init(&attr)
268 if err != 0 {
269 writeErrStr(failthreadcreate)
270 exit(1)
271 }
272
273
274
275
276
277
278 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
279 writeErrStr(failthreadcreate)
280 exit(1)
281 }
282 g0.stack.hi = stacksize
283 memstats.stacks_sys.add(int64(stacksize))
284
285
286 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
287 writeErrStr(failthreadcreate)
288 exit(1)
289 }
290
291
292
293 var oset sigset
294 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
295 err = pthread_create(&attr, fn, nil)
296 sigprocmask(_SIG_SETMASK, &oset, nil)
297 if err != 0 {
298 writeErrStr(failthreadcreate)
299 exit(1)
300 }
301 }
302
303
304
305
306
307
308
309 func libpreinit() {
310 initsig(true)
311 }
312
313
314
315 func mpreinit(mp *m) {
316 mp.gsignal = malg(32 * 1024)
317 mp.gsignal.m = mp
318 if GOOS == "darwin" && GOARCH == "arm64" {
319
320
321
322 mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize)
323 }
324 }
325
326
327
328 func minit() {
329
330
331 if !(GOOS == "ios" && GOARCH == "arm64") {
332 minitSignalStack()
333 }
334 minitSignalMask()
335 getg().m.procid = uint64(pthread_self())
336 }
337
338
339
340
341 func unminit() {
342
343
344 if !(GOOS == "ios" && GOARCH == "arm64") {
345 unminitSignals()
346 }
347 getg().m.procid = 0
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 const prefix = "executable_path="
469 if len(executablePath) > len(prefix) && executablePath[:len(prefix)] == prefix {
470 executablePath = executablePath[len(prefix):]
471 }
472 }
473
474 func signalM(mp *m, sig int) {
475 pthread_kill(pthread(mp.procid), uint32(sig))
476 }
477
478
479
480 const sigPerThreadSyscall = 1 << 31
481
482
483 func runPerThreadSyscall() {
484 throw("runPerThreadSyscall only valid on linux")
485 }
486
View as plain text