enum
{
ESRCH = 3,
+ EAGAIN = 35,
+ EWOULDBLOCK = EAGAIN,
ENOTSUP = 91,
// From OpenBSD's sys/time.h
int32
runtime·semasleep(int64 ns)
{
- Timespec ts;
-
- // spin-mutex lock
- while(runtime·xchg(&g->m->waitsemalock, 1))
- runtime·osyield();
+ Timespec ts, *tsp = nil;
+
+ // Compute sleep deadline.
+ if(ns >= 0) {
+ int32 nsec;
+ ns += runtime·nanotime();
+ ts.tv_sec = runtime·timediv(ns, 1000000000, &nsec);
+ ts.tv_nsec = nsec; // tv_nsec is int64 on amd64
+ tsp = &ts;
+ }
for(;;) {
- // lock held
- if(g->m->waitsemacount == 0) {
- // sleep until semaphore != 0 or timeout.
- // thrsleep unlocks m->waitsemalock.
- if(ns < 0)
- runtime·thrsleep(&g->m->waitsemacount, 0, nil, &g->m->waitsemalock, nil);
- else {
- ns += runtime·nanotime();
- // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
- ts.tv_nsec = 0;
- ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
- runtime·thrsleep(&g->m->waitsemacount, CLOCK_MONOTONIC, &ts, &g->m->waitsemalock, nil);
- }
- // reacquire lock
- while(runtime·xchg(&g->m->waitsemalock, 1))
- runtime·osyield();
- }
+ int32 ret;
+
+ // spin-mutex lock
+ while(runtime·xchg(&g->m->waitsemalock, 1))
+ runtime·osyield();
- // lock held (again)
if(g->m->waitsemacount != 0) {
// semaphore is available.
g->m->waitsemacount--;
return 0; // semaphore acquired
}
- // semaphore not available.
- // if there is a timeout, stop now.
- // otherwise keep trying.
- if(ns >= 0)
- break;
+ // sleep until semaphore != 0 or timeout.
+ // thrsleep unlocks m->waitsemalock.
+ ret = runtime·thrsleep(&g->m->waitsemacount, CLOCK_MONOTONIC, tsp, &g->m->waitsemalock, (int32 *)&g->m->waitsemacount);
+ if(ret == EWOULDBLOCK)
+ return -1;
}
-
- // lock held but giving up
- // spin-mutex unlock
- runtime·atomicstore(&g->m->waitsemalock, 0);
- return -1;
}
static void badsemawakeup(void);