diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:55:52 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:55:52 +0200 |
commit | f811708ffcb776be52a81637224c06b700177566 (patch) | |
tree | 05a9632fef0f4e5ad835c2e6d426631e485e90d1 /sys/src/ape/lib/ap/power | |
parent | 3d05e77ca1f743e5b4091c6bfe311460175ed9ae (diff) |
ape: change tas/sleep locks to cas/semacquire/semrelease locks (from sources)
Diffstat (limited to 'sys/src/ape/lib/ap/power')
-rw-r--r-- | sys/src/ape/lib/ap/power/atom.s | 63 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/power/lock.c | 50 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/power/main9p.s | 2 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/power/mkfile | 1 |
4 files changed, 85 insertions, 31 deletions
diff --git a/sys/src/ape/lib/ap/power/atom.s b/sys/src/ape/lib/ap/power/atom.s new file mode 100644 index 000000000..b387300df --- /dev/null +++ b/sys/src/ape/lib/ap/power/atom.s @@ -0,0 +1,63 @@ +TEXT _xinc(SB),$0 /* void _xinc(long *); */ +TEXT ainc(SB),$0 /* long ainc(long *); */ + MOVW R3, R4 +xincloop: + LWAR (R4), R3 + ADD $1, R3 + DCBT (R4) /* fix 405 errata cpu_210 */ + STWCCC R3, (R4) + BNE xincloop + RETURN + +TEXT _xdec(SB),$0 /* long _xdec(long *); */ +TEXT adec(SB),$0 /* long adec(long *); */ + MOVW R3, R4 +xdecloop: + LWAR (R4), R3 + ADD $-1, R3 + DCBT (R4) /* fix 405 errata cpu_210 */ + STWCCC R3, (R4) + BNE xdecloop + RETURN + +TEXT loadlink(SB), $0 + + LWAR (R3), R3 + RETURN + +TEXT storecond(SB), $0 + + MOVW val+4(FP), R4 + DCBT (R3) /* fix 405 errata cpu_210 */ + STWCCC R4, (R3) + BNE storecondfail + MOVW $1, R3 + RETURN +storecondfail: + MOVW $0, R3 + RETURN + +/* + * int cas(uint *p, int ov, int nv); + * int casp(void **p, void *ov, void *nv); + */ + +TEXT cas+0(SB),0,$0 +TEXT casp+0(SB),0,$0 + MOVW ov+4(FP),R4 + MOVW nv+8(FP),R8 + LWAR (R3),R5 + CMP R5,R4 + BNE fail + DCBT (R3) /* fix 405 errata cpu_210 */ + STWCCC R8,(R3) + BNE fail1 + MOVW $1,R3 + RETURN +fail: + DCBT (R3) /* fix 405 errata cpu_210 */ + STWCCC R5,(R3) /* give up exclusive access */ +fail1: + MOVW R0,R3 + RETURN + END diff --git a/sys/src/ape/lib/ap/power/lock.c b/sys/src/ape/lib/ap/power/lock.c index 0d17c34d5..65a65df7b 100644 --- a/sys/src/ape/lib/ap/power/lock.c +++ b/sys/src/ape/lib/ap/power/lock.c @@ -3,43 +3,33 @@ #define _LOCK_EXTENSION #include <lock.h> -int tas(int*); - 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); + 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 */ } - /* now nice and slow */ - for(i=0; i<1000; i++){ - if(!tas(&lk->val)) - return; - _SLEEP(100); - } - /* 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; } diff --git a/sys/src/ape/lib/ap/power/main9p.s b/sys/src/ape/lib/ap/power/main9p.s index 4565b9d06..809ddc451 100644 --- a/sys/src/ape/lib/ap/power/main9p.s +++ b/sys/src/ape/lib/ap/power/main9p.s @@ -1,7 +1,7 @@ #define NPRIVATES 16 GLOBL _tos(SB), $4 -GLOBAL _errnoloc(SB), $4 +GLOBL _errnoloc(SB), $4 GLOBL _privates(SB), $4 GLOBL _nprivates(SB), $4 diff --git a/sys/src/ape/lib/ap/power/mkfile b/sys/src/ape/lib/ap/power/mkfile index cc546cd84..ab4b35df6 100644 --- a/sys/src/ape/lib/ap/power/mkfile +++ b/sys/src/ape/lib/ap/power/mkfile @@ -2,6 +2,7 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ cycles.$O\ getfcr.$O\ lock.$O\ |