LEFT | RIGHT |
(no file at all) | |
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 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "type.h" | 7 #include "type.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 | 9 |
10 #define MAXALIGN 7 | 10 #define MAXALIGN 7 |
11 #define NOSELGEN 1 | 11 #define NOSELGEN 1 |
12 | 12 |
13 static int32 debug = 0; | 13 static int32 debug = 0; |
14 | 14 |
15 typedef struct WaitQ WaitQ; | 15 typedef struct WaitQ WaitQ; |
16 typedef struct SudoG SudoG; | 16 typedef struct SudoG SudoG; |
17 typedef struct Select Select; | 17 typedef struct Select Select; |
18 typedef struct Scase Scase; | 18 typedef struct Scase Scase; |
19 | 19 |
20 struct SudoG | 20 struct SudoG |
21 { | 21 { |
22 G* g; // g and selgen constitute | 22 G* g; // g and selgen constitute |
23 uint32 selgen; // a weak pointer to g | 23 uint32 selgen; // a weak pointer to g |
24 SudoG* link; | 24 SudoG* link; |
| 25 int64 releasetime; |
25 byte* elem; // data element | 26 byte* elem; // data element |
26 }; | 27 }; |
27 | 28 |
28 struct WaitQ | 29 struct WaitQ |
29 { | 30 { |
30 SudoG* first; | 31 SudoG* first; |
31 SudoG* last; | 32 SudoG* last; |
32 }; | 33 }; |
33 | 34 |
34 struct Hchan | 35 struct Hchan |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 * when a channel involved in the sleep has | 148 * when a channel involved in the sleep has |
148 * been closed. it is easiest to loop and re-run | 149 * been closed. it is easiest to loop and re-run |
149 * the operation; we'll see that it's now closed. | 150 * the operation; we'll see that it's now closed. |
150 */ | 151 */ |
151 void | 152 void |
152 runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres) | 153 runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres) |
153 { | 154 { |
154 SudoG *sg; | 155 SudoG *sg; |
155 SudoG mysg; | 156 SudoG mysg; |
156 G* gp; | 157 G* gp; |
| 158 int64 t0; |
157 | 159 |
158 if(c == nil) { | 160 if(c == nil) { |
159 USED(t); | 161 USED(t); |
160 if(pres != nil) { | 162 if(pres != nil) { |
161 *pres = false; | 163 *pres = false; |
162 return; | 164 return; |
163 } | 165 } |
164 runtime·park(nil, nil, "chan send (nil chan)"); | 166 runtime·park(nil, nil, "chan send (nil chan)"); |
165 return; // not reached | 167 return; // not reached |
166 } | 168 } |
167 | 169 |
168 if(runtime·gcwaiting) | 170 if(runtime·gcwaiting) |
169 runtime·gosched(); | 171 runtime·gosched(); |
170 | 172 |
171 if(debug) { | 173 if(debug) { |
172 runtime·printf("chansend: chan=%p; elem=", c); | 174 runtime·printf("chansend: chan=%p; elem=", c); |
173 c->elemalg->print(c->elemsize, ep); | 175 c->elemalg->print(c->elemsize, ep); |
174 runtime·prints("\n"); | 176 runtime·prints("\n"); |
175 } | 177 } |
176 | 178 |
| 179 t0 = 0; |
| 180 mysg.releasetime = 0; |
| 181 if(runtime·blockprofilerate > 0) { |
| 182 t0 = runtime·cputicks(); |
| 183 mysg.releasetime = -1; |
| 184 } |
| 185 |
177 runtime·lock(c); | 186 runtime·lock(c); |
178 if(c->closed) | 187 if(c->closed) |
179 goto closed; | 188 goto closed; |
180 | 189 |
181 if(c->dataqsiz > 0) | 190 if(c->dataqsiz > 0) |
182 goto asynch; | 191 goto asynch; |
183 | 192 |
184 sg = dequeue(&c->recvq); | 193 sg = dequeue(&c->recvq); |
185 if(sg != nil) { | 194 if(sg != nil) { |
186 runtime·unlock(c); | 195 runtime·unlock(c); |
187 | 196 |
188 gp = sg->g; | 197 gp = sg->g; |
189 gp->param = sg; | 198 gp->param = sg; |
190 if(sg->elem != nil) | 199 if(sg->elem != nil) |
191 c->elemalg->copy(c->elemsize, sg->elem, ep); | 200 c->elemalg->copy(c->elemsize, sg->elem, ep); |
| 201 if(sg->releasetime) |
| 202 sg->releasetime = runtime·cputicks(); |
192 runtime·ready(gp); | 203 runtime·ready(gp); |
193 | 204 |
194 if(pres != nil) | 205 if(pres != nil) |
195 *pres = true; | 206 *pres = true; |
196 return; | 207 return; |
197 } | 208 } |
198 | 209 |
199 if(pres != nil) { | 210 if(pres != nil) { |
200 runtime·unlock(c); | 211 runtime·unlock(c); |
201 *pres = false; | 212 *pres = false; |
202 return; | 213 return; |
203 } | 214 } |
204 | 215 |
205 mysg.elem = ep; | 216 mysg.elem = ep; |
206 mysg.g = g; | 217 mysg.g = g; |
207 mysg.selgen = NOSELGEN; | 218 mysg.selgen = NOSELGEN; |
208 g->param = nil; | 219 g->param = nil; |
209 enqueue(&c->sendq, &mysg); | 220 enqueue(&c->sendq, &mysg); |
210 runtime·park(runtime·unlock, c, "chan send"); | 221 runtime·park(runtime·unlock, c, "chan send"); |
211 | 222 |
212 if(g->param == nil) { | 223 if(g->param == nil) { |
213 runtime·lock(c); | 224 runtime·lock(c); |
214 if(!c->closed) | 225 if(!c->closed) |
215 runtime·throw("chansend: spurious wakeup"); | 226 runtime·throw("chansend: spurious wakeup"); |
216 goto closed; | 227 goto closed; |
217 } | 228 } |
| 229 |
| 230 if(mysg.releasetime > 0) |
| 231 runtime·blockevent(mysg.releasetime - t0, 2); |
218 | 232 |
219 return; | 233 return; |
220 | 234 |
221 asynch: | 235 asynch: |
222 if(c->closed) | 236 if(c->closed) |
223 goto closed; | 237 goto closed; |
224 | 238 |
225 if(c->qcount >= c->dataqsiz) { | 239 if(c->qcount >= c->dataqsiz) { |
226 if(pres != nil) { | 240 if(pres != nil) { |
227 runtime·unlock(c); | 241 runtime·unlock(c); |
(...skipping 11 matching lines...) Expand all Loading... |
239 } | 253 } |
240 c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep); | 254 c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep); |
241 if(++c->sendx == c->dataqsiz) | 255 if(++c->sendx == c->dataqsiz) |
242 c->sendx = 0; | 256 c->sendx = 0; |
243 c->qcount++; | 257 c->qcount++; |
244 | 258 |
245 sg = dequeue(&c->recvq); | 259 sg = dequeue(&c->recvq); |
246 if(sg != nil) { | 260 if(sg != nil) { |
247 gp = sg->g; | 261 gp = sg->g; |
248 runtime·unlock(c); | 262 runtime·unlock(c); |
| 263 if(sg->releasetime) |
| 264 sg->releasetime = runtime·cputicks(); |
249 runtime·ready(gp); | 265 runtime·ready(gp); |
250 } else | 266 } else |
251 runtime·unlock(c); | 267 runtime·unlock(c); |
252 if(pres != nil) | 268 if(pres != nil) |
253 *pres = true; | 269 *pres = true; |
| 270 if(mysg.releasetime > 0) |
| 271 runtime·blockevent(mysg.releasetime - t0, 2); |
254 return; | 272 return; |
255 | 273 |
256 closed: | 274 closed: |
257 runtime·unlock(c); | 275 runtime·unlock(c); |
258 runtime·panicstring("send on closed channel"); | 276 runtime·panicstring("send on closed channel"); |
259 } | 277 } |
260 | 278 |
261 | 279 |
262 void | 280 void |
263 runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
) | 281 runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
) |
264 { | 282 { |
265 SudoG *sg; | 283 SudoG *sg; |
266 SudoG mysg; | 284 SudoG mysg; |
267 G *gp; | 285 G *gp; |
| 286 int64 t0; |
268 | 287 |
269 if(runtime·gcwaiting) | 288 if(runtime·gcwaiting) |
270 runtime·gosched(); | 289 runtime·gosched(); |
271 | 290 |
272 if(debug) | 291 if(debug) |
273 runtime·printf("chanrecv: chan=%p\n", c); | 292 runtime·printf("chanrecv: chan=%p\n", c); |
274 | 293 |
275 if(c == nil) { | 294 if(c == nil) { |
276 USED(t); | 295 USED(t); |
277 if(selected != nil) { | 296 if(selected != nil) { |
278 *selected = false; | 297 *selected = false; |
279 return; | 298 return; |
280 } | 299 } |
281 runtime·park(nil, nil, "chan receive (nil chan)"); | 300 runtime·park(nil, nil, "chan receive (nil chan)"); |
282 return; // not reached | 301 return; // not reached |
283 } | 302 } |
284 | 303 |
| 304 t0 = 0; |
| 305 mysg.releasetime = 0; |
| 306 if(runtime·blockprofilerate > 0) { |
| 307 t0 = runtime·cputicks(); |
| 308 mysg.releasetime = -1; |
| 309 } |
| 310 |
285 runtime·lock(c); | 311 runtime·lock(c); |
286 if(c->dataqsiz > 0) | 312 if(c->dataqsiz > 0) |
287 goto asynch; | 313 goto asynch; |
288 | 314 |
289 if(c->closed) | 315 if(c->closed) |
290 goto closed; | 316 goto closed; |
291 | 317 |
292 sg = dequeue(&c->sendq); | 318 sg = dequeue(&c->sendq); |
293 if(sg != nil) { | 319 if(sg != nil) { |
294 runtime·unlock(c); | 320 runtime·unlock(c); |
295 | 321 |
296 if(ep != nil) | 322 if(ep != nil) |
297 c->elemalg->copy(c->elemsize, ep, sg->elem); | 323 c->elemalg->copy(c->elemsize, ep, sg->elem); |
298 gp = sg->g; | 324 gp = sg->g; |
299 gp->param = sg; | 325 gp->param = sg; |
| 326 if(sg->releasetime) |
| 327 sg->releasetime = runtime·cputicks(); |
300 runtime·ready(gp); | 328 runtime·ready(gp); |
301 | 329 |
302 if(selected != nil) | 330 if(selected != nil) |
303 *selected = true; | 331 *selected = true; |
304 if(received != nil) | 332 if(received != nil) |
305 *received = true; | 333 *received = true; |
306 return; | 334 return; |
307 } | 335 } |
308 | 336 |
309 if(selected != nil) { | 337 if(selected != nil) { |
(...skipping 11 matching lines...) Expand all Loading... |
321 | 349 |
322 if(g->param == nil) { | 350 if(g->param == nil) { |
323 runtime·lock(c); | 351 runtime·lock(c); |
324 if(!c->closed) | 352 if(!c->closed) |
325 runtime·throw("chanrecv: spurious wakeup"); | 353 runtime·throw("chanrecv: spurious wakeup"); |
326 goto closed; | 354 goto closed; |
327 } | 355 } |
328 | 356 |
329 if(received != nil) | 357 if(received != nil) |
330 *received = true; | 358 *received = true; |
| 359 if(mysg.releasetime > 0) |
| 360 runtime·blockevent(mysg.releasetime - t0, 2); |
331 return; | 361 return; |
332 | 362 |
333 asynch: | 363 asynch: |
334 if(c->qcount <= 0) { | 364 if(c->qcount <= 0) { |
335 if(c->closed) | 365 if(c->closed) |
336 goto closed; | 366 goto closed; |
337 | 367 |
338 if(selected != nil) { | 368 if(selected != nil) { |
339 runtime·unlock(c); | 369 runtime·unlock(c); |
340 *selected = false; | 370 *selected = false; |
(...skipping 14 matching lines...) Expand all Loading... |
355 c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); | 385 c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); |
356 c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); | 386 c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); |
357 if(++c->recvx == c->dataqsiz) | 387 if(++c->recvx == c->dataqsiz) |
358 c->recvx = 0; | 388 c->recvx = 0; |
359 c->qcount--; | 389 c->qcount--; |
360 | 390 |
361 sg = dequeue(&c->sendq); | 391 sg = dequeue(&c->sendq); |
362 if(sg != nil) { | 392 if(sg != nil) { |
363 gp = sg->g; | 393 gp = sg->g; |
364 runtime·unlock(c); | 394 runtime·unlock(c); |
| 395 if(sg->releasetime) |
| 396 sg->releasetime = runtime·cputicks(); |
365 runtime·ready(gp); | 397 runtime·ready(gp); |
366 } else | 398 } else |
367 runtime·unlock(c); | 399 runtime·unlock(c); |
368 | 400 |
369 if(selected != nil) | 401 if(selected != nil) |
370 *selected = true; | 402 *selected = true; |
371 if(received != nil) | 403 if(received != nil) |
372 *received = true; | 404 *received = true; |
| 405 if(mysg.releasetime > 0) |
| 406 runtime·blockevent(mysg.releasetime - t0, 2); |
373 return; | 407 return; |
374 | 408 |
375 closed: | 409 closed: |
376 if(ep != nil) | 410 if(ep != nil) |
377 c->elemalg->copy(c->elemsize, ep, nil); | 411 c->elemalg->copy(c->elemsize, ep, nil); |
378 if(selected != nil) | 412 if(selected != nil) |
379 *selected = true; | 413 *selected = true; |
380 if(received != nil) | 414 if(received != nil) |
381 *received = false; | 415 *received = false; |
382 runtime·unlock(c); | 416 runtime·unlock(c); |
| 417 if(mysg.releasetime > 0) |
| 418 runtime·blockevent(mysg.releasetime - t0, 2); |
383 } | 419 } |
384 | 420 |
385 // chansend1(hchan *chan any, elem any); | 421 // chansend1(hchan *chan any, elem any); |
386 #pragma textflag 7 | 422 #pragma textflag 7 |
387 void | 423 void |
388 runtime·chansend1(ChanType *t, Hchan* c, ...) | 424 runtime·chansend1(ChanType *t, Hchan* c, ...) |
389 { | 425 { |
390 runtime·chansend(t, c, (byte*)(&c+1), nil); | 426 runtime·chansend(t, c, (byte*)(&c+1), nil); |
391 } | 427 } |
392 | 428 |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 { | 1261 { |
1226 sgp->link = nil; | 1262 sgp->link = nil; |
1227 if(q->first == nil) { | 1263 if(q->first == nil) { |
1228 q->first = sgp; | 1264 q->first = sgp; |
1229 q->last = sgp; | 1265 q->last = sgp; |
1230 return; | 1266 return; |
1231 } | 1267 } |
1232 q->last->link = sgp; | 1268 q->last->link = sgp; |
1233 q->last = sgp; | 1269 q->last = sgp; |
1234 } | 1270 } |
LEFT | RIGHT |