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