/* Acquire semaphore (subtract 1). */ static int semacquire(Segment *s, long *addr, int block) { int acquired; Sema phore; if(canacquire(addr)) return 1; if(!block) return 0; acquired = 0; semqueue(s, addr, &phore); for(;;){ phore.waiting = 1; coherence(); if(canacquire(addr)){ acquired = 1; break; } if(waserror()) break; sleep(&phore, semawoke, &phore); poperror(); } semdequeue(s, &phore); coherence(); /* not strictly necessary due to lock in semdequeue */ if(!phore.waiting) semwakeup(s, addr, 1); if(!acquired) nexterror(); return 1; }
/* Acquire semaphore or timeout */ static int tsemacquire(Segment *s, long *addr, ulong ms) { int acquired; Sema phore; int timedout; ulong t; ulong tsemdbg; if(canacquire(addr)) return 1; if(ms == 0) return 0; acquired = 0; timedout = 0; semqueue(s, addr, &phore); for(;;){ phore.waiting = 1; coherence(); if(canacquire(addr)){ acquired = 1; break; } if(waserror()) break; t = m->ticks; tsleep(&phore, semawoke, &phore, ms); if((tsemdbg = TK2MS(m->ticks - t)) >= ms){ timedout = 1; poperror(); break; } ms -= TK2MS(m->ticks - t); poperror(); } semdequeue(s, &phore); coherence(); /* not strictly necessary due to lock in semdequeue */ if(!phore.waiting) semwakeup(s, addr, 1); if(timedout) return 0; if(!acquired) nexterror(); return 1; }