1 #define _LOCK_EXTENSION 2 #include <stdlib.h> 3 #include <string.h> 4 #include "../plan9/sys9.h" 5 #include <lock.h> 6 7 enum 8 { 9 Pagesize = 4096, 10 Semperpg = Pagesize/(16*sizeof(unsigned int)), 11 Lockaddr = 0x60000000, 12 13 POWER = 0x320, 14 MAGNUM = 0x330, 15 MAGNUMII = 0x340, 16 R4K = 0x500, 17 }; 18 19 static int arch; 20 extern int C_3ktas(int*); 21 extern int C_4ktas(int*); 22 extern int C_fcr0(void); 23 24 static void 25 lockinit(void) 26 { 27 int n; 28 29 if(arch != 0) 30 return; /* allow multiple calls */ 31 arch = C_fcr0(); 32 switch(arch) { 33 case POWER: 34 n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize); 35 if(n < 0) { 36 arch = MAGNUM; 37 break; 38 } 39 memset((void*)Lockaddr, 0, Pagesize); 40 break; 41 case MAGNUM: 42 case MAGNUMII: 43 case R4K: 44 break; 45 default: 46 arch = R4K; 47 break; 48 } 49 50 } 51 52 void 53 lock(Lock *lk) 54 { 55 int *hwsem; 56 int hash; 57 58 retry: 59 switch(arch) { 60 case 0: 61 lockinit(); 62 goto retry; 63 case MAGNUM: 64 case MAGNUMII: 65 while(C_3ktas(&lk->val)) 66 _SLEEP(0); 67 return; 68 case R4K: 69 for(;;){ 70 while(lk->val) 71 ; 72 if(C_4ktas(&lk->val) == 0) 73 return; 74 } 75 break; 76 case POWER: 77 /* Use low order lock bits to generate hash */ 78 hash = ((int)lk/sizeof(int)) & (Semperpg-1); 79 hwsem = (int*)Lockaddr+hash; 80 81 for(;;) { 82 if((*hwsem & 1) == 0) { 83 if(lk->val) 84 *hwsem = 0; 85 else { 86 lk->val = 1; 87 *hwsem = 0; 88 return; 89 } 90 } 91 while(lk->val) 92 ; 93 } 94 } 95 } 96 97 int 98 canlock(Lock *lk) 99 { 100 int *hwsem; 101 int hash; 102 103 retry: 104 switch(arch) { 105 case 0: 106 lockinit(); 107 goto retry; 108 case MAGNUM: 109 case MAGNUMII: 110 if(C_3ktas(&lk->val)) 111 return 0; 112 return 1; 113 case R4K: 114 if(C_4ktas(&lk->val)) 115 return 0; 116 return 1; 117 case POWER: 118 /* Use low order lock bits to generate hash */ 119 hash = ((int)lk/sizeof(int)) & (Semperpg-1); 120 hwsem = (int*)Lockaddr+hash; 121 122 if((*hwsem & 1) == 0) { 123 if(lk->val) 124 *hwsem = 0; 125 else { 126 lk->val = 1; 127 *hwsem = 0; 128 return 1; 129 } 130 } 131 return 0; 132 default: 133 return 0; 134 } 135 } 136 137 void 138 unlock(Lock *lk) 139 { 140 lk->val = 0; 141 } 142 143 int 144 tas(int *p) 145 { 146 int *hwsem; 147 int hash; 148 149 retry: 150 switch(arch) { 151 case 0: 152 lockinit(); 153 goto retry; 154 case MAGNUM: 155 case MAGNUMII: 156 return C_3ktas(p); 157 case R4K: 158 return C_4ktas(p); 159 case POWER: 160 /* Use low order lock bits to generate hash */ 161 hash = ((int)p/sizeof(int)) & (Semperpg-1); 162 hwsem = (int*)Lockaddr+hash; 163 164 if((*hwsem & 1) == 0) { 165 if(*p) 166 *hwsem = 0; 167 else { 168 *p = 1; 169 *hwsem = 0; 170 return 0; 171 } 172 } 173 return 1; 174 default: 175 return 0; 176 } 177 } 178