summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/mips
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/mips
parent3d05e77ca1f743e5b4091c6bfe311460175ed9ae (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.s52
-rw-r--r--sys/src/ape/lib/ap/mips/lock.c178
-rw-r--r--sys/src/ape/lib/ap/mips/mkfile1
-rw-r--r--sys/src/ape/lib/ap/mips/tas.s1
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: