libgo: export NetBSD-specific types in mksysinfo.sh
[gcc.git] / libgo / go / runtime / os_darwin.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
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 //go:nosplit
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 //go:nosplit
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 //go:nosplit
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 // The read and write file descriptors used by the sigNote functions.
79 var sigNoteRead, sigNoteWrite int32
80
81 // sigNoteSetup initializes an async-signal-safe note.
82 //
83 // The current implementation of notes on Darwin is not async-signal-safe,
84 // because the functions pthread_mutex_lock, pthread_cond_signal, and
85 // pthread_mutex_unlock, called by semawakeup, are not async-signal-safe.
86 // There is only one case where we need to wake up a note from a signal
87 // handler: the sigsend function. The signal handler code does not require
88 // all the features of notes: it does not need to do a timed wait.
89 // This is a separate implementation of notes, based on a pipe, that does
90 // not support timed waits but is async-signal-safe.
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 // Make the write end of the pipe non-blocking, so that if the pipe
104 // buffer is somehow full we will not block in the signal handler.
105 // Leave the read end of the pipe blocking so that we will block
106 // in sigNoteSleep.
107 setNonblock(sigNoteWrite)
108 }
109
110 // sigNoteWakeup wakes up a thread sleeping on a note created by sigNoteSetup.
111 func sigNoteWakeup(*note) {
112 var b byte
113 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
114 }
115
116 // sigNoteSleep waits for a note created by sigNoteSetup to be woken.
117 func sigNoteSleep(*note) {
118 entersyscallblock()
119 var b byte
120 read(sigNoteRead, unsafe.Pointer(&b), 1)
121 exitsyscall()
122 }
123
124 // BSD interface for threading.
125 func osinit() {
126 // pthread_create delayed until end of goenvs so that we
127 // can look at the environment first.
128
129 ncpu = getncpu()
130 physPageSize = getPageSize()
131 }