summaryrefslogtreecommitdiff
path: root/sys/src/libc/port/lock.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-09-21 19:53:27 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-09-21 19:53:27 +0200
commit3d05e77ca1f743e5b4091c6bfe311460175ed9ae (patch)
treed17a262c559e389e3adb6171de308800eb9d3426 /sys/src/libc/port/lock.c
parent041e4852d258f05fe5f60964a76c99714905774e (diff)
libc: change tas/sleep locks to cas/semacquire/semrelease locks (from sources)
spinlocks have been changed to use the new semacquire/semrelease syscalls in combination with atomic compare and swap operations.
Diffstat (limited to 'sys/src/libc/port/lock.c')
-rw-r--r--sys/src/libc/port/lock.c48
1 files changed, 20 insertions, 28 deletions
diff --git a/sys/src/libc/port/lock.c b/sys/src/libc/port/lock.c
index af07b9cc7..213fcd778 100644
--- a/sys/src/libc/port/lock.c
+++ b/sys/src/libc/port/lock.c
@@ -2,40 +2,32 @@
#include <libc.h>
void
-lock(Lock *lk)
+lock(Lock *l)
{
- int i;
-
- /* once fast */
- if(!_tas(&lk->val))
- return;
- /* a thousand times pretty fast */
- for(i=0; i<1000; i++){
- if(!_tas(&lk->val))
- return;
- sleep(0);
- }
- /* now nice and slow */
- for(i=0; i<1000; i++){
- if(!_tas(&lk->val))
- return;
- sleep(100);
+ if(ainc(&l->key) == 1)
+ return; /* changed from 0 -> 1: we hold lock */
+ /* otherwise wait in kernel */
+ while(semacquire(&l->sem, 1) < 0){
+ /* interrupted; try again */
}
- /* take your time */
- while(_tas(&lk->val))
- sleep(1000);
}
-int
-canlock(Lock *lk)
+void
+unlock(Lock *l)
{
- if(_tas(&lk->val))
- return 0;
- return 1;
+ if(adec(&l->key) == 0)
+ return; /* changed from 1 -> 0: no contention */
+ semrelease(&l->sem, 1);
}
-void
-unlock(Lock *lk)
+int
+canlock(Lock *l)
{
- lk->val = 0;
+ if(ainc(&l->key) == 1)
+ return 1; /* changed from 0 -> 1: success */
+ /* Undo increment (but don't miss wakeup) */
+ if(adec(&l->key) == 0)
+ return 0; /* changed from 1 -> 0: no contention */
+ semrelease(&l->sem, 1);
+ return 0;
}