summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/power
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/power
parent3d05e77ca1f743e5b4091c6bfe311460175ed9ae (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.s63
-rw-r--r--sys/src/ape/lib/ap/power/lock.c50
-rw-r--r--sys/src/ape/lib/ap/power/main9p.s2
-rw-r--r--sys/src/ape/lib/ap/power/mkfile1
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\