Source file src/pkg/runtime/os_darwin.go
1
2
3
4
5 package runtime
6
7 import "unsafe"
8
9 type mOS struct {
10 initialized bool
11 mutex pthreadmutex
12 cond pthreadcond
13 count int
14 }
15
16 func unimplemented(name string) {
17 println(name, "not implemented")
18 *(*int)(unsafe.Pointer(uintptr(1231))) = 1231
19 }
20
21
22 func semacreate(mp *m) {
23 if mp.initialized {
24 return
25 }
26 mp.initialized = true
27 if err := pthread_mutex_init(&mp.mutex, nil); err != 0 {
28 throw("pthread_mutex_init")
29 }
30 if err := pthread_cond_init(&mp.cond, nil); err != 0 {
31 throw("pthread_cond_init")
32 }
33 }
34
35
36 func semasleep(ns int64) int32 {
37 var start int64
38 if ns >= 0 {
39 start = nanotime()
40 }
41 mp := getg().m
42 pthread_mutex_lock(&mp.mutex)
43 for {
44 if mp.count > 0 {
45 mp.count--
46 pthread_mutex_unlock(&mp.mutex)
47 return 0
48 }
49 if ns >= 0 {
50 spent := nanotime() - start
51 if spent >= ns {
52 pthread_mutex_unlock(&mp.mutex)
53 return -1
54 }
55 var t timespec
56 t.setNsec(ns - spent)
57 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
58 if err == _ETIMEDOUT {
59 pthread_mutex_unlock(&mp.mutex)
60 return -1
61 }
62 } else {
63 pthread_cond_wait(&mp.cond, &mp.mutex)
64 }
65 }
66 }
67
68
69 func semawakeup(mp *m) {
70 pthread_mutex_lock(&mp.mutex)
71 mp.count++
72 if mp.count > 0 {
73 pthread_cond_signal(&mp.cond)
74 }
75 pthread_mutex_unlock(&mp.mutex)
76 }
77
78
79 var sigNoteRead, sigNoteWrite int32
80
81
82
83
84
85
86
87
88
89
90
91 func sigNoteSetup(*note) {
92 if sigNoteRead != 0 || sigNoteWrite != 0 {
93 throw("duplicate sigNoteSetup")
94 }
95 var errno int32
96 sigNoteRead, sigNoteWrite, errno = pipe()
97 if errno != 0 {
98 throw("pipe failed")
99 }
100 closeonexec(sigNoteRead)
101 closeonexec(sigNoteWrite)
102
103
104
105
106
107 setNonblock(sigNoteWrite)
108 }
109
110
111 func sigNoteWakeup(*note) {
112 var b byte
113 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
114 }
115
116
117 func sigNoteSleep(*note) {
118 entersyscallblock()
119 var b byte
120 read(sigNoteRead, unsafe.Pointer(&b), 1)
121 exitsyscall()
122 }
123
124
125 func osinit() {
126
127
128
129 ncpu = getncpu()
130 physPageSize = getPageSize()
131 }
132
133 const (
134 _CTL_HW = 6
135 _HW_NCPU = 3
136 _HW_PAGESIZE = 7
137 )
138
139 func getncpu() int32 {
140
141 mib := [2]uint32{_CTL_HW, _HW_NCPU}
142 out := uint32(0)
143 nout := unsafe.Sizeof(out)
144 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
145 if ret >= 0 && int32(out) > 0 {
146 return int32(out)
147 }
148 return 1
149 }
150
151 func getPageSize() uintptr {
152
153 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
154 out := uint32(0)
155 nout := unsafe.Sizeof(out)
156 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
157 if ret >= 0 && int32(out) > 0 {
158 return uintptr(out)
159 }
160 return 0
161 }
162
163 var urandom_dev = []byte("/dev/urandom\x00")
164
165
166 func getRandomData(r []byte) {
167 fd := open(&urandom_dev[0], 0 , 0)
168 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
169 closefd(fd)
170 extendRandom(r, int(n))
171 }
172
173 func goenvs() {
174 goenvs_unix()
175 }
176
177
178
179 func newosproc(mp *m) {
180 stk := unsafe.Pointer(mp.g0.stack.hi)
181 if false {
182 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
183 }
184
185
186 var attr pthreadattr
187 var err int32
188 err = pthread_attr_init(&attr)
189 if err != 0 {
190 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
191 exit(1)
192 }
193
194
195 var stacksize uintptr
196 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
197 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
198 exit(1)
199 }
200 mp.g0.stack.hi = stacksize
201
202
203
204 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
205 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
206 exit(1)
207 }
208
209
210
211 var oset sigset
212 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
213 err = pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp))
214 sigprocmask(_SIG_SETMASK, &oset, nil)
215 if err != 0 {
216 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
217 exit(1)
218 }
219 }
220
221
222 func mstart_stub()
223
224
225
226
227
228
229
230 func newosproc0(stacksize uintptr, fn uintptr) {
231
232 var attr pthreadattr
233 var err int32
234 err = pthread_attr_init(&attr)
235 if err != 0 {
236 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
237 exit(1)
238 }
239
240
241
242
243
244
245 if pthread_attr_getstacksize(&attr, &stacksize) != 0 {
246 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
247 exit(1)
248 }
249 g0.stack.hi = stacksize
250 mSysStatInc(&memstats.stacks_sys, stacksize)
251
252
253 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
254 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
255 exit(1)
256 }
257
258
259
260 var oset sigset
261 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
262 err = pthread_create(&attr, fn, nil)
263 sigprocmask(_SIG_SETMASK, &oset, nil)
264 if err != 0 {
265 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
266 exit(1)
267 }
268 }
269
270 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
271 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
272
273
274
275
276
277
278 func libpreinit() {
279 initsig(true)
280 }
281
282
283
284 func mpreinit(mp *m) {
285 mp.gsignal = malg(32 * 1024)
286 mp.gsignal.m = mp
287 }
288
289
290
291 func minit() {
292
293
294 if GOARCH != "arm" && GOARCH != "arm64" {
295 minitSignalStack()
296 }
297 minitSignalMask()
298 }
299
300
301
302 func unminit() {
303
304
305 if GOARCH != "arm" && GOARCH != "arm64" {
306 unminitSignals()
307 }
308 }
309
310
311 func osyield() {
312 usleep(1)
313 }
314
315 const (
316 _NSIG = 32
317 _SI_USER = 0
318 _SIG_BLOCK = 1
319 _SIG_UNBLOCK = 2
320 _SIG_SETMASK = 3
321 _SS_DISABLE = 4
322 )
323
324
325
326 type sigset uint32
327
328 var sigset_all = ^sigset(0)
329
330
331
332 func setsig(i uint32, fn uintptr) {
333 var sa usigactiont
334 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
335 sa.sa_mask = ^uint32(0)
336 if fn == funcPC(sighandler) {
337 if iscgo {
338 fn = funcPC(cgoSigtramp)
339 } else {
340 fn = funcPC(sigtramp)
341 }
342 }
343 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
344 sigaction(i, &sa, nil)
345 }
346
347
348
349 func sigtramp()
350 func cgoSigtramp()
351
352
353
354 func setsigstack(i uint32) {
355 var osa usigactiont
356 sigaction(i, nil, &osa)
357 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
358 if osa.sa_flags&_SA_ONSTACK != 0 {
359 return
360 }
361 var sa usigactiont
362 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
363 sa.sa_mask = osa.sa_mask
364 sa.sa_flags = osa.sa_flags | _SA_ONSTACK
365 sigaction(i, &sa, nil)
366 }
367
368
369
370 func getsig(i uint32) uintptr {
371 var sa usigactiont
372 sigaction(i, nil, &sa)
373 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
374 }
375
376
377
378 func setSignalstackSP(s *stackt, sp uintptr) {
379 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
380 }
381
382
383
384 func sigaddset(mask *sigset, i int) {
385 *mask |= 1 << (uint32(i) - 1)
386 }
387
388 func sigdelset(mask *sigset, i int) {
389 *mask &^= 1 << (uint32(i) - 1)
390 }
391
392
393 var executablePath string
394
395 func sysargs(argc int32, argv **byte) {
396
397 n := argc + 1
398 for argv_index(argv, n) != nil {
399 n++
400 }
401 executablePath = gostringnocopy(argv_index(argv, n+1))
402
403
404 const prefix = "executable_path="
405 if len(executablePath) > len(prefix) && executablePath[:len(prefix)] == prefix {
406 executablePath = executablePath[len(prefix):]
407 }
408 }
409
View as plain text