LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Semaphore implementation exposed to Go. | 5 // Semaphore implementation exposed to Go. |
6 // Intended use is provide a sleep and wakeup | 6 // Intended use is provide a sleep and wakeup |
7 // primitive that can be used in the contended case | 7 // primitive that can be used in the contended case |
8 // of other synchronization primitives. | 8 // of other synchronization primitives. |
9 // Thus it targets the same goal as Linux's futex, | 9 // Thus it targets the same goal as Linux's futex, |
10 // but it has much simpler semantics. | 10 // but it has much simpler semantics. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 cansemacquire(uint32 *addr) | 91 cansemacquire(uint32 *addr) |
92 { | 92 { |
93 uint32 v; | 93 uint32 v; |
94 | 94 |
95 while((v = runtime·atomicload(addr)) > 0) | 95 while((v = runtime·atomicload(addr)) > 0) |
96 if(runtime·cas(addr, v, v-1)) | 96 if(runtime·cas(addr, v, v-1)) |
97 return 1; | 97 return 1; |
98 return 0; | 98 return 0; |
99 } | 99 } |
100 | 100 |
101 static void | 101 void |
102 semacquireimpl(uint32 volatile *addr, int32 profile) | 102 runtime·semacquire(uint32 volatile *addr, bool profile) |
103 { | 103 { |
104 Sema s; // Needs to be allocated on stack, otherwise garbage collector c
ould deallocate it | 104 Sema s; // Needs to be allocated on stack, otherwise garbage collector c
ould deallocate it |
105 SemaRoot *root; | 105 SemaRoot *root; |
106 int64 t0; | 106 int64 t0; |
107 ········ | 107 ········ |
108 // Easy case. | 108 // Easy case. |
109 if(cansemacquire(addr)) | 109 if(cansemacquire(addr)) |
110 return; | 110 return; |
111 | 111 |
112 // Harder case: | 112 // Harder case: |
(...skipping 25 matching lines...) Expand all Loading... |
138 runtime·park(runtime·unlock, root, "semacquire"); | 138 runtime·park(runtime·unlock, root, "semacquire"); |
139 if(cansemacquire(addr)) { | 139 if(cansemacquire(addr)) { |
140 if(t0) | 140 if(t0) |
141 runtime·blockevent(s.releasetime - t0, 3); | 141 runtime·blockevent(s.releasetime - t0, 3); |
142 return; | 142 return; |
143 } | 143 } |
144 } | 144 } |
145 } | 145 } |
146 | 146 |
147 void | 147 void |
148 runtime·semacquire(uint32 volatile *addr) | |
149 { | |
150 semacquireimpl(addr, 0); | |
151 } | |
152 | |
153 void | |
154 runtime·semrelease(uint32 volatile *addr) | 148 runtime·semrelease(uint32 volatile *addr) |
155 { | 149 { |
156 Sema *s; | 150 Sema *s; |
157 SemaRoot *root; | 151 SemaRoot *root; |
158 | 152 |
159 root = semroot(addr); | 153 root = semroot(addr); |
160 runtime·xadd(addr, 1); | 154 runtime·xadd(addr, 1); |
161 | 155 |
162 // Easy case: no waiters? | 156 // Easy case: no waiters? |
163 // This check must happen after the xadd, to avoid a missed wakeup | 157 // This check must happen after the xadd, to avoid a missed wakeup |
(...skipping 18 matching lines...) Expand all Loading... |
182 } | 176 } |
183 runtime·unlock(root); | 177 runtime·unlock(root); |
184 if(s) { | 178 if(s) { |
185 if(s->releasetime) | 179 if(s->releasetime) |
186 s->releasetime = runtime·cputicks(); | 180 s->releasetime = runtime·cputicks(); |
187 runtime·ready(s->g); | 181 runtime·ready(s->g); |
188 } | 182 } |
189 } | 183 } |
190 | 184 |
191 func runtime_Semacquire(addr *uint32) { | 185 func runtime_Semacquire(addr *uint32) { |
192 » semacquireimpl(addr, 1); | 186 » runtime·semacquire(addr, true); |
193 } | 187 } |
194 | 188 |
195 func runtime_Semrelease(addr *uint32) { | 189 func runtime_Semrelease(addr *uint32) { |
196 runtime·semrelease(addr); | 190 runtime·semrelease(addr); |
197 } | 191 } |
198 | |
199 void net·runtime_Semacquire(uint32 *addr) { | |
200 semacquireimpl(addr, 1); | |
201 } | |
202 | |
203 void net·runtime_Semrelease(uint32 *addr) { | |
204 runtime·semrelease(addr); | |
205 } | |
LEFT | RIGHT |