Blame


1 cea10000 2005-05-01 devnull #undef exits
2 cea10000 2005-05-01 devnull #undef _exits
3 cea10000 2005-05-01 devnull
4 cea10000 2005-05-01 devnull extern int __isthreaded;
5 cea10000 2005-05-01 devnull
6 cea10000 2005-05-01 devnull /*
7 cea10000 2005-05-01 devnull * spin locks
8 cea10000 2005-05-01 devnull */
9 cea10000 2005-05-01 devnull extern int _tas(int*);
10 cea10000 2005-05-01 devnull
11 cea10000 2005-05-01 devnull void
12 cea10000 2005-05-01 devnull _threadunlock(Lock *l, ulong pc)
13 cea10000 2005-05-01 devnull {
14 cea10000 2005-05-01 devnull USED(pc);
15 cea10000 2005-05-01 devnull
16 cea10000 2005-05-01 devnull l->held = 0;
17 cea10000 2005-05-01 devnull }
18 cea10000 2005-05-01 devnull
19 cea10000 2005-05-01 devnull int
20 cea10000 2005-05-01 devnull _threadlock(Lock *l, int block, ulong pc)
21 cea10000 2005-05-01 devnull {
22 cea10000 2005-05-01 devnull int i;
23 cea10000 2005-05-01 devnull
24 cea10000 2005-05-01 devnull USED(pc);
25 cea10000 2005-05-01 devnull
26 cea10000 2005-05-01 devnull /* once fast */
27 cea10000 2005-05-01 devnull if(!_tas(&l->held))
28 cea10000 2005-05-01 devnull return 1;
29 cea10000 2005-05-01 devnull if(!block)
30 cea10000 2005-05-01 devnull return 0;
31 cea10000 2005-05-01 devnull
32 cea10000 2005-05-01 devnull /* a thousand times pretty fast */
33 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
34 cea10000 2005-05-01 devnull if(!_tas(&l->held))
35 cea10000 2005-05-01 devnull return 1;
36 cea10000 2005-05-01 devnull sched_yield();
37 cea10000 2005-05-01 devnull }
38 cea10000 2005-05-01 devnull /* increasingly slow */
39 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
40 cea10000 2005-05-01 devnull if(!_tas(&l->held))
41 cea10000 2005-05-01 devnull return 1;
42 cea10000 2005-05-01 devnull usleep(1);
43 cea10000 2005-05-01 devnull }
44 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
45 cea10000 2005-05-01 devnull if(!_tas(&l->held))
46 cea10000 2005-05-01 devnull return 1;
47 cea10000 2005-05-01 devnull usleep(10);
48 cea10000 2005-05-01 devnull }
49 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
50 cea10000 2005-05-01 devnull if(!_tas(&l->held))
51 cea10000 2005-05-01 devnull return 1;
52 cea10000 2005-05-01 devnull usleep(100);
53 cea10000 2005-05-01 devnull }
54 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
55 cea10000 2005-05-01 devnull if(!_tas(&l->held))
56 cea10000 2005-05-01 devnull return 1;
57 cea10000 2005-05-01 devnull usleep(1000);
58 cea10000 2005-05-01 devnull }
59 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
60 cea10000 2005-05-01 devnull if(!_tas(&l->held))
61 cea10000 2005-05-01 devnull return 1;
62 cea10000 2005-05-01 devnull usleep(10*1000);
63 cea10000 2005-05-01 devnull }
64 cea10000 2005-05-01 devnull /* now nice and slow */
65 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
66 cea10000 2005-05-01 devnull if(!_tas(&l->held))
67 cea10000 2005-05-01 devnull return 1;
68 cea10000 2005-05-01 devnull usleep(100*1000);
69 cea10000 2005-05-01 devnull }
70 cea10000 2005-05-01 devnull /* take your time */
71 cea10000 2005-05-01 devnull while(_tas(&l->held))
72 cea10000 2005-05-01 devnull usleep(1000*1000);
73 cea10000 2005-05-01 devnull return 1;
74 cea10000 2005-05-01 devnull }
75 cea10000 2005-05-01 devnull
76 cea10000 2005-05-01 devnull /*
77 cea10000 2005-05-01 devnull * For libc.
78 cea10000 2005-05-01 devnull */
79 cea10000 2005-05-01 devnull
80 cea10000 2005-05-01 devnull typedef struct {
81 cea10000 2005-05-01 devnull volatile long access_lock;
82 cea10000 2005-05-01 devnull volatile long lock_owner;
83 cea10000 2005-05-01 devnull volatile char *fname;
84 cea10000 2005-05-01 devnull volatile int lineno;
85 cea10000 2005-05-01 devnull } spinlock_t;
86 cea10000 2005-05-01 devnull
87 cea10000 2005-05-01 devnull void
88 cea10000 2005-05-01 devnull _spinlock(spinlock_t *lk)
89 cea10000 2005-05-01 devnull {
90 cea10000 2005-05-01 devnull lock((Lock*)&lk->access_lock);
91 cea10000 2005-05-01 devnull }
92 cea10000 2005-05-01 devnull
93 cea10000 2005-05-01 devnull /*
94 cea10000 2005-05-01 devnull * sleep and wakeup
95 cea10000 2005-05-01 devnull */
96 cea10000 2005-05-01 devnull static void
97 cea10000 2005-05-01 devnull ign(int x)
98 cea10000 2005-05-01 devnull {
99 cea10000 2005-05-01 devnull USED(x);
100 cea10000 2005-05-01 devnull }
101 cea10000 2005-05-01 devnull
102 cea10000 2005-05-01 devnull static void /*__attribute__((constructor))*/
103 cea10000 2005-05-01 devnull ignusr1(int restart)
104 cea10000 2005-05-01 devnull {
105 cea10000 2005-05-01 devnull struct sigaction sa;
106 cea10000 2005-05-01 devnull
107 cea10000 2005-05-01 devnull memset(&sa, 0, sizeof sa);
108 cea10000 2005-05-01 devnull sa.sa_handler = ign;
109 cea10000 2005-05-01 devnull sigemptyset(&sa.sa_mask);
110 cea10000 2005-05-01 devnull sigaddset(&sa.sa_mask, SIGUSR1);
111 cea10000 2005-05-01 devnull if(restart)
112 cea10000 2005-05-01 devnull sa.sa_flags = SA_RESTART;
113 cea10000 2005-05-01 devnull sigaction(SIGUSR1, &sa, nil);
114 cea10000 2005-05-01 devnull }
115 cea10000 2005-05-01 devnull
116 cea10000 2005-05-01 devnull void
117 cea10000 2005-05-01 devnull _procsleep(_Procrendez *r)
118 cea10000 2005-05-01 devnull {
119 cea10000 2005-05-01 devnull sigset_t mask;
120 cea10000 2005-05-01 devnull
121 cea10000 2005-05-01 devnull /*
122 cea10000 2005-05-01 devnull * Go to sleep.
123 cea10000 2005-05-01 devnull *
124 cea10000 2005-05-01 devnull * Block USR1, set the handler to interrupt system calls,
125 cea10000 2005-05-01 devnull * unlock the vouslock so our waker can wake us,
126 cea10000 2005-05-01 devnull * and then suspend.
127 cea10000 2005-05-01 devnull */
128 cea10000 2005-05-01 devnull again:
129 cea10000 2005-05-01 devnull r->asleep = 1;
130 cea10000 2005-05-01 devnull r->pid = getpid();
131 cea10000 2005-05-01 devnull
132 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, nil, &mask);
133 cea10000 2005-05-01 devnull sigaddset(&mask, SIGUSR1);
134 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, &mask, nil);
135 cea10000 2005-05-01 devnull ignusr1(0);
136 cea10000 2005-05-01 devnull unlock(r->l);
137 cea10000 2005-05-01 devnull sigdelset(&mask, SIGUSR1);
138 cea10000 2005-05-01 devnull sigsuspend(&mask);
139 cea10000 2005-05-01 devnull
140 cea10000 2005-05-01 devnull /*
141 cea10000 2005-05-01 devnull * We're awake. Make USR1 not interrupt system calls.
142 cea10000 2005-05-01 devnull */
143 cea10000 2005-05-01 devnull lock(r->l);
144 cea10000 2005-05-01 devnull ignusr1(1);
145 cea10000 2005-05-01 devnull if(r->asleep && r->pid == getpid()){
146 cea10000 2005-05-01 devnull /* Didn't really wake up - signal from something else */
147 cea10000 2005-05-01 devnull goto again;
148 cea10000 2005-05-01 devnull }
149 cea10000 2005-05-01 devnull }
150 cea10000 2005-05-01 devnull
151 cea10000 2005-05-01 devnull void
152 cea10000 2005-05-01 devnull _procwakeup(_Procrendez *r)
153 cea10000 2005-05-01 devnull {
154 cea10000 2005-05-01 devnull if(r->asleep){
155 cea10000 2005-05-01 devnull r->asleep = 0;
156 cea10000 2005-05-01 devnull assert(r->pid >= 1);
157 cea10000 2005-05-01 devnull kill(r->pid, SIGUSR1);
158 cea10000 2005-05-01 devnull }
159 cea10000 2005-05-01 devnull }
160 cea10000 2005-05-01 devnull
161 cea10000 2005-05-01 devnull void
162 cea10000 2005-05-01 devnull _procwakeupandunlock(_Procrendez *r)
163 cea10000 2005-05-01 devnull {
164 cea10000 2005-05-01 devnull _procwakeup(r);
165 cea10000 2005-05-01 devnull unlock(r->l);
166 cea10000 2005-05-01 devnull }
167 cea10000 2005-05-01 devnull
168 cea10000 2005-05-01 devnull
169 cea10000 2005-05-01 devnull /*
170 cea10000 2005-05-01 devnull * process creation and exit
171 cea10000 2005-05-01 devnull */
172 cea10000 2005-05-01 devnull typedef struct Stackfree Stackfree;
173 cea10000 2005-05-01 devnull struct Stackfree
174 cea10000 2005-05-01 devnull {
175 cea10000 2005-05-01 devnull Stackfree *next;
176 cea10000 2005-05-01 devnull int pid;
177 cea10000 2005-05-01 devnull };
178 cea10000 2005-05-01 devnull static Lock stacklock;
179 cea10000 2005-05-01 devnull static Stackfree *stackfree;
180 cea10000 2005-05-01 devnull
181 cea10000 2005-05-01 devnull static void
182 cea10000 2005-05-01 devnull delayfreestack(uchar *stk)
183 cea10000 2005-05-01 devnull {
184 cea10000 2005-05-01 devnull Stackfree *sf;
185 cea10000 2005-05-01 devnull
186 cea10000 2005-05-01 devnull sf = (Stackfree*)stk;
187 cea10000 2005-05-01 devnull sf->pid = getpid();
188 cea10000 2005-05-01 devnull lock(&stacklock);
189 cea10000 2005-05-01 devnull sf->next = stackfree;
190 cea10000 2005-05-01 devnull stackfree = sf;
191 cea10000 2005-05-01 devnull unlock(&stacklock);
192 cea10000 2005-05-01 devnull }
193 cea10000 2005-05-01 devnull
194 cea10000 2005-05-01 devnull static void
195 cea10000 2005-05-01 devnull dofreestacks(void)
196 cea10000 2005-05-01 devnull {
197 cea10000 2005-05-01 devnull Stackfree *sf, *last, *next;
198 cea10000 2005-05-01 devnull
199 cea10000 2005-05-01 devnull if(stackfree==nil || !canlock(&stacklock))
200 cea10000 2005-05-01 devnull return;
201 cea10000 2005-05-01 devnull
202 cea10000 2005-05-01 devnull for(last=nil,sf=stackfree; sf; last=sf,sf=next){
203 cea10000 2005-05-01 devnull next = sf->next;
204 cea10000 2005-05-01 devnull if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
205 cea10000 2005-05-01 devnull free(sf);
206 cea10000 2005-05-01 devnull if(last)
207 cea10000 2005-05-01 devnull last->next = next;
208 cea10000 2005-05-01 devnull else
209 cea10000 2005-05-01 devnull stackfree = next;
210 cea10000 2005-05-01 devnull sf = last;
211 cea10000 2005-05-01 devnull }
212 cea10000 2005-05-01 devnull }
213 cea10000 2005-05-01 devnull unlock(&stacklock);
214 cea10000 2005-05-01 devnull }
215 cea10000 2005-05-01 devnull
216 cea10000 2005-05-01 devnull static int
217 cea10000 2005-05-01 devnull startprocfn(void *v)
218 cea10000 2005-05-01 devnull {
219 cea10000 2005-05-01 devnull void **a;
220 cea10000 2005-05-01 devnull uchar *stk;
221 cea10000 2005-05-01 devnull void (*fn)(void*);
222 cea10000 2005-05-01 devnull Proc *p;
223 cea10000 2005-05-01 devnull
224 cea10000 2005-05-01 devnull a = (void**)v;
225 cea10000 2005-05-01 devnull fn = a[0];
226 cea10000 2005-05-01 devnull p = a[1];
227 cea10000 2005-05-01 devnull stk = a[2];
228 cea10000 2005-05-01 devnull free(a);
229 cea10000 2005-05-01 devnull p->osprocid = getpid();
230 cea10000 2005-05-01 devnull
231 cea10000 2005-05-01 devnull (*fn)(p);
232 cea10000 2005-05-01 devnull
233 cea10000 2005-05-01 devnull delayfreestack(stk);
234 cea10000 2005-05-01 devnull _exit(0);
235 cea10000 2005-05-01 devnull return 0;
236 cea10000 2005-05-01 devnull }
237 cea10000 2005-05-01 devnull
238 cea10000 2005-05-01 devnull void
239 cea10000 2005-05-01 devnull _procstart(Proc *p, void (*fn)(Proc*))
240 cea10000 2005-05-01 devnull {
241 cea10000 2005-05-01 devnull void **a;
242 cea10000 2005-05-01 devnull uchar *stk;
243 cea10000 2005-05-01 devnull int pid;
244 cea10000 2005-05-01 devnull
245 cea10000 2005-05-01 devnull dofreestacks();
246 cea10000 2005-05-01 devnull a = malloc(3*sizeof a[0]);
247 cea10000 2005-05-01 devnull if(a == nil)
248 cea10000 2005-05-01 devnull sysfatal("_procstart malloc: %r");
249 cea10000 2005-05-01 devnull stk = malloc(65536);
250 cea10000 2005-05-01 devnull if(stk == nil)
251 cea10000 2005-05-01 devnull sysfatal("_procstart malloc stack: %r");
252 cea10000 2005-05-01 devnull
253 cea10000 2005-05-01 devnull a[0] = fn;
254 cea10000 2005-05-01 devnull a[1] = p;
255 cea10000 2005-05-01 devnull a[2] = stk;
256 cea10000 2005-05-01 devnull
257 cea10000 2005-05-01 devnull pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a);
258 cea10000 2005-05-01 devnull if(pid < 0){
259 cea10000 2005-05-01 devnull fprint(2, "_procstart rfork_thread: %r\n");
260 cea10000 2005-05-01 devnull abort();
261 cea10000 2005-05-01 devnull }
262 cea10000 2005-05-01 devnull }
263 cea10000 2005-05-01 devnull
264 cea10000 2005-05-01 devnull static char *threadexitsmsg;
265 cea10000 2005-05-01 devnull void
266 cea10000 2005-05-01 devnull sigusr2handler(int s)
267 cea10000 2005-05-01 devnull {
268 cea10000 2005-05-01 devnull /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
269 cea10000 2005-05-01 devnull if(threadexitsmsg)
270 cea10000 2005-05-01 devnull _exits(threadexitsmsg);
271 cea10000 2005-05-01 devnull }
272 cea10000 2005-05-01 devnull
273 cea10000 2005-05-01 devnull void
274 cea10000 2005-05-01 devnull threadexitsall(char *msg)
275 cea10000 2005-05-01 devnull {
276 cea10000 2005-05-01 devnull static int pid[1024];
277 cea10000 2005-05-01 devnull int i, npid, mypid;
278 cea10000 2005-05-01 devnull Proc *p;
279 cea10000 2005-05-01 devnull
280 cea10000 2005-05-01 devnull if(msg == nil)
281 cea10000 2005-05-01 devnull msg = "";
282 cea10000 2005-05-01 devnull mypid = getpid();
283 cea10000 2005-05-01 devnull lock(&_threadprocslock);
284 cea10000 2005-05-01 devnull threadexitsmsg = msg;
285 cea10000 2005-05-01 devnull npid = 0;
286 cea10000 2005-05-01 devnull for(p=_threadprocs; p; p=p->next)
287 cea10000 2005-05-01 devnull if(p->osprocid != mypid && p->osprocid >= 1)
288 cea10000 2005-05-01 devnull pid[npid++] = p->osprocid;
289 cea10000 2005-05-01 devnull for(i=0; i<npid; i++)
290 cea10000 2005-05-01 devnull kill(pid[i], SIGUSR2);
291 cea10000 2005-05-01 devnull unlock(&_threadprocslock);
292 cea10000 2005-05-01 devnull exits(msg);
293 cea10000 2005-05-01 devnull }
294 cea10000 2005-05-01 devnull
295 cea10000 2005-05-01 devnull /*
296 cea10000 2005-05-01 devnull * per-process data, indexed by pid
297 cea10000 2005-05-01 devnull */
298 cea10000 2005-05-01 devnull typedef struct Perproc Perproc;
299 cea10000 2005-05-01 devnull struct Perproc
300 cea10000 2005-05-01 devnull {
301 cea10000 2005-05-01 devnull int pid;
302 cea10000 2005-05-01 devnull Proc *proc;
303 cea10000 2005-05-01 devnull };
304 cea10000 2005-05-01 devnull
305 cea10000 2005-05-01 devnull static Lock perlock;
306 cea10000 2005-05-01 devnull static Perproc perproc[1024];
307 cea10000 2005-05-01 devnull #define P ((Proc*)-1)
308 cea10000 2005-05-01 devnull
309 cea10000 2005-05-01 devnull static Perproc*
310 cea10000 2005-05-01 devnull myperproc(void)
311 cea10000 2005-05-01 devnull {
312 cea10000 2005-05-01 devnull int i, pid, h;
313 cea10000 2005-05-01 devnull Perproc *p;
314 cea10000 2005-05-01 devnull
315 cea10000 2005-05-01 devnull pid = getpid();
316 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
317 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
318 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
319 cea10000 2005-05-01 devnull if(p->pid == pid)
320 cea10000 2005-05-01 devnull return p;
321 cea10000 2005-05-01 devnull if(p->pid == 0){
322 cea10000 2005-05-01 devnull print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
323 cea10000 2005-05-01 devnull break;
324 cea10000 2005-05-01 devnull }
325 cea10000 2005-05-01 devnull }
326 cea10000 2005-05-01 devnull fprint(2, "myperproc %d: cannot find self\n", pid);
327 cea10000 2005-05-01 devnull abort();
328 cea10000 2005-05-01 devnull return nil;
329 cea10000 2005-05-01 devnull }
330 cea10000 2005-05-01 devnull
331 cea10000 2005-05-01 devnull static Perproc*
332 cea10000 2005-05-01 devnull newperproc(void)
333 cea10000 2005-05-01 devnull {
334 cea10000 2005-05-01 devnull int i, pid, h;
335 cea10000 2005-05-01 devnull Perproc *p;
336 cea10000 2005-05-01 devnull
337 cea10000 2005-05-01 devnull lock(&perlock);
338 cea10000 2005-05-01 devnull pid = getpid();
339 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
340 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
341 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
342 cea10000 2005-05-01 devnull if(p->pid == pid || p->pid == -1 || p->pid == 0){
343 cea10000 2005-05-01 devnull p->pid = pid;
344 cea10000 2005-05-01 devnull unlock(&perlock);
345 cea10000 2005-05-01 devnull return p;
346 cea10000 2005-05-01 devnull }
347 cea10000 2005-05-01 devnull }
348 cea10000 2005-05-01 devnull fprint(2, "newperproc %d: out of procs\n", pid);
349 cea10000 2005-05-01 devnull abort();
350 cea10000 2005-05-01 devnull return nil;
351 cea10000 2005-05-01 devnull }
352 cea10000 2005-05-01 devnull
353 cea10000 2005-05-01 devnull Proc*
354 cea10000 2005-05-01 devnull _threadproc(void)
355 cea10000 2005-05-01 devnull {
356 cea10000 2005-05-01 devnull return myperproc()->proc;
357 cea10000 2005-05-01 devnull }
358 cea10000 2005-05-01 devnull
359 cea10000 2005-05-01 devnull void
360 cea10000 2005-05-01 devnull _threadsetproc(Proc *p)
361 cea10000 2005-05-01 devnull {
362 cea10000 2005-05-01 devnull Perproc *pp;
363 cea10000 2005-05-01 devnull
364 cea10000 2005-05-01 devnull if(p)
365 cea10000 2005-05-01 devnull p->osprocid = getpid();
366 cea10000 2005-05-01 devnull pp = newperproc();
367 cea10000 2005-05-01 devnull pp->proc = p;
368 cea10000 2005-05-01 devnull if(p == nil)
369 cea10000 2005-05-01 devnull pp->pid = -1;
370 cea10000 2005-05-01 devnull }
371 cea10000 2005-05-01 devnull
372 cea10000 2005-05-01 devnull void
373 cea10000 2005-05-01 devnull _pthreadinit(void)
374 cea10000 2005-05-01 devnull {
375 cea10000 2005-05-01 devnull __isthreaded = 1;
376 cea10000 2005-05-01 devnull signal(SIGUSR2, sigusr2handler);
377 cea10000 2005-05-01 devnull }
378 cea10000 2005-05-01 devnull
379 cea10000 2005-05-01 devnull void
380 cea10000 2005-05-01 devnull _threadpexit(void)
381 cea10000 2005-05-01 devnull {
382 cea10000 2005-05-01 devnull _exit(0);
383 cea10000 2005-05-01 devnull }
384 cea10000 2005-05-01 devnull