summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/arm
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-09-21 19:55:52 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-09-21 19:55:52 +0200
commitf811708ffcb776be52a81637224c06b700177566 (patch)
tree05a9632fef0f4e5ad835c2e6d426631e485e90d1 /sys/src/ape/lib/ap/arm
parent3d05e77ca1f743e5b4091c6bfe311460175ed9ae (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.s58
-rw-r--r--sys/src/ape/lib/ap/arm/lock.c37
-rw-r--r--sys/src/ape/lib/ap/arm/mkfile1
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\