diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:53:27 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:53:27 +0200 |
commit | 3d05e77ca1f743e5b4091c6bfe311460175ed9ae (patch) | |
tree | d17a262c559e389e3adb6171de308800eb9d3426 /sys/src/libc/port/lock.c | |
parent | 041e4852d258f05fe5f60964a76c99714905774e (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.c | 48 |
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; } |