summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/mips/lock.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/mips/lock.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/mips/lock.c')
-rwxr-xr-xsys/src/ape/lib/ap/mips/lock.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/mips/lock.c b/sys/src/ape/lib/ap/mips/lock.c
new file mode 100755
index 000000000..f0ecbe22a
--- /dev/null
+++ b/sys/src/ape/lib/ap/mips/lock.c
@@ -0,0 +1,172 @@
+#define _LOCK_EXTENSION
+#include <stdlib.h>
+#include <string.h>
+#include "../plan9/sys9.h"
+#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:
+ n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize);
+ if(n < 0) {
+ arch = MAGNUM;
+ break;
+ }
+ memset((void*)Lockaddr, 0, Pagesize);
+ break;
+ case MAGNUM:
+ case MAGNUMII:
+ case R4K:
+ break;
+ default:
+ abort();
+ }
+
+}
+
+void
+lock(Lock *lk)
+{
+ 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;
+ }
+}
+
+void
+unlock(Lock *lk)
+{
+ lk->val = 0;
+}
+
+int
+tas(int *p)
+{
+ 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;
+ }
+}