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