diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-07-07 19:53:26 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-07-07 19:53:26 +0200 |
commit | cd92790c50433ee99fc3a3b3a95792e1daf2aed1 (patch) | |
tree | b660b045e948d522e9e0bc3c53d4e0ca068fe76e /sys/src/ape | |
parent | 65061470665b3f91f01d23bad6a54704e8aa5851 (diff) |
ape: port libc smp tas() for arm
Diffstat (limited to 'sys/src/ape')
-rw-r--r-- | sys/src/ape/lib/ap/arm/lock.c | 78 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/arm/tas.s | 17 |
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 |