diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /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-x | sys/src/ape/lib/ap/mips/lock.c | 172 |
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; + } +} |