1219b2ee8SDavid du Colombier #define _LOCK_EXTENSION 2219b2ee8SDavid du Colombier #include <stdlib.h> 3219b2ee8SDavid du Colombier #include <string.h> 4219b2ee8SDavid du Colombier #include "../plan9/sys9.h" 5219b2ee8SDavid du Colombier #include <lock.h> 6219b2ee8SDavid du Colombier 7219b2ee8SDavid du Colombier enum 8219b2ee8SDavid du Colombier { 9219b2ee8SDavid du Colombier Pagesize = 4096, 10219b2ee8SDavid du Colombier Semperpg = Pagesize/(16*sizeof(unsigned int)), 11219b2ee8SDavid du Colombier Lockaddr = 0x60000000, 12219b2ee8SDavid du Colombier 13219b2ee8SDavid du Colombier POWER = 0x320, 14219b2ee8SDavid du Colombier MAGNUM = 0x330, 15219b2ee8SDavid du Colombier MAGNUMII = 0x340, 16219b2ee8SDavid du Colombier R4K = 0x500, 17219b2ee8SDavid du Colombier }; 18219b2ee8SDavid du Colombier 19219b2ee8SDavid du Colombier static int arch; 20219b2ee8SDavid du Colombier extern int C_3ktas(int*); 21219b2ee8SDavid du Colombier extern int C_4ktas(int*); 22219b2ee8SDavid du Colombier extern int C_fcr0(void); 23219b2ee8SDavid du Colombier 24*7dd7cddfSDavid du Colombier static void 25*7dd7cddfSDavid du Colombier lockinit(void) 26219b2ee8SDavid du Colombier { 27219b2ee8SDavid du Colombier int n; 28219b2ee8SDavid du Colombier 29*7dd7cddfSDavid du Colombier if(arch != 0) 30*7dd7cddfSDavid du Colombier return; /* allow multiple calls */ 31219b2ee8SDavid du Colombier arch = C_fcr0(); 32219b2ee8SDavid du Colombier switch(arch) { 33219b2ee8SDavid du Colombier case POWER: 34219b2ee8SDavid du Colombier n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize); 35219b2ee8SDavid du Colombier if(n < 0) { 36219b2ee8SDavid du Colombier arch = MAGNUM; 37219b2ee8SDavid du Colombier break; 38219b2ee8SDavid du Colombier } 39219b2ee8SDavid du Colombier memset((void*)Lockaddr, 0, Pagesize); 40219b2ee8SDavid du Colombier break; 41219b2ee8SDavid du Colombier case MAGNUM: 42219b2ee8SDavid du Colombier case MAGNUMII: 43219b2ee8SDavid du Colombier case R4K: 44219b2ee8SDavid du Colombier break; 45219b2ee8SDavid du Colombier default: 46219b2ee8SDavid du Colombier abort(); 47219b2ee8SDavid du Colombier } 48219b2ee8SDavid du Colombier 49219b2ee8SDavid du Colombier } 50219b2ee8SDavid du Colombier 51219b2ee8SDavid du Colombier void 52219b2ee8SDavid du Colombier lock(Lock *lk) 53219b2ee8SDavid du Colombier { 54219b2ee8SDavid du Colombier int *hwsem; 55219b2ee8SDavid du Colombier int hash; 56219b2ee8SDavid du Colombier 57*7dd7cddfSDavid du Colombier retry: 58219b2ee8SDavid du Colombier switch(arch) { 59*7dd7cddfSDavid du Colombier case 0: 60*7dd7cddfSDavid du Colombier lockinit(); 61*7dd7cddfSDavid du Colombier goto retry; 62219b2ee8SDavid du Colombier case MAGNUM: 63219b2ee8SDavid du Colombier case MAGNUMII: 64219b2ee8SDavid du Colombier while(C_3ktas(&lk->val)) 65219b2ee8SDavid du Colombier _SLEEP(0); 66219b2ee8SDavid du Colombier return; 67219b2ee8SDavid du Colombier case R4K: 68219b2ee8SDavid du Colombier for(;;){ 69219b2ee8SDavid du Colombier while(lk->val) 70219b2ee8SDavid du Colombier ; 71219b2ee8SDavid du Colombier if(C_4ktas(&lk->val) == 0) 72219b2ee8SDavid du Colombier return; 73219b2ee8SDavid du Colombier } 74219b2ee8SDavid du Colombier break; 75219b2ee8SDavid du Colombier case POWER: 76219b2ee8SDavid du Colombier /* Use low order lock bits to generate hash */ 77219b2ee8SDavid du Colombier hash = ((int)lk/sizeof(int)) & (Semperpg-1); 78219b2ee8SDavid du Colombier hwsem = (int*)Lockaddr+hash; 79219b2ee8SDavid du Colombier 80219b2ee8SDavid du Colombier for(;;) { 81219b2ee8SDavid du Colombier if((*hwsem & 1) == 0) { 82219b2ee8SDavid du Colombier if(lk->val) 83219b2ee8SDavid du Colombier *hwsem = 0; 84219b2ee8SDavid du Colombier else { 85219b2ee8SDavid du Colombier lk->val = 1; 86219b2ee8SDavid du Colombier *hwsem = 0; 87219b2ee8SDavid du Colombier return; 88219b2ee8SDavid du Colombier } 89219b2ee8SDavid du Colombier } 90219b2ee8SDavid du Colombier while(lk->val) 91219b2ee8SDavid du Colombier ; 92219b2ee8SDavid du Colombier } 93219b2ee8SDavid du Colombier } 94219b2ee8SDavid du Colombier } 95219b2ee8SDavid du Colombier 96219b2ee8SDavid du Colombier int 97219b2ee8SDavid du Colombier canlock(Lock *lk) 98219b2ee8SDavid du Colombier { 99219b2ee8SDavid du Colombier int *hwsem; 100219b2ee8SDavid du Colombier int hash; 101219b2ee8SDavid du Colombier 102*7dd7cddfSDavid du Colombier retry: 103219b2ee8SDavid du Colombier switch(arch) { 104*7dd7cddfSDavid du Colombier case 0: 105*7dd7cddfSDavid du Colombier lockinit(); 106*7dd7cddfSDavid du Colombier goto retry; 107219b2ee8SDavid du Colombier case MAGNUM: 108219b2ee8SDavid du Colombier case MAGNUMII: 109219b2ee8SDavid du Colombier if(C_3ktas(&lk->val)) 110219b2ee8SDavid du Colombier return 0; 111219b2ee8SDavid du Colombier return 1; 112219b2ee8SDavid du Colombier case R4K: 113219b2ee8SDavid du Colombier if(C_4ktas(&lk->val)) 114219b2ee8SDavid du Colombier return 0; 115219b2ee8SDavid du Colombier return 1; 116219b2ee8SDavid du Colombier case POWER: 117219b2ee8SDavid du Colombier /* Use low order lock bits to generate hash */ 118219b2ee8SDavid du Colombier hash = ((int)lk/sizeof(int)) & (Semperpg-1); 119219b2ee8SDavid du Colombier hwsem = (int*)Lockaddr+hash; 120219b2ee8SDavid du Colombier 121219b2ee8SDavid du Colombier if((*hwsem & 1) == 0) { 122219b2ee8SDavid du Colombier if(lk->val) 123219b2ee8SDavid du Colombier *hwsem = 0; 124219b2ee8SDavid du Colombier else { 125219b2ee8SDavid du Colombier lk->val = 1; 126219b2ee8SDavid du Colombier *hwsem = 0; 127219b2ee8SDavid du Colombier return 1; 128219b2ee8SDavid du Colombier } 129219b2ee8SDavid du Colombier } 130219b2ee8SDavid du Colombier return 0; 131219b2ee8SDavid du Colombier } 132219b2ee8SDavid du Colombier } 133219b2ee8SDavid du Colombier 134219b2ee8SDavid du Colombier void 135219b2ee8SDavid du Colombier unlock(Lock *lk) 136219b2ee8SDavid du Colombier { 137219b2ee8SDavid du Colombier lk->val = 0; 138219b2ee8SDavid du Colombier } 139*7dd7cddfSDavid du Colombier 140*7dd7cddfSDavid du Colombier int 141*7dd7cddfSDavid du Colombier _tas(int *p) 142*7dd7cddfSDavid du Colombier { 143*7dd7cddfSDavid du Colombier int *hwsem; 144*7dd7cddfSDavid du Colombier int hash; 145*7dd7cddfSDavid du Colombier 146*7dd7cddfSDavid du Colombier retry: 147*7dd7cddfSDavid du Colombier switch(arch) { 148*7dd7cddfSDavid du Colombier case 0: 149*7dd7cddfSDavid du Colombier lockinit(); 150*7dd7cddfSDavid du Colombier goto retry; 151*7dd7cddfSDavid du Colombier case MAGNUM: 152*7dd7cddfSDavid du Colombier case MAGNUMII: 153*7dd7cddfSDavid du Colombier return C_3ktas(p); 154*7dd7cddfSDavid du Colombier case R4K: 155*7dd7cddfSDavid du Colombier return C_4ktas(p); 156*7dd7cddfSDavid du Colombier case POWER: 157*7dd7cddfSDavid du Colombier /* Use low order lock bits to generate hash */ 158*7dd7cddfSDavid du Colombier hash = ((int)p/sizeof(int)) & (Semperpg-1); 159*7dd7cddfSDavid du Colombier hwsem = (int*)Lockaddr+hash; 160*7dd7cddfSDavid du Colombier 161*7dd7cddfSDavid du Colombier if((*hwsem & 1) == 0) { 162*7dd7cddfSDavid du Colombier if(*p) 163*7dd7cddfSDavid du Colombier *hwsem = 0; 164*7dd7cddfSDavid du Colombier else { 165*7dd7cddfSDavid du Colombier *p = 1; 166*7dd7cddfSDavid du Colombier *hwsem = 0; 167*7dd7cddfSDavid du Colombier return 0; 168*7dd7cddfSDavid du Colombier } 169*7dd7cddfSDavid du Colombier } 170*7dd7cddfSDavid du Colombier return 1; 171*7dd7cddfSDavid du Colombier } 172*7dd7cddfSDavid du Colombier } 173