xref: /plan9-contrib/sys/src/ape/lib/ap/mips/lock.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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 	}
132 }
133 
134 void
135 unlock(Lock *lk)
136 {
137 	lk->val = 0;
138 }
139 
140 int
141 tas(int *p)
142 {
143 	int *hwsem;
144 	int hash;
145 
146 retry:
147 	switch(arch) {
148 	case 0:
149 		lockinit();
150 		goto retry;
151 	case MAGNUM:
152 	case MAGNUMII:
153 		return C_3ktas(p);
154 	case R4K:
155 		return C_4ktas(p);
156 	case POWER:
157 		/* Use low order lock bits to generate hash */
158 		hash = ((int)p/sizeof(int)) & (Semperpg-1);
159 		hwsem = (int*)Lockaddr+hash;
160 
161 		if((*hwsem & 1) == 0) {
162 			if(*p)
163 				*hwsem = 0;
164 			else {
165 				*p = 1;
166 				*hwsem = 0;
167 				return 0;
168 			}
169 		}
170 		return 1;
171 	}
172 }
173