Source file
src/runtime/os_darwin.go
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 mp := getg().m
45 pthread_mutex_lock(&mp.mutex)
46 for {
47 if mp.count > 0 {
48 mp.count--
49 pthread_mutex_unlock(&mp.mutex)
50 return 0
51 }
52 if ns >= 0 {
53 spent := nanotime() - start
54 if spent >= ns {
55 pthread_mutex_unlock(&mp.mutex)
56 return -1
57 }
58 var t timespec
59 t.setNsec(ns - spent)
60 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
61 if err == _ETIMEDOUT {
62 pthread_mutex_unlock(&mp.mutex)
63 return -1
64 }
65 } else {
66 pthread_cond_wait(&mp.cond, &mp.mutex)
67 }
68 }
69 }
70
71
72 func semawakeup(mp *m) {
73 pthread_mutex_lock(&mp.mutex)
74 mp.count++
75 if mp.count > 0 {
76 pthread_cond_signal(&mp.cond)
77 }
78 pthread_mutex_unlock(&mp.mutex)
79 }
80
81
82 var sigNoteRead, sigNoteWrite int32
83
84
85
86
87
88
89
90
91
92
93
94 func sigNoteSetup(*note) {
95 if sigNoteRead != 0 || sigNoteWrite != 0 {
96 throw("duplicate sigNoteSetup")
97 }
98 var errno int32
99 sigNoteRead, sigNoteWrite, errno = pipe()
100 if errno != 0 {
101 throw("pipe failed")
102 }
103 closeonexec(sigNoteRead)
104 closeonexec(sigNoteWrite)
105
106
107
108
109
110 setNonblock(sigNoteWrite)
111 }
112
113
114 func sigNoteWakeup(*note) {
115 var b byte
116 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
117 }
118
119
120 func sigNoteSleep(*note) {
121 for {
122 var b byte
123 entersyscallblock()
124 n := read(sigNoteRead, unsafe.Pointer(&b), 1)
125 exitsyscall()
126 if n != -_EINTR {
127 return
128 }
129 }
130 }
131
132
133 func osinit() {
134
135
136
137 ncpu = getncpu()
138 physPageSize = getPageSize()
139 }
140
141 func sysctlbynameInt32(name []byte) (int32, int32) {
142 out := int32(0)
143 nout := unsafe.Sizeof(out)
144 ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
145 return ret, out
146 }
147
148
149 func internal_cpu_getsysctlbyname(name []byte) (int32, int32) {
150 return sysctlbynameInt32(name)
151 }
152
153 const (
154 _CTL_HW = 6
155 _HW_NCPU = 3
156 _HW_PAGESIZE = 7
157 )
158
159 func getncpu() int32 {
160
161 mib := [2]uint32{_CTL_HW, _HW_NCPU}
162 out := uint32(0)
163 nout := unsafe.Sizeof(out)
164 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
165 if ret >= 0 && int32(out) > 0 {
166 return int32(out)
167 }
168 return 1
169 }
170
171 func getPageSize() uintptr {
172
173 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
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 uintptr(out)
179 }
180 return 0
181 }
182
183 var urandom_dev = []byte("/dev/urandom\x00")
184
185
186 func getRandomData(r []byte) {
187 fd := open(&urandom_dev[0], 0 , 0)
188 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
189 closefd(fd)
190 extendRandom(r, int(n))
191 }
192
193 func goenvs() {
194 goenvs_unix()
195 }
196
197
198
199
200 func newosproc(mp *m) {
201 stk := unsafe.Pointer(mp.g0.stack.hi)
202 if false {
203 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
204 }
205
206
207 var attr pthreadattr
208 var err int32
209 err = pthread_attr_init(&attr)
210 if err != 0 {
211 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
212 exit(1)
213 }
214
215
216 var stacksize uintptr
217 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
218 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
219 exit(1)
220 }
221 mp.g0.stack.hi = stacksize
222
223
224 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
225 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
226 exit(1)
227 }
228
229
230
231 var oset sigset
232 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
233 err = pthread_create(&attr, abi.FuncPCABI0(mstart_stub), unsafe.Pointer(mp))
234 sigprocmask(_SIG_SETMASK, &oset, nil)
235 if err != 0 {
236 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
237 exit(1)
238 }
239 }
240
241
242 func mstart_stub()
243
244
245
246
247
248
249
250 func newosproc0(stacksize uintptr, fn uintptr) {
251
252 var attr pthreadattr
253 var err int32
254 err = pthread_attr_init(&attr)
255 if err != 0 {
256 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
257 exit(1)
258 }
259
260
261
262
263
264
265 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
266 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
267 exit(1)
268 }
269 g0.stack.hi = stacksize
270 memstats.stacks_sys.add(int64(stacksize))
271
272
273 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
274 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
275 exit(1)
276 }
277
278
279
280 var oset sigset
281 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
282 err = pthread_create(&attr, fn, nil)
283 sigprocmask(_SIG_SETMASK, &oset, nil)
284 if err != 0 {
285 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
286 exit(1)
287 }
288 }
289
290 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
291 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
292
293
294
295
296
297
298
299 func libpreinit() {
300 initsig(true)
301 }
302
303
304
305 func mpreinit(mp *m) {
306 mp.gsignal = malg(32 * 1024)
307 mp.gsignal.m = mp
308 if GOOS == "darwin" && GOARCH == "arm64" {
309
310
311
312 mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize)
313 }
314 }
315
316
317
318 func minit() {
319
320
321 if !(GOOS == "ios" && GOARCH == "arm64") {
322 minitSignalStack()
323 }
324 minitSignalMask()
325 getg().m.procid = uint64(pthread_self())
326 }
327
328
329
330
331 func unminit() {
332
333
334 if !(GOOS == "ios" && GOARCH == "arm64") {
335 unminitSignals()
336 }
337 }
338
339
340
341 func mdestroy(mp *m) {
342 }
343
344
345 func osyield_no_g() {
346 usleep_no_g(1)
347 }
348
349
350 func osyield() {
351 usleep(1)
352 }
353
354 const (
355 _NSIG = 32
356 _SI_USER = 0
357 _SIG_BLOCK = 1
358 _SIG_UNBLOCK = 2
359 _SIG_SETMASK = 3
360 _SS_DISABLE = 4
361 )
362
363
364
365 type sigset uint32
366
367 var sigset_all = ^sigset(0)
368
369
370
371 func setsig(i uint32, fn uintptr) {
372 var sa usigactiont
373 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
374 sa.sa_mask = ^uint32(0)
375 if fn == abi.FuncPCABIInternal(sighandler) {
376 if iscgo {
377 fn = abi.FuncPCABI0(cgoSigtramp)
378 } else {
379 fn = abi.FuncPCABI0(sigtramp)
380 }
381 }
382 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
383 sigaction(i, &sa, nil)
384 }
385
386
387
388 func sigtramp()
389 func cgoSigtramp()
390
391
392
393 func setsigstack(i uint32) {
394 var osa usigactiont
395 sigaction(i, nil, &osa)
396 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
397 if osa.sa_flags&_SA_ONSTACK != 0 {
398 return
399 }
400 var sa usigactiont
401 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
402 sa.sa_mask = osa.sa_mask
403 sa.sa_flags = osa.sa_flags | _SA_ONSTACK
404 sigaction(i, &sa, nil)
405 }
406
407
408
409 func getsig(i uint32) uintptr {
410 var sa usigactiont
411 sigaction(i, nil, &sa)
412 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
413 }
414
415
416
417
418 func setSignalstackSP(s *stackt, sp uintptr) {
419 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
420 }
421
422
423
424 func sigaddset(mask *sigset, i int) {
425 *mask |= 1 << (uint32(i) - 1)
426 }
427
428 func sigdelset(mask *sigset, i int) {
429 *mask &^= 1 << (uint32(i) - 1)
430 }
431
432 func setProcessCPUProfiler(hz int32) {
433 setProcessCPUProfilerTimer(hz)
434 }
435
436 func setThreadCPUProfiler(hz int32) {
437 setThreadCPUProfilerHz(hz)
438 }
439
440
441 func validSIGPROF(mp *m, c *sigctxt) bool {
442 return true
443 }
444
445
446 var executablePath string
447
448 func sysargs(argc int32, argv **byte) {
449
450 n := argc + 1
451 for argv_index(argv, n) != nil {
452 n++
453 }
454 executablePath = gostringnocopy(argv_index(argv, n+1))
455
456
457 const prefix = "executable_path="
458 if len(executablePath) > len(prefix) && executablePath[:len(prefix)] == prefix {
459 executablePath = executablePath[len(prefix):]
460 }
461 }
462
463 func signalM(mp *m, sig int) {
464 pthread_kill(pthread(mp.procid), uint32(sig))
465 }
466
467
468
469 const sigPerThreadSyscall = 1 << 31
470
471
472 func runPerThreadSyscall() {
473 throw("runPerThreadSyscall only valid on linux")
474 }
475
View as plain text