summaryrefslogtreecommitdiff
path: root/sys/src/ape
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-07-07 19:53:26 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-07-07 19:53:26 +0200
commitcd92790c50433ee99fc3a3b3a95792e1daf2aed1 (patch)
treeb660b045e948d522e9e0bc3c53d4e0ca068fe76e /sys/src/ape
parent65061470665b3f91f01d23bad6a54704e8aa5851 (diff)
ape: port libc smp tas() for arm
Diffstat (limited to 'sys/src/ape')
-rw-r--r--sys/src/ape/lib/ap/arm/lock.c78
-rw-r--r--sys/src/ape/lib/ap/arm/tas.s17
2 files changed, 85 insertions, 10 deletions
diff --git a/sys/src/ape/lib/ap/arm/lock.c b/sys/src/ape/lib/ap/arm/lock.c
index 91c0ba233..d601e00da 100644
--- a/sys/src/ape/lib/ap/arm/lock.c
+++ b/sys/src/ape/lib/ap/arm/lock.c
@@ -2,25 +2,91 @@
#include "../plan9/sys9.h"
#include <lock.h>
-int tas(int*);
+int tas(int*); /* tas.s */
+
+static long lockinit(long);
+
+/*
+ * barrier is called from tas.s assembly
+ * to execute memory barrier.
+ */
+long (*_barrier)(long) = lockinit;
+
+static int
+cpus(void)
+{
+ char buf[256], *p;
+ int f, n;
+
+ f = _OPEN("#c/sysstat", 0);
+ if(f < 0)
+ return -1;
+ n = _READ(f, buf, sizeof(buf)-1);
+ _CLOSE(f);
+ if(n <= 0)
+ return -1;
+ buf[n] = '\0';
+ n = 0;
+ p = buf;
+ while(*p != '\0'){
+ if(*p == '\n')
+ n++;
+ p++;
+ }
+ return n;
+}
+
+long _dmb(long);
+
+static long
+_nop(long r0)
+{
+ return r0;
+}
+
+static long
+lockinit(long r0)
+{
+ if(cpus() > 1)
+ _barrier = _dmb;
+ else
+ _barrier = _nop;
+ return (*_barrier)(r0);
+}
void
lock(Lock *lk)
{
- while(tas(&lk->val))
+ 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);
+ }
+ /* take your time */
+ while(tas(&lk->val))
+ _SLEEP(1000);
}
int
canlock(Lock *lk)
{
- if(tas(&lk->val))
- return 0;
- return 1;
+ return tas(&lk->val) == 0;
}
void
unlock(Lock *lk)
{
- lk->val = 0;
+ lk->val = (*_barrier)(0);
}
diff --git a/sys/src/ape/lib/ap/arm/tas.s b/sys/src/ape/lib/ap/arm/tas.s
index f1269209e..25d0e1cfe 100644
--- a/sys/src/ape/lib/ap/arm/tas.s
+++ b/sys/src/ape/lib/ap/arm/tas.s
@@ -1,5 +1,14 @@
-TEXT tas(SB), $-4
- MOVW R0,R1
- MOVW $1,R0
- SWPW R0,(R1)
+TEXT tas(SB), 1, $-4
+ MOVW $1, R2
+_tas1:
+ LDREX (R0), R1
+ STREX R2, (R0), R3
+ CMP.S $0, R3
+ BNE _tas1
+ MOVW R1, R0
+ MOVW _barrier(SB), R4
+ B (R4)
+
+TEXT _dmb(SB), 1, $-4
+ WORD $0xf57ff05f
RET