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
lockinit(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
lock(Lock * lk)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
canlock(Lock * lk)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
unlock(Lock * lk)138 unlock(Lock *lk)
139 {
140 lk->val = 0;
141 }
142
143 int
tas(int * p)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