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