xref: /plan9/sys/src/ape/lib/ap/mips/lock.pre-sema.c (revision 51f48f69b4c3e5c9d9f7955d28612ef2d4048ccc)
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