xref: /plan9-contrib/sys/src/ape/lib/ap/mips/lock.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 void
25 lockinit()
26 {
27 	int n;
28 
29 	arch = C_fcr0();
30 	switch(arch) {
31 	case POWER:
32 		n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize);
33 		if(n < 0) {
34 			arch = MAGNUM;
35 			break;
36 		}
37 		memset((void*)Lockaddr, 0, Pagesize);
38 		break;
39 	case MAGNUM:
40 	case MAGNUMII:
41 	case R4K:
42 		break;
43 	default:
44 		abort();
45 	}
46 
47 }
48 
49 void
50 lock(Lock *lk)
51 {
52 	int *hwsem;
53 	int hash;
54 
55 	switch(arch) {
56 	case MAGNUM:
57 	case MAGNUMII:
58 		while(C_3ktas(&lk->val))
59 			_SLEEP(0);
60 		return;
61 	case R4K:
62 		for(;;){
63 			while(lk->val)
64 				;
65 			if(C_4ktas(&lk->val) == 0)
66 				return;
67 		}
68 		break;
69 	case POWER:
70 		/* Use low order lock bits to generate hash */
71 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
72 		hwsem = (int*)Lockaddr+hash;
73 
74 		for(;;) {
75 			if((*hwsem & 1) == 0) {
76 				if(lk->val)
77 					*hwsem = 0;
78 				else {
79 					lk->val = 1;
80 					*hwsem = 0;
81 					return;
82 				}
83 			}
84 			while(lk->val)
85 				;
86 		}
87 	}
88 }
89 
90 int
91 canlock(Lock *lk)
92 {
93 	int *hwsem;
94 	int hash;
95 
96 	switch(arch) {
97 	case MAGNUM:
98 	case MAGNUMII:
99 		if(C_3ktas(&lk->val))
100 			return 0;
101 		return 1;
102 	case R4K:
103 		if(C_4ktas(&lk->val))
104 			return 0;
105 		return 1;
106 	case POWER:
107 		/* Use low order lock bits to generate hash */
108 		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
109 		hwsem = (int*)Lockaddr+hash;
110 
111 		if((*hwsem & 1) == 0) {
112 			if(lk->val)
113 				*hwsem = 0;
114 			else {
115 				lk->val = 1;
116 				*hwsem = 0;
117 				return 1;
118 			}
119 		}
120 		return 0;
121 	}
122 }
123 
124 void
125 unlock(Lock *lk)
126 {
127 	lk->val = 0;
128 }
129