ref: cd92790c50433ee99fc3a3b3a95792e1daf2aed1
parent: 65061470665b3f91f01d23bad6a54704e8aa5851
author: cinap_lenrek <[email protected]>
date: Tue Jul 7 15:53:26 EDT 2015
ape: port libc smp tas() for arm
--- 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);
}
--- 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