]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/ap/mips/lock.c
ape: fix lockinit() for mips
[plan9front.git] / sys / src / ape / lib / ap / mips / lock.c
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                 if(_SEGATTACH(0,  "lock", (void*)Lockaddr, Pagesize) == (void*)-1) {
35                         arch = MAGNUM;
36                         break;
37                 }
38                 memset((void*)Lockaddr, 0, Pagesize);
39                 break;
40         case MAGNUM:
41         case MAGNUMII:
42         case R4K:
43                 break;
44         default:
45                 arch = R4K;
46                 break;
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         return -1;      /* not reached */
133 }
134
135 void
136 unlock(Lock *lk)
137 {
138         lk->val = 0;
139 }
140
141 int
142 tas(int *p)
143 {
144         int *hwsem;
145         int hash;
146
147 retry:
148         switch(arch) {
149         case 0:
150                 lockinit();
151                 goto retry;
152         case MAGNUM:
153         case MAGNUMII:
154                 return C_3ktas(p);
155         case R4K:
156                 return C_4ktas(p);
157         case POWER:
158                 /* Use low order lock bits to generate hash */
159                 hash = ((int)p/sizeof(int)) & (Semperpg-1);
160                 hwsem = (int*)Lockaddr+hash;
161
162                 if((*hwsem & 1) == 0) {
163                         if(*p)
164                                 *hwsem = 0;
165                         else {
166                                 *p = 1;
167                                 *hwsem = 0;
168                                 return 0;
169                         }
170                 }
171                 return 1;
172         }
173         return -1;      /* not reached */
174 }