diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:55:52 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-21 19:55:52 +0200 |
commit | f811708ffcb776be52a81637224c06b700177566 (patch) | |
tree | 05a9632fef0f4e5ad835c2e6d426631e485e90d1 /sys/src/ape/lib/ap/mips | |
parent | 3d05e77ca1f743e5b4091c6bfe311460175ed9ae (diff) |
ape: change tas/sleep locks to cas/semacquire/semrelease locks (from sources)
Diffstat (limited to 'sys/src/ape/lib/ap/mips')
-rw-r--r-- | sys/src/ape/lib/ap/mips/atom.s | 52 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/mips/lock.c | 178 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/mips/mkfile | 1 | ||||
-rw-r--r-- | sys/src/ape/lib/ap/mips/tas.s | 1 |
4 files changed, 75 insertions, 157 deletions
diff --git a/sys/src/ape/lib/ap/mips/atom.s b/sys/src/ape/lib/ap/mips/atom.s new file mode 100644 index 000000000..b907f7f59 --- /dev/null +++ b/sys/src/ape/lib/ap/mips/atom.s @@ -0,0 +1,52 @@ +/* + * R4000 user-level atomic operations + */ + +#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16)) +#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16)) +#define NOOP WORD $0x27 + +TEXT ainc(SB), 1, $-4 /* long ainc(long *); */ +TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */ + MOVW R1, R2 /* address of counter */ +loop: MOVW $1, R3 + LL(2, 1) + NOOP + ADDU R1, R3 + MOVW R3, R1 /* return new value */ + SC(2, 3) + NOOP + BEQ R3,loop + RET + +TEXT adec(SB), 1, $-4 /* long adec(long*); */ +TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */ + MOVW R1, R2 /* address of counter */ +loop1: MOVW $-1, R3 + LL(2, 1) + NOOP + ADDU R1, R3 + MOVW R3, R1 /* return new value */ + SC(2, 3) + NOOP + BEQ R3,loop1 + RET + +/* + * int cas(uint* p, int ov, int nv); + */ +TEXT cas(SB), 1, $-4 + MOVW ov+4(FP), R2 + MOVW nv+8(FP), R3 +spincas: + LL(1, 4) /* R4 = *R1 */ + NOOP + BNE R2, R4, fail + SC(1, 3) /* *R1 = R3 */ + NOOP + BEQ R3, spincas /* R3 == 0 means store failed */ + MOVW $1, R1 + RET +fail: + MOVW $0, R1 + RET diff --git a/sys/src/ape/lib/ap/mips/lock.c b/sys/src/ape/lib/ap/mips/lock.c index 866d074e9..65a65df7b 100644 --- a/sys/src/ape/lib/ap/mips/lock.c +++ b/sys/src/ape/lib/ap/mips/lock.c @@ -1,171 +1,35 @@ -#define _LOCK_EXTENSION -#include <stdlib.h> -#include <string.h> +#include "../plan9/lib.h" #include "../plan9/sys9.h" +#define _LOCK_EXTENSION #include <lock.h> -enum -{ - Pagesize = 4096, - Semperpg = Pagesize/(16*sizeof(unsigned int)), - Lockaddr = 0x60000000, - - POWER = 0x320, - MAGNUM = 0x330, - MAGNUMII = 0x340, - R4K = 0x500, -}; - -static int arch; -extern int C_3ktas(int*); -extern int C_4ktas(int*); -extern int C_fcr0(void); - -static void -lockinit(void) -{ - int n; - - if(arch != 0) - return; /* allow multiple calls */ - arch = C_fcr0(); - switch(arch) { - case POWER: - if(_SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize) == (void*)-1) { - arch = MAGNUM; - break; - } - memset((void*)Lockaddr, 0, Pagesize); - break; - case MAGNUM: - case MAGNUMII: - case R4K: - break; - default: - abort(); - } - -} - void -lock(Lock *lk) +lock(Lock *l) { - int *hwsem; - int hash; - -retry: - switch(arch) { - case 0: - lockinit(); - goto retry; - case MAGNUM: - case MAGNUMII: - while(C_3ktas(&lk->val)) - _SLEEP(0); - return; - case R4K: - for(;;){ - while(lk->val) - ; - if(C_4ktas(&lk->val) == 0) - return; - } - break; - case POWER: - /* Use low order lock bits to generate hash */ - hash = ((int)lk/sizeof(int)) & (Semperpg-1); - hwsem = (int*)Lockaddr+hash; - - for(;;) { - if((*hwsem & 1) == 0) { - if(lk->val) - *hwsem = 0; - else { - lk->val = 1; - *hwsem = 0; - return; - } - } - while(lk->val) - ; - } - } -} - -int -canlock(Lock *lk) -{ - int *hwsem; - int hash; - -retry: - switch(arch) { - case 0: - lockinit(); - goto retry; - case MAGNUM: - case MAGNUMII: - if(C_3ktas(&lk->val)) - return 0; - return 1; - case R4K: - if(C_4ktas(&lk->val)) - return 0; - return 1; - case POWER: - /* Use low order lock bits to generate hash */ - hash = ((int)lk/sizeof(int)) & (Semperpg-1); - hwsem = (int*)Lockaddr+hash; - - if((*hwsem & 1) == 0) { - if(lk->val) - *hwsem = 0; - else { - lk->val = 1; - *hwsem = 0; - return 1; - } - } - return 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 */ + } } void -unlock(Lock *lk) +unlock(Lock *l) { - lk->val = 0; + if(adec(&l->key) == 0) + return; /* changed from 1 -> 0: no contention */ + _SEMRELEASE(&l->sem, 1); } int -tas(int *p) +canlock(Lock *l) { - int *hwsem; - int hash; - -retry: - switch(arch) { - case 0: - lockinit(); - goto retry; - case MAGNUM: - case MAGNUMII: - return C_3ktas(p); - case R4K: - return C_4ktas(p); - case POWER: - /* Use low order lock bits to generate hash */ - hash = ((int)p/sizeof(int)) & (Semperpg-1); - hwsem = (int*)Lockaddr+hash; - - if((*hwsem & 1) == 0) { - if(*p) - *hwsem = 0; - else { - *p = 1; - *hwsem = 0; - return 0; - } - } - return 1; - } + 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/mips/mkfile b/sys/src/ape/lib/ap/mips/mkfile index 0896229a6..5d24b767f 100644 --- a/sys/src/ape/lib/ap/mips/mkfile +++ b/sys/src/ape/lib/ap/mips/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\ diff --git a/sys/src/ape/lib/ap/mips/tas.s b/sys/src/ape/lib/ap/mips/tas.s index d754b21f6..448cbe068 100644 --- a/sys/src/ape/lib/ap/mips/tas.s +++ b/sys/src/ape/lib/ap/mips/tas.s @@ -17,6 +17,7 @@ btas: BLTZ R1, btas RET + TEXT tas(SB),$0 TEXT C_4ktas(SB), $0 MOVW R1, R2 /* address of key */ tas1: |