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/arm | |
parent | 3d05e77ca1f743e5b4091c6bfe311460175ed9ae (diff) |
ape: change tas/sleep locks to cas/semacquire/semrelease locks (from sources)
Diffstat (limited to 'sys/src/ape/lib/ap/arm')
-rw-r--r-- | sys/src/ape/lib/ap/arm/atom.s | 58 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/arm/lock.c | 37 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/arm/mkfile | 1 |
3 files changed, 82 insertions, 14 deletions
diff --git a/sys/src/ape/lib/ap/arm/atom.s b/sys/src/ape/lib/ap/arm/atom.s new file mode 100644 index 000000000..b59a89d90 --- /dev/null +++ b/sys/src/ape/lib/ap/arm/atom.s @@ -0,0 +1,58 @@ +#define CLREX WORD $0xf57ff01f +#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) +/* `The order of operands is from left to right in dataflow order' - asm man */ +#define STREX(v,a,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0) + +/* + * int cas(ulong *p, ulong ov, ulong nv); + */ + +TEXT cas+0(SB),0,$0 /* r0 holds p */ +TEXT casp+0(SB),0,$0 /* r0 holds p */ + MOVW ov+4(FP), R1 + MOVW nv+8(FP), R2 +spincas: + LDREX(0,3) /* LDREX 0(R0),R3 */ + CMP.S R3, R1 + BNE fail + STREX(2,0,4) /* STREX 0(R0),R2,R4 */ + CMP.S $0, R4 + BNE spincas + MOVW $1, R0 + RET +fail: + CLREX + MOVW $0, R0 + RET + +TEXT _xinc(SB), $0 /* void _xinc(long *); */ +TEXT ainc(SB), $0 /* long ainc(long *); */ +spinainc: + LDREX(0,3) /* LDREX 0(R0),R3 */ + ADD $1,R3 + STREX(3,0,4) /* STREX 0(R0),R3,R4 */ + CMP.S $0, R4 + BNE spinainc + MOVW R3, R0 + RET + +TEXT _xdec(SB), $0 /* long _xdec(long *); */ +TEXT adec(SB), $0 /* long adec(long *); */ +spinadec: + LDREX(0,3) /* LDREX 0(R0),R3 */ + SUB $1,R3 + STREX(3,0,4) /* STREX 0(R0),R3,R4 */ + CMP.S $0, R4 + BNE spinadec + MOVW R3, R0 + RET + +TEXT loadlinked(SB), $0 /* long loadlinked(long *); */ + LDREX(0,0) /* LDREX 0(R0),R0 */ + RET + +TEXT storecond(SB), $0 /* int storecond(long *, long); */ + MOVW ov+4(FP), R3 + STREX(3,0,0) /* STREX 0(R0),R3,R0 */ + RSB $1, R0 + RET diff --git a/sys/src/ape/lib/ap/arm/lock.c b/sys/src/ape/lib/ap/arm/lock.c index 91c0ba233..65a65df7b 100644 --- a/sys/src/ape/lib/ap/arm/lock.c +++ b/sys/src/ape/lib/ap/arm/lock.c @@ -1,26 +1,35 @@ -#define _LOCK_EXTENSION +#include "../plan9/lib.h" #include "../plan9/sys9.h" +#define _LOCK_EXTENSION #include <lock.h> -int tas(int*); - void -lock(Lock *lk) +lock(Lock *l) { - while(tas(&lk->val)) - _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 */ + } } -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/arm/mkfile b/sys/src/ape/lib/ap/arm/mkfile index f65e34395..97d0fa80b 100644 --- a/sys/src/ape/lib/ap/arm/mkfile +++ b/sys/src/ape/lib/ap/arm/mkfile @@ -2,6 +2,7 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ cycles.$O\ div.$O\ getfcr.$O\ |