diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-26 22:24:31 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-09-26 22:24:31 +0200 |
commit | cdc2c30e99f2fb3d65dfbc8ef73efd433a3f1966 (patch) | |
tree | 5c3d5a6a42311f09444ca34d09bfebc78e08f5a3 /sys/src/ape/lib/ap/mips/lock.c | |
parent | b4cdfc6c5517390d6be05b2c01e56bacc9e85ea8 (diff) |
reverting semaphore lock changes from sources (r41ccd6d221da, rb28756e5ba29)
semaphore locks have much higher overhead than initially presented
in the "Semaphores in Plan9" paper. until the reason for it has been
found out i will revert the changes.
Diffstat (limited to 'sys/src/ape/lib/ap/mips/lock.c')
-rw-r--r-- | sys/src/ape/lib/ap/mips/lock.c | 178 |
1 files changed, 157 insertions, 21 deletions
diff --git a/sys/src/ape/lib/ap/mips/lock.c b/sys/src/ape/lib/ap/mips/lock.c index 65a65df7b..866d074e9 100644 --- a/sys/src/ape/lib/ap/mips/lock.c +++ b/sys/src/ape/lib/ap/mips/lock.c @@ -1,35 +1,171 @@ -#include "../plan9/lib.h" -#include "../plan9/sys9.h" #define _LOCK_EXTENSION +#include <stdlib.h> +#include <string.h> +#include "../plan9/sys9.h" #include <lock.h> -void -lock(Lock *l) +enum { - 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 */ + 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) +{ + 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 *l) +unlock(Lock *lk) { - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - _SEMRELEASE(&l->sem, 1); + lk->val = 0; } int -canlock(Lock *l) +tas(int *p) { - 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; + 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; + } } |