xref: /plan9/sys/src/ape/lib/ap/mips/lock.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1219b2ee8SDavid du Colombier #define _LOCK_EXTENSION
2219b2ee8SDavid du Colombier #include <stdlib.h>
3219b2ee8SDavid du Colombier #include <string.h>
4219b2ee8SDavid du Colombier #include "../plan9/sys9.h"
5219b2ee8SDavid du Colombier #include <lock.h>
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier enum
8219b2ee8SDavid du Colombier {
9219b2ee8SDavid du Colombier 	Pagesize	= 4096,
10219b2ee8SDavid du Colombier 	Semperpg	= Pagesize/(16*sizeof(unsigned int)),
11219b2ee8SDavid du Colombier 	Lockaddr	= 0x60000000,
12219b2ee8SDavid du Colombier 
13219b2ee8SDavid du Colombier 	POWER		= 0x320,
14219b2ee8SDavid du Colombier 	MAGNUM		= 0x330,
15219b2ee8SDavid du Colombier 	MAGNUMII	= 0x340,
16219b2ee8SDavid du Colombier 	R4K		= 0x500,
17219b2ee8SDavid du Colombier };
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier static	int arch;
20219b2ee8SDavid du Colombier extern	int C_3ktas(int*);
21219b2ee8SDavid du Colombier extern	int C_4ktas(int*);
22219b2ee8SDavid du Colombier extern	int C_fcr0(void);
23219b2ee8SDavid du Colombier 
24*7dd7cddfSDavid du Colombier static void
25*7dd7cddfSDavid du Colombier lockinit(void)
26219b2ee8SDavid du Colombier {
27219b2ee8SDavid du Colombier 	int n;
28219b2ee8SDavid du Colombier 
29*7dd7cddfSDavid du Colombier 	if(arch != 0)
30*7dd7cddfSDavid du Colombier 		return;	/* allow multiple calls */
31219b2ee8SDavid du Colombier 	arch = C_fcr0();
32219b2ee8SDavid du Colombier 	switch(arch) {
33219b2ee8SDavid du Colombier 	case POWER:
34219b2ee8SDavid du Colombier 		n = _SEGATTACH(0,  "lock", (void*)Lockaddr, Pagesize);
35219b2ee8SDavid du Colombier 		if(n < 0) {
36219b2ee8SDavid du Colombier 			arch = MAGNUM;
37219b2ee8SDavid du Colombier 			break;
38219b2ee8SDavid du Colombier 		}
39219b2ee8SDavid du Colombier 		memset((void*)Lockaddr, 0, Pagesize);
40219b2ee8SDavid du Colombier 		break;
41219b2ee8SDavid du Colombier 	case MAGNUM:
42219b2ee8SDavid du Colombier 	case MAGNUMII:
43219b2ee8SDavid du Colombier 	case R4K:
44219b2ee8SDavid du Colombier 		break;
45219b2ee8SDavid du Colombier 	default:
46219b2ee8SDavid du Colombier 		abort();
47219b2ee8SDavid du Colombier 	}
48219b2ee8SDavid du Colombier 
49219b2ee8SDavid du Colombier }
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier void
52219b2ee8SDavid du Colombier lock(Lock *lk)
53219b2ee8SDavid du Colombier {
54219b2ee8SDavid du Colombier 	int *hwsem;
55219b2ee8SDavid du Colombier 	int hash;
56219b2ee8SDavid du Colombier 
57*7dd7cddfSDavid du Colombier retry:
58219b2ee8SDavid du Colombier 	switch(arch) {
59*7dd7cddfSDavid du Colombier 	case 0:
60*7dd7cddfSDavid du Colombier 		lockinit();
61*7dd7cddfSDavid du Colombier 		goto retry;
62219b2ee8SDavid du Colombier 	case MAGNUM:
63219b2ee8SDavid du Colombier 	case MAGNUMII:
64219b2ee8SDavid du Colombier 		while(C_3ktas(&lk->val))
65219b2ee8SDavid du Colombier 			_SLEEP(0);
66219b2ee8SDavid du Colombier 		return;
67219b2ee8SDavid du Colombier 	case R4K:
68219b2ee8SDavid du Colombier 		for(;;){
69219b2ee8SDavid du Colombier 			while(lk->val)
70219b2ee8SDavid du Colombier 				;
71219b2ee8SDavid du Colombier 			if(C_4ktas(&lk->val) == 0)
72219b2ee8SDavid du Colombier 				return;
73219b2ee8SDavid du Colombier 		}
74219b2ee8SDavid du Colombier 		break;
75219b2ee8SDavid du Colombier 	case POWER:
76219b2ee8SDavid du Colombier 		/* Use low order lock bits to generate hash */
77219b2ee8SDavid du Colombier 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
78219b2ee8SDavid du Colombier 		hwsem = (int*)Lockaddr+hash;
79219b2ee8SDavid du Colombier 
80219b2ee8SDavid du Colombier 		for(;;) {
81219b2ee8SDavid du Colombier 			if((*hwsem & 1) == 0) {
82219b2ee8SDavid du Colombier 				if(lk->val)
83219b2ee8SDavid du Colombier 					*hwsem = 0;
84219b2ee8SDavid du Colombier 				else {
85219b2ee8SDavid du Colombier 					lk->val = 1;
86219b2ee8SDavid du Colombier 					*hwsem = 0;
87219b2ee8SDavid du Colombier 					return;
88219b2ee8SDavid du Colombier 				}
89219b2ee8SDavid du Colombier 			}
90219b2ee8SDavid du Colombier 			while(lk->val)
91219b2ee8SDavid du Colombier 				;
92219b2ee8SDavid du Colombier 		}
93219b2ee8SDavid du Colombier 	}
94219b2ee8SDavid du Colombier }
95219b2ee8SDavid du Colombier 
96219b2ee8SDavid du Colombier int
97219b2ee8SDavid du Colombier canlock(Lock *lk)
98219b2ee8SDavid du Colombier {
99219b2ee8SDavid du Colombier 	int *hwsem;
100219b2ee8SDavid du Colombier 	int hash;
101219b2ee8SDavid du Colombier 
102*7dd7cddfSDavid du Colombier retry:
103219b2ee8SDavid du Colombier 	switch(arch) {
104*7dd7cddfSDavid du Colombier 	case 0:
105*7dd7cddfSDavid du Colombier 		lockinit();
106*7dd7cddfSDavid du Colombier 		goto retry;
107219b2ee8SDavid du Colombier 	case MAGNUM:
108219b2ee8SDavid du Colombier 	case MAGNUMII:
109219b2ee8SDavid du Colombier 		if(C_3ktas(&lk->val))
110219b2ee8SDavid du Colombier 			return 0;
111219b2ee8SDavid du Colombier 		return 1;
112219b2ee8SDavid du Colombier 	case R4K:
113219b2ee8SDavid du Colombier 		if(C_4ktas(&lk->val))
114219b2ee8SDavid du Colombier 			return 0;
115219b2ee8SDavid du Colombier 		return 1;
116219b2ee8SDavid du Colombier 	case POWER:
117219b2ee8SDavid du Colombier 		/* Use low order lock bits to generate hash */
118219b2ee8SDavid du Colombier 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
119219b2ee8SDavid du Colombier 		hwsem = (int*)Lockaddr+hash;
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier 		if((*hwsem & 1) == 0) {
122219b2ee8SDavid du Colombier 			if(lk->val)
123219b2ee8SDavid du Colombier 				*hwsem = 0;
124219b2ee8SDavid du Colombier 			else {
125219b2ee8SDavid du Colombier 				lk->val = 1;
126219b2ee8SDavid du Colombier 				*hwsem = 0;
127219b2ee8SDavid du Colombier 				return 1;
128219b2ee8SDavid du Colombier 			}
129219b2ee8SDavid du Colombier 		}
130219b2ee8SDavid du Colombier 		return 0;
131219b2ee8SDavid du Colombier 	}
132219b2ee8SDavid du Colombier }
133219b2ee8SDavid du Colombier 
134219b2ee8SDavid du Colombier void
135219b2ee8SDavid du Colombier unlock(Lock *lk)
136219b2ee8SDavid du Colombier {
137219b2ee8SDavid du Colombier 	lk->val = 0;
138219b2ee8SDavid du Colombier }
139*7dd7cddfSDavid du Colombier 
140*7dd7cddfSDavid du Colombier int
141*7dd7cddfSDavid du Colombier _tas(int *p)
142*7dd7cddfSDavid du Colombier {
143*7dd7cddfSDavid du Colombier 	int *hwsem;
144*7dd7cddfSDavid du Colombier 	int hash;
145*7dd7cddfSDavid du Colombier 
146*7dd7cddfSDavid du Colombier retry:
147*7dd7cddfSDavid du Colombier 	switch(arch) {
148*7dd7cddfSDavid du Colombier 	case 0:
149*7dd7cddfSDavid du Colombier 		lockinit();
150*7dd7cddfSDavid du Colombier 		goto retry;
151*7dd7cddfSDavid du Colombier 	case MAGNUM:
152*7dd7cddfSDavid du Colombier 	case MAGNUMII:
153*7dd7cddfSDavid du Colombier 		return C_3ktas(p);
154*7dd7cddfSDavid du Colombier 	case R4K:
155*7dd7cddfSDavid du Colombier 		return C_4ktas(p);
156*7dd7cddfSDavid du Colombier 	case POWER:
157*7dd7cddfSDavid du Colombier 		/* Use low order lock bits to generate hash */
158*7dd7cddfSDavid du Colombier 		hash = ((int)p/sizeof(int)) & (Semperpg-1);
159*7dd7cddfSDavid du Colombier 		hwsem = (int*)Lockaddr+hash;
160*7dd7cddfSDavid du Colombier 
161*7dd7cddfSDavid du Colombier 		if((*hwsem & 1) == 0) {
162*7dd7cddfSDavid du Colombier 			if(*p)
163*7dd7cddfSDavid du Colombier 				*hwsem = 0;
164*7dd7cddfSDavid du Colombier 			else {
165*7dd7cddfSDavid du Colombier 				*p = 1;
166*7dd7cddfSDavid du Colombier 				*hwsem = 0;
167*7dd7cddfSDavid du Colombier 				return 0;
168*7dd7cddfSDavid du Colombier 			}
169*7dd7cddfSDavid du Colombier 		}
170*7dd7cddfSDavid du Colombier 		return 1;
171*7dd7cddfSDavid du Colombier 	}
172*7dd7cddfSDavid du Colombier }
173