xref: /plan9-contrib/sys/src/ape/lib/ap/mips/lock.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #define _LOCK_EXTENSION
2*219b2ee8SDavid du Colombier #include <stdlib.h>
3*219b2ee8SDavid du Colombier #include <string.h>
4*219b2ee8SDavid du Colombier #include "../plan9/sys9.h"
5*219b2ee8SDavid du Colombier #include <lock.h>
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier enum
8*219b2ee8SDavid du Colombier {
9*219b2ee8SDavid du Colombier 	Pagesize	= 4096,
10*219b2ee8SDavid du Colombier 	Semperpg	= Pagesize/(16*sizeof(unsigned int)),
11*219b2ee8SDavid du Colombier 	Lockaddr	= 0x60000000,
12*219b2ee8SDavid du Colombier 
13*219b2ee8SDavid du Colombier 	POWER		= 0x320,
14*219b2ee8SDavid du Colombier 	MAGNUM		= 0x330,
15*219b2ee8SDavid du Colombier 	MAGNUMII	= 0x340,
16*219b2ee8SDavid du Colombier 	R4K		= 0x500,
17*219b2ee8SDavid du Colombier };
18*219b2ee8SDavid du Colombier 
19*219b2ee8SDavid du Colombier static	int arch;
20*219b2ee8SDavid du Colombier extern	int C_3ktas(int*);
21*219b2ee8SDavid du Colombier extern	int C_4ktas(int*);
22*219b2ee8SDavid du Colombier extern	int C_fcr0(void);
23*219b2ee8SDavid du Colombier 
24*219b2ee8SDavid du Colombier void
25*219b2ee8SDavid du Colombier lockinit()
26*219b2ee8SDavid du Colombier {
27*219b2ee8SDavid du Colombier 	int n;
28*219b2ee8SDavid du Colombier 
29*219b2ee8SDavid du Colombier 	arch = C_fcr0();
30*219b2ee8SDavid du Colombier 	switch(arch) {
31*219b2ee8SDavid du Colombier 	case POWER:
32*219b2ee8SDavid du Colombier 		n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize);
33*219b2ee8SDavid du Colombier 		if(n < 0) {
34*219b2ee8SDavid du Colombier 			arch = MAGNUM;
35*219b2ee8SDavid du Colombier 			break;
36*219b2ee8SDavid du Colombier 		}
37*219b2ee8SDavid du Colombier 		memset((void*)Lockaddr, 0, Pagesize);
38*219b2ee8SDavid du Colombier 		break;
39*219b2ee8SDavid du Colombier 	case MAGNUM:
40*219b2ee8SDavid du Colombier 	case MAGNUMII:
41*219b2ee8SDavid du Colombier 	case R4K:
42*219b2ee8SDavid du Colombier 		break;
43*219b2ee8SDavid du Colombier 	default:
44*219b2ee8SDavid du Colombier 		abort();
45*219b2ee8SDavid du Colombier 	}
46*219b2ee8SDavid du Colombier 
47*219b2ee8SDavid du Colombier }
48*219b2ee8SDavid du Colombier 
49*219b2ee8SDavid du Colombier void
50*219b2ee8SDavid du Colombier lock(Lock *lk)
51*219b2ee8SDavid du Colombier {
52*219b2ee8SDavid du Colombier 	int *hwsem;
53*219b2ee8SDavid du Colombier 	int hash;
54*219b2ee8SDavid du Colombier 
55*219b2ee8SDavid du Colombier 	switch(arch) {
56*219b2ee8SDavid du Colombier 	case MAGNUM:
57*219b2ee8SDavid du Colombier 	case MAGNUMII:
58*219b2ee8SDavid du Colombier 		while(C_3ktas(&lk->val))
59*219b2ee8SDavid du Colombier 			_SLEEP(0);
60*219b2ee8SDavid du Colombier 		return;
61*219b2ee8SDavid du Colombier 	case R4K:
62*219b2ee8SDavid du Colombier 		for(;;){
63*219b2ee8SDavid du Colombier 			while(lk->val)
64*219b2ee8SDavid du Colombier 				;
65*219b2ee8SDavid du Colombier 			if(C_4ktas(&lk->val) == 0)
66*219b2ee8SDavid du Colombier 				return;
67*219b2ee8SDavid du Colombier 		}
68*219b2ee8SDavid du Colombier 		break;
69*219b2ee8SDavid du Colombier 	case POWER:
70*219b2ee8SDavid du Colombier 		/* Use low order lock bits to generate hash */
71*219b2ee8SDavid du Colombier 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
72*219b2ee8SDavid du Colombier 		hwsem = (int*)Lockaddr+hash;
73*219b2ee8SDavid du Colombier 
74*219b2ee8SDavid du Colombier 		for(;;) {
75*219b2ee8SDavid du Colombier 			if((*hwsem & 1) == 0) {
76*219b2ee8SDavid du Colombier 				if(lk->val)
77*219b2ee8SDavid du Colombier 					*hwsem = 0;
78*219b2ee8SDavid du Colombier 				else {
79*219b2ee8SDavid du Colombier 					lk->val = 1;
80*219b2ee8SDavid du Colombier 					*hwsem = 0;
81*219b2ee8SDavid du Colombier 					return;
82*219b2ee8SDavid du Colombier 				}
83*219b2ee8SDavid du Colombier 			}
84*219b2ee8SDavid du Colombier 			while(lk->val)
85*219b2ee8SDavid du Colombier 				;
86*219b2ee8SDavid du Colombier 		}
87*219b2ee8SDavid du Colombier 	}
88*219b2ee8SDavid du Colombier }
89*219b2ee8SDavid du Colombier 
90*219b2ee8SDavid du Colombier int
91*219b2ee8SDavid du Colombier canlock(Lock *lk)
92*219b2ee8SDavid du Colombier {
93*219b2ee8SDavid du Colombier 	int *hwsem;
94*219b2ee8SDavid du Colombier 	int hash;
95*219b2ee8SDavid du Colombier 
96*219b2ee8SDavid du Colombier 	switch(arch) {
97*219b2ee8SDavid du Colombier 	case MAGNUM:
98*219b2ee8SDavid du Colombier 	case MAGNUMII:
99*219b2ee8SDavid du Colombier 		if(C_3ktas(&lk->val))
100*219b2ee8SDavid du Colombier 			return 0;
101*219b2ee8SDavid du Colombier 		return 1;
102*219b2ee8SDavid du Colombier 	case R4K:
103*219b2ee8SDavid du Colombier 		if(C_4ktas(&lk->val))
104*219b2ee8SDavid du Colombier 			return 0;
105*219b2ee8SDavid du Colombier 		return 1;
106*219b2ee8SDavid du Colombier 	case POWER:
107*219b2ee8SDavid du Colombier 		/* Use low order lock bits to generate hash */
108*219b2ee8SDavid du Colombier 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
109*219b2ee8SDavid du Colombier 		hwsem = (int*)Lockaddr+hash;
110*219b2ee8SDavid du Colombier 
111*219b2ee8SDavid du Colombier 		if((*hwsem & 1) == 0) {
112*219b2ee8SDavid du Colombier 			if(lk->val)
113*219b2ee8SDavid du Colombier 				*hwsem = 0;
114*219b2ee8SDavid du Colombier 			else {
115*219b2ee8SDavid du Colombier 				lk->val = 1;
116*219b2ee8SDavid du Colombier 				*hwsem = 0;
117*219b2ee8SDavid du Colombier 				return 1;
118*219b2ee8SDavid du Colombier 			}
119*219b2ee8SDavid du Colombier 		}
120*219b2ee8SDavid du Colombier 		return 0;
121*219b2ee8SDavid du Colombier 	}
122*219b2ee8SDavid du Colombier }
123*219b2ee8SDavid du Colombier 
124*219b2ee8SDavid du Colombier void
125*219b2ee8SDavid du Colombier unlock(Lock *lk)
126*219b2ee8SDavid du Colombier {
127*219b2ee8SDavid du Colombier 	lk->val = 0;
128*219b2ee8SDavid du Colombier }
129