]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/mips/lock.c
merge
[plan9front.git] / sys / src / libc / mips / lock.c
1 #include <u.h>
2 #include <libc.h>
3
4 enum
5 {
6         Pagesize        = 4096,
7         Semperpg        = Pagesize/(16*sizeof(uint)),
8         Lockaddr        = 0x60000000,
9
10         POWER           = 0x320,
11         MAGNUM          = 0x330,
12         MAGNUMII        = 0x340,
13         R4K             = 0x500,
14 };
15
16 static  int arch;
17 extern  int C_3ktas(int*);
18 extern  int C_4ktas(int*);
19 extern  int C_fcr0(void);
20
21 static void
22 lockinit(void)
23 {
24         void *v;
25
26         if(arch != 0)
27                 return; /* allow multiple calls */
28         arch = C_fcr0();
29         switch(arch) {
30         case POWER:
31                 v = (void*)Lockaddr;
32                 if(segattach(SG_CEXEC, "lock", v, Pagesize) == (void*)-1) {
33                         arch = MAGNUM;
34                         break;
35                 }
36                 memset(v, 0, Pagesize);
37                 break;
38         case MAGNUM:
39         case MAGNUMII:
40         case R4K:
41                 break;
42         default:
43                 arch = R4K;
44                 break;
45         }
46 }
47
48 void
49 lock(Lock *lk)
50 {
51         int *hwsem;
52         int hash;
53
54 retry:
55         switch(arch) {
56         case 0:
57                 lockinit();
58                 goto retry;
59         case MAGNUM:
60         case MAGNUMII:
61                 while(C_3ktas(&lk->val))
62                         sleep(0);
63                 return;
64         case R4K:
65                 for(;;){
66                         while(lk->val)
67                                 ;
68                         if(C_4ktas(&lk->val) == 0)
69                                 return;
70                 }
71                 break;
72         case POWER:
73                 /* Use low order lock bits to generate hash */
74                 hash = ((int)lk/sizeof(int)) & (Semperpg-1);
75                 hwsem = (int*)Lockaddr+hash;
76
77                 for(;;) {
78                         if((*hwsem & 1) == 0) {
79                                 if(lk->val)
80                                         *hwsem = 0;
81                                 else {
82                                         lk->val = 1;
83                                         *hwsem = 0;
84                                         return;
85                                 }
86                         }
87                         while(lk->val)
88                                 ;
89                 }
90         }
91 }
92
93 int
94 canlock(Lock *lk)
95 {
96         int *hwsem;
97         int hash;
98
99 retry:
100         switch(arch) {
101         case 0:
102                 lockinit();
103                 goto retry;
104         case MAGNUM:
105         case MAGNUMII:
106                 if(C_3ktas(&lk->val))
107                         return 0;
108                 return 1;
109         case R4K:
110                 if(C_4ktas(&lk->val))
111                         return 0;
112                 return 1;
113         case POWER:
114                 /* Use low order lock bits to generate hash */
115                 hash = ((int)lk/sizeof(int)) & (Semperpg-1);
116                 hwsem = (int*)Lockaddr+hash;
117
118                 if((*hwsem & 1) == 0) {
119                         if(lk->val)
120                                 *hwsem = 0;
121                         else {
122                                 lk->val = 1;
123                                 *hwsem = 0;
124                                 return 1;
125                         }
126                 }
127                 break;
128         }
129         return 0;
130 }
131
132 void
133 unlock(Lock *lk)
134 {
135         lk->val = 0;
136 }
137
138 int
139 _tas(int *p)
140 {
141         int *hwsem;
142         int hash;
143
144 retry:
145         switch(arch) {
146         case 0:
147                 lockinit();
148                 goto retry;
149         case MAGNUM:
150         case MAGNUMII:
151                 return C_3ktas(p);
152         case R4K:
153                 return C_4ktas(p);
154         case POWER:
155                 /* Use low order lock bits to generate hash */
156                 hash = ((int)p/sizeof(int)) & (Semperpg-1);
157                 hwsem = (int*)Lockaddr+hash;
158
159                 if((*hwsem & 1) == 0) {
160                         if(*p)
161                                 *hwsem = 0;
162                         else {
163                                 *p = 1;
164                                 *hwsem = 0;
165                                 return 0;
166                         }
167                 }
168                 break;
169         }
170         return 1;
171 }