xref: /plan9/sys/src/ape/lib/ap/mips/lock.c (revision 401314a3b4602c168a19b28ed47ba5cbefe42fe0)
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
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 		abort();
47 	}
48 
49 }
50 
51 void
52 lock(Lock *lk)
53 {
54 	int *hwsem;
55 	int hash;
56 
57 retry:
58 	switch(arch) {
59 	case 0:
60 		lockinit();
61 		goto retry;
62 	case MAGNUM:
63 	case MAGNUMII:
64 		while(C_3ktas(&lk->val))
65 			_SLEEP(0);
66 		return;
67 	case R4K:
68 		for(;;){
69 			while(lk->val)
70 				;
71 			if(C_4ktas(&lk->val) == 0)
72 				return;
73 		}
74 		break;
75 	case POWER:
76 		/* Use low order lock bits to generate hash */
77 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
78 		hwsem = (int*)Lockaddr+hash;
79 
80 		for(;;) {
81 			if((*hwsem & 1) == 0) {
82 				if(lk->val)
83 					*hwsem = 0;
84 				else {
85 					lk->val = 1;
86 					*hwsem = 0;
87 					return;
88 				}
89 			}
90 			while(lk->val)
91 				;
92 		}
93 	}
94 }
95 
96 int
97 canlock(Lock *lk)
98 {
99 	int *hwsem;
100 	int hash;
101 
102 retry:
103 	switch(arch) {
104 	case 0:
105 		lockinit();
106 		goto retry;
107 	case MAGNUM:
108 	case MAGNUMII:
109 		if(C_3ktas(&lk->val))
110 			return 0;
111 		return 1;
112 	case R4K:
113 		if(C_4ktas(&lk->val))
114 			return 0;
115 		return 1;
116 	case POWER:
117 		/* Use low order lock bits to generate hash */
118 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
119 		hwsem = (int*)Lockaddr+hash;
120 
121 		if((*hwsem & 1) == 0) {
122 			if(lk->val)
123 				*hwsem = 0;
124 			else {
125 				lk->val = 1;
126 				*hwsem = 0;
127 				return 1;
128 			}
129 		}
130 		return 0;
131 	default:
132 		return 0;
133 	}
134 }
135 
136 void
137 unlock(Lock *lk)
138 {
139 	lk->val = 0;
140 }
141 
142 int
143 tas(int *p)
144 {
145 	int *hwsem;
146 	int hash;
147 
148 retry:
149 	switch(arch) {
150 	case 0:
151 		lockinit();
152 		goto retry;
153 	case MAGNUM:
154 	case MAGNUMII:
155 		return C_3ktas(p);
156 	case R4K:
157 		return C_4ktas(p);
158 	case POWER:
159 		/* Use low order lock bits to generate hash */
160 		hash = ((int)p/sizeof(int)) & (Semperpg-1);
161 		hwsem = (int*)Lockaddr+hash;
162 
163 		if((*hwsem & 1) == 0) {
164 			if(*p)
165 				*hwsem = 0;
166 			else {
167 				*p = 1;
168 				*hwsem = 0;
169 				return 0;
170 			}
171 		}
172 		return 1;
173 	default:
174 		return 0;
175 	}
176 }
177