// releases the lock by decrementing l->key, l->key will
// be >0, so it will increment the semaphore to wake up
// one of the others. This is the same algorithm used
-// in Plan 9's user-space locks.
+// in Plan 9's user-level locks.
//
// Note that semaphores are never destroyed (the kernel
// will clean up when the process exits). We assume for now
}
+// User-level semaphore implementation:
+// try to do the operations in user space on u,
+// but when it's time to block, fall back on the kernel semaphore k.
+// This is the same algorithm used in Plan 9.
+void
+usemacquire(Usema *s)
+{
+ if((int32)xadd(&s->u, -1) < 0)
+ semacquire(s->k);
+}
+
+void
+usemrelease(Usema *s)
+{
+ if((int32)xadd(&s->u, 1) <= 0)
+ semrelease(s->k);
+}
+
+
// Event notifications.
void
noteclear(Note *n)
void
notesleep(Note *n)
{
- if(n->sema == 0)
- initsema(&n->sema);
+ if(n->sema.k == 0)
+ initsema(&n->sema.k);
while(!n->wakeup)
- semacquire(n->sema);
+ usemacquire(&n->sema);
}
void
notewakeup(Note *n)
{
- if(n->sema == 0)
- initsema(&n->sema);
+ if(n->sema.k == 0)
+ initsema(&n->sema.k);
n->wakeup = 1;
- semrelease(n->sema);
+ usemrelease(&n->sema);
}