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 abort(); 47 } 48 49 } 50 51 void 52 lock(Lock *lk) 53 { 54 int *hwsem; 55 int hash; 56 57 retry: 58 switch(arch) { 59 case 0: 60 lockinit(); 61 goto retry; 62 case MAGNUM: 63 case MAGNUMII: 64 while(C_3ktas(&lk->val)) 65 _SLEEP(0); 66 return; 67 case R4K: 68 for(;;){ 69 while(lk->val) 70 ; 71 if(C_4ktas(&lk->val) == 0) 72 return; 73 } 74 break; 75 case POWER: 76 /* Use low order lock bits to generate hash */ 77 hash = ((int)lk/sizeof(int)) & (Semperpg-1); 78 hwsem = (int*)Lockaddr+hash; 79 80 for(;;) { 81 if((*hwsem & 1) == 0) { 82 if(lk->val) 83 *hwsem = 0; 84 else { 85 lk->val = 1; 86 *hwsem = 0; 87 return; 88 } 89 } 90 while(lk->val) 91 ; 92 } 93 } 94 } 95 96 int 97 canlock(Lock *lk) 98 { 99 int *hwsem; 100 int hash; 101 102 retry: 103 switch(arch) { 104 case 0: 105 lockinit(); 106 goto retry; 107 case MAGNUM: 108 case MAGNUMII: 109 if(C_3ktas(&lk->val)) 110 return 0; 111 return 1; 112 case R4K: 113 if(C_4ktas(&lk->val)) 114 return 0; 115 return 1; 116 case POWER: 117 /* Use low order lock bits to generate hash */ 118 hash = ((int)lk/sizeof(int)) & (Semperpg-1); 119 hwsem = (int*)Lockaddr+hash; 120 121 if((*hwsem & 1) == 0) { 122 if(lk->val) 123 *hwsem = 0; 124 else { 125 lk->val = 1; 126 *hwsem = 0; 127 return 1; 128 } 129 } 130 return 0; 131 } 132 } 133 134 void 135 unlock(Lock *lk) 136 { 137 lk->val = 0; 138 } 139 140 int 141 tas(int *p) 142 { 143 int *hwsem; 144 int hash; 145 146 retry: 147 switch(arch) { 148 case 0: 149 lockinit(); 150 goto retry; 151 case MAGNUM: 152 case MAGNUMII: 153 return C_3ktas(p); 154 case R4K: 155 return C_4ktas(p); 156 case POWER: 157 /* Use low order lock bits to generate hash */ 158 hash = ((int)p/sizeof(int)) & (Semperpg-1); 159 hwsem = (int*)Lockaddr+hash; 160 161 if((*hwsem & 1) == 0) { 162 if(*p) 163 *hwsem = 0; 164 else { 165 *p = 1; 166 *hwsem = 0; 167 return 0; 168 } 169 } 170 return 1; 171 } 172 } 173