cae36a52 |
1 | #include <u.h> |
2 | #include <libc.h> |
3 | #include <ureg.h> |
4 | #include "dat.h" |
5 | #include "fns.h" |
6 | #include "linux.h" |
7 | |
8 | static int timernotefd; |
9 | static void timerproc(void*); |
10 | |
11 | static int |
12 | pidhash(int pid) |
13 | { |
14 | return (pid - 1) % MAXPROC; |
15 | } |
16 | |
17 | Uproc* |
18 | getproc(int tid) |
19 | { |
20 | Uproc *p; |
21 | |
22 | if(tid > 0){ |
23 | p = &proctab.proc[pidhash(tid)]; |
24 | if(p->tid == tid) |
25 | return p; |
26 | } |
27 | return nil; |
28 | } |
29 | |
30 | Uproc* |
31 | getprocn(int n) |
32 | { |
33 | Uproc *p; |
34 | |
35 | p = &proctab.proc[n]; |
36 | if(p->tid > 0) |
37 | return p; |
38 | return nil; |
39 | } |
40 | |
41 | static Uproc* |
42 | allocproc(void) |
43 | { |
44 | Uproc *p; |
45 | int tid, i; |
46 | |
47 | for(i=0; i<MAXPROC; i++){ |
48 | tid = proctab.nextpid++; |
49 | p = &proctab.proc[pidhash(tid)]; |
50 | if(p->tid <= 0){ |
51 | proctab.alloc++; |
52 | |
53 | p->tid = tid; |
54 | p->pid = tid; |
55 | p->pgid = tid; |
56 | p->psid = tid; |
57 | return p; |
58 | } |
59 | } |
60 | |
61 | trace("allocproc(): out of processes"); |
62 | return nil; |
63 | } |
64 | |
65 | static void |
66 | freeproc(Uproc *p) |
67 | { |
68 | Uwait *w; |
69 | |
70 | while(w = p->freewait){ |
71 | p->freewait = w->next; |
72 | free(w); |
73 | } |
74 | exittrace(p); |
75 | free(p->comm); |
76 | free(p->root); |
77 | free(p->cwd); |
78 | free(p->kcwd); |
79 | memset(p, 0, sizeof(*p)); |
80 | proctab.alloc--; |
81 | } |
82 | |
83 | void initproc(void) |
84 | { |
85 | Uproc *p; |
86 | char buf[1024]; |
87 | int pid; |
88 | |
89 | proctab.nextpid = 10; |
90 | |
91 | p = allocproc(); |
92 | p->kpid = getpid(); |
93 | snprint(buf, sizeof(buf), "/proc/%d/note", p->kpid); |
94 | p->notefd = open(buf, OWRITE); |
95 | snprint(buf, sizeof(buf), "/proc/%d/args", p->kpid); |
96 | p->argsfd = open(buf, ORDWR); |
97 | |
98 | current = p; |
99 | |
100 | inittrace(); |
101 | inittime(); |
102 | initsignal(); |
103 | initmem(); |
104 | inittls(); |
105 | initfile(); |
106 | |
107 | if((pid = procfork(timerproc, nil, 0)) < 0) |
108 | panic("initproc: unable to fork timerproc: %r"); |
109 | |
110 | snprint(buf, sizeof(buf), "/proc/%d/note", pid); |
111 | timernotefd = open(buf, OWRITE); |
112 | |
113 | current->root = nil; |
114 | current->cwd = kstrdup(getwd(buf, sizeof(buf))); |
115 | current->kcwd = kstrdup(current->cwd); |
116 | current->linkloop = 0; |
117 | current->starttime = nsec(); |
118 | |
119 | inittrap(); |
120 | } |
121 | |
122 | void |
123 | setprocname(char *s) |
124 | { |
125 | if(current == nil){ |
126 | char buf[32]; |
127 | int fd; |
128 | |
129 | snprint(buf, sizeof(buf), "/proc/%d/args", getpid()); |
130 | if((fd = open(buf, OWRITE)) >= 0){ |
131 | write(fd, s, strlen(s)); |
132 | close(fd); |
133 | } |
134 | } else { |
135 | write(current->argsfd, s, strlen(s)); |
136 | } |
137 | } |
138 | |
139 | static void |
140 | intrnote(void *, char *msg) |
141 | { |
142 | if(strncmp(msg, "interrupt", 9) == 0) |
143 | noted(NCONT); |
144 | noted(NDFLT); |
145 | } |
146 | |
147 | struct kprocforkargs |
148 | { |
149 | int flags; |
150 | void (*func)(void *aux); |
151 | void *aux; |
152 | }; |
153 | |
154 | static int |
155 | kprocfork(void *arg) |
156 | { |
157 | struct kprocforkargs args; |
158 | int pid; |
159 | |
160 | memmove(&args, arg, sizeof(args)); |
161 | |
162 | if((pid = rfork(RFPROC|RFMEM|args.flags)) != 0) |
163 | return pid; |
164 | |
165 | notify(intrnote); |
166 | |
167 | unmapuserspace(); |
168 | current = nil; |
169 | |
170 | profme(); |
171 | args.func(args.aux); |
172 | longjmp(exitjmp, 1); |
173 | return -1; |
174 | } |
175 | |
176 | /* |
177 | * procfork starts a kernel process running on kstack. |
178 | * that process will have linux memory segments (stack, private, |
179 | * shared) unmapped but plan9 segments (text, bss, stack) shared. |
180 | * here is no Uproc associated with it! current will be set to nil so |
181 | * you cant call sys_????() functions in here. |
182 | * procfork returns the plan9 pid. (usefull for posting notes) |
183 | */ |
184 | int procfork(void (*func)(void *aux), void *aux, int flags) |
185 | { |
186 | struct kprocforkargs args; |
187 | |
188 | args.flags = flags; |
189 | args.func = func; |
190 | args.aux = aux; |
191 | |
192 | return onstack(kstack, kprocfork, &args); |
193 | } |
194 | |
195 | static void *Intr = (void*)~0; |
196 | |
197 | static char Notifyme[] = "notifyme"; |
198 | static char Wakeme[] = "wakeme"; |
199 | static char Xchange[] = "xchange"; |
200 | |
201 | static char Wakeup[] = "wakeup"; |
202 | static char Abort[] = "abort"; |
203 | |
204 | int notifyme(int on) |
205 | { |
206 | Uproc *p; |
207 | |
208 | p = current; |
209 | qlock(p); |
210 | if(on){ |
211 | if(p->notified || signalspending(p)){ |
212 | qunlock(p); |
213 | return 1; |
214 | } |
215 | if(p->state == nil) |
216 | p->state = Notifyme; |
217 | } else { |
218 | p->state = nil; |
219 | } |
220 | qunlock(p); |
221 | return 0; |
222 | } |
223 | |
224 | void wakeme(int on) |
225 | { |
226 | Uproc *p; |
227 | |
228 | p = current; |
229 | qlock(p); |
230 | if(on){ |
231 | if(p->state == nil) |
232 | p->state = Wakeme; |
233 | } else { |
234 | p->state = nil; |
235 | } |
236 | qunlock(p); |
237 | } |
238 | |
239 | int sleepproc(QLock *l, int flags) |
240 | { |
241 | Uproc *p; |
242 | void *ret; |
243 | char *x; |
244 | |
245 | p = current; |
246 | qlock(p); |
247 | x = p->state; |
248 | if(x == nil || x == Wakeme){ |
249 | p->xstate = x; |
250 | p->state = Xchange; |
251 | if(l != nil) |
252 | qunlock(l); |
253 | qunlock(p); |
254 | if(flags && signalspending(p)){ |
255 | ret = Intr; |
256 | } else { |
257 | ret = rendezvous(p, Xchange); |
258 | } |
259 | if(ret == Intr){ |
260 | qlock(p); |
261 | if(p->state != Xchange){ |
262 | while((ret = rendezvous(p, Xchange)) == Intr) |
263 | ; |
264 | } else { |
265 | p->state = x; |
266 | } |
267 | qunlock(p); |
268 | } |
269 | if(l != nil) |
270 | qlock(l); |
271 | } else { |
272 | p->state = Wakeme; |
273 | ret = x; |
274 | qunlock(p); |
275 | } |
276 | return (ret == Wakeup) ? 0 : -ERESTART; |
277 | } |
278 | |
279 | static int |
280 | wakeup(Uproc *proc, char *m, int force) |
281 | { |
282 | char *x; |
283 | |
284 | if(proc != nil){ |
285 | qlock(proc); |
286 | x = proc->state; |
287 | |
288 | if(x == Wakeme){ |
289 | proc->state = m; |
290 | qunlock(proc); |
291 | return 1; |
292 | } |
293 | if(x == Xchange){ |
294 | proc->state = proc->xstate; |
295 | proc->xstate = nil; |
296 | qunlock(proc); |
297 | while(rendezvous(proc, m) == Intr) |
298 | ; |
299 | return 1; |
300 | } |
301 | if((m != Wakeup) && (proc->notified == 0)){ |
302 | if(x == Notifyme) |
303 | proc->state = nil; |
304 | if(x == Notifyme || force){ |
305 | proc->notified = 1; |
306 | qunlock(proc); |
307 | write(proc->notefd, "interrupt", 9); |
308 | return 1; |
309 | } |
310 | } |
311 | qunlock(proc); |
312 | } |
313 | return 0; |
314 | } |
315 | |
316 | Uwait* addwaitq(Uwaitq *q) |
317 | { |
318 | Uproc *p; |
319 | Uwait *w; |
320 | |
321 | p = current; |
322 | if(w = p->freewait){ |
323 | p->freewait = w->next; |
324 | } else { |
325 | w = kmalloc(sizeof(*w)); |
326 | } |
327 | |
328 | w->next = nil; |
329 | |
330 | w->proc = p; |
331 | w->file = nil; |
332 | |
333 | w->q = q; |
334 | qlock(q); |
335 | w->nextq = q->w; |
336 | q->w = w; |
337 | qunlock(q); |
338 | |
339 | return w; |
340 | } |
341 | |
342 | void delwaitq(Uwait *w) |
343 | { |
344 | Uwaitq *q; |
345 | Uwait **x; |
346 | |
347 | q = w->q; |
348 | qlock(q); |
349 | for(x = &q->w; *x; x=&((*x)->nextq)){ |
350 | if(*x == w){ |
351 | *x = w->nextq; |
352 | break; |
353 | } |
354 | } |
355 | qunlock(q); |
356 | |
357 | w->q = nil; |
358 | w->nextq = nil; |
359 | |
360 | w->proc = nil; |
361 | putfile(w->file); |
362 | w->file = nil; |
363 | |
364 | w->next = current->freewait; |
365 | current->freewait = w; |
366 | } |
367 | |
368 | int requeue(Uwaitq *q1, Uwaitq *q2, int nrequeue) |
369 | { |
370 | int n; |
371 | Uwait *w; |
372 | |
373 | n = 1000; |
374 | for(;;){ |
375 | qlock(q1); |
376 | if(canqlock(q2)) |
377 | break; |
378 | qunlock(q1); |
379 | if(--n <= 0) |
380 | return 0; |
381 | sleep(0); |
382 | } |
383 | n = 0; |
384 | while((w = q1->w) && (n < nrequeue)){ |
385 | q1->w = w->nextq; |
386 | w->q = q2; |
387 | w->nextq = q2->w; |
388 | q2->w = w; |
389 | n++; |
390 | } |
391 | qunlock(q2); |
392 | qunlock(q1); |
393 | return n; |
394 | } |
395 | |
396 | int wakeq(Uwaitq *q, int nwake) |
397 | { |
398 | int n; |
399 | Uwait *w; |
400 | |
401 | n = 0; |
402 | if(q != nil){ |
403 | qlock(q); |
404 | for(w = q->w; w && n < nwake; w=w->nextq) |
405 | n += wakeup(w->proc, Wakeup, 0); |
406 | qunlock(q); |
407 | } |
408 | return n; |
409 | } |
410 | |
411 | int sleepq(Uwaitq *q, QLock *l, int flags) |
412 | { |
413 | Uwait *w; |
414 | int ret; |
415 | |
416 | w = addwaitq(q); |
417 | ret = sleepproc(l, flags); |
418 | delwaitq(w); |
419 | |
420 | return ret; |
421 | } |
422 | |
423 | static Uproc *alarmq; |
424 | |
425 | int |
426 | procsetalarm(Uproc *proc, vlong t) |
427 | { |
428 | Uproc **pp; |
429 | int ret; |
430 | |
431 | if(proc->alarm && t >= proc->alarm) |
432 | return 0; |
433 | ret = (alarmq == nil) || (t < alarmq->alarm); |
434 | for(pp = &alarmq; *pp; pp = &((*pp)->alarmq)){ |
435 | if(*pp == proc){ |
436 | *pp = proc->alarmq; |
437 | break; |
438 | } |
439 | } |
440 | for(pp = &alarmq; *pp; pp = &((*pp)->alarmq)) |
441 | if((*pp)->alarm > t) |
442 | break; |
443 | proc->alarm = t; |
444 | proc->alarmq = *pp; |
445 | *pp = proc; |
446 | return ret; |
447 | } |
448 | |
449 | void |
450 | setalarm(vlong t) |
451 | { |
452 | qlock(&proctab); |
453 | if(procsetalarm(current, t)) |
454 | write(timernotefd, "interrupt", 9); |
455 | qunlock(&proctab); |
456 | } |
457 | |
458 | /* signal.c */ |
459 | extern void alarmtimer(Uproc *proc, vlong now); |
460 | |
461 | static void |
462 | timerproc(void*) |
463 | { |
464 | Uproc *h; |
465 | vlong now; |
466 | long m; |
467 | |
468 | setprocname("timerproc()"); |
469 | |
470 | while(proctab.alloc > 0){ |
471 | qlock(&proctab); |
472 | m = 2000; |
473 | now = nsec(); |
474 | while(h = alarmq){ |
475 | if(now < h->alarm){ |
476 | m = (h->alarm - now) / 1000000; |
477 | break; |
478 | } |
479 | alarmq = h->alarmq; |
480 | h->alarm = 0; |
481 | h->alarmq = nil; |
482 | if(h->timeout){ |
483 | if(now >= h->timeout){ |
484 | h->timeout = 0; |
485 | wakeup(h, Wakeup, 0); |
486 | } else |
487 | procsetalarm(h, h->timeout); |
488 | } |
489 | alarmtimer(h, now); |
490 | } |
491 | qunlock(&proctab); |
492 | sleep((m + (1000/HZ-1))/(1000/HZ)); |
493 | } |
494 | } |
495 | |
496 | /* |
497 | static void |
498 | timerproc(void *) |
499 | { |
500 | Uproc *p; |
501 | vlong expire, now, wake, dead; |
502 | int err, i, alive; |
503 | char c; |
504 | |
505 | setprocname("timerproc()"); |
506 | dead = 0; |
507 | for(;;){ |
508 | qlock(&proctab); |
509 | now = nsec(); |
510 | wake = now + 60000000000LL; |
511 | alive = 0; |
512 | for(i=0; i<MAXPROC; i++){ |
513 | if((p = getprocn(i)) == nil) |
514 | continue; |
515 | if(p->wstate & WEXITED) |
516 | continue; |
517 | if(p->kpid <= 0) |
518 | continue; |
519 | |
520 | if(now >= dead){ |
521 | if(read(p->argsfd, &c, 1) < 0){ |
522 | err = mkerror(); |
523 | if(err != -EINTR && err != -ERESTART){ |
524 | p->kpid = 0; |
525 | qunlock(&proctab); |
526 | exitproc(p, SIGKILL, 1); |
527 | qlock(&proctab); |
528 | continue; |
529 | } |
530 | } |
531 | } |
532 | alive++; |
533 | expire = p->timeout; |
534 | if(expire > 0){ |
535 | if(now >= expire){ |
536 | p->timeout = 0; |
537 | wakeup(p, Wakeup, 0); |
538 | } else { |
539 | if(expire < wake) |
540 | wake = expire; |
541 | } |
542 | } |
543 | expire = alarmtimer(p, now, wake); |
544 | if(expire < wake) |
545 | wake = expire; |
546 | } |
547 | qunlock(&proctab); |
548 | |
549 | if(now >= dead) |
550 | dead = now + 5000000000LL; |
551 | if(dead < wake) |
552 | wake = dead; |
553 | if(alive == 0) |
554 | break; |
555 | wake -= now; |
556 | |
557 | sleep(wake/1000000LL); |
558 | } |
559 | } |
560 | */ |
561 | |
562 | int sys_waitpid(int pid, int *pexit, int opt) |
563 | { |
564 | int i, n, m, status; |
565 | Uproc *p; |
566 | |
567 | trace("sys_waitpid(%d, %p, %d)", pid, pexit, opt); |
568 | |
569 | m = WEXITED; |
570 | if(opt & WUNTRACED) |
571 | m |= WSTOPPED; |
572 | if(opt & WCONTINUED) |
573 | m |= WCONTINUED; |
574 | |
575 | qlock(&proctab); |
576 | for(;;){ |
577 | n = 0; |
578 | for(i=0; i<MAXPROC; i++){ |
579 | if((p = getprocn(i)) == nil) |
580 | continue; |
581 | if(p == current) |
582 | continue; |
583 | if((p->exitsignal != SIGCHLD) && (opt & (WALL|WCLONE))==0) |
584 | continue; |
585 | if(p->ppid != current->pid) |
586 | continue; |
587 | if(pid > 0){ |
588 | if(p->pid != pid) |
589 | continue; |
590 | } else if(pid == 0){ |
591 | if(p->pgid != current->pgid) |
592 | continue; |
593 | } else if(pid < -1){ |
594 | if(p->pgid != -pid) |
595 | continue; |
596 | } |
597 | n++; |
598 | trace("sys_waitpid(): child %d wstate %x", p->pid, p->wstate); |
599 | if(p->wevent & m) |
600 | goto found; |
601 | } |
602 | if(n == 0){ |
603 | qunlock(&proctab); |
604 | trace("sys_waitpid(): no children we can wait for"); |
605 | return -ECHILD; |
606 | } |
607 | if(opt & WNOHANG){ |
608 | qunlock(&proctab); |
609 | trace("sys_waitpid(): no exited/stoped/cont children"); |
610 | return 0; |
611 | } |
612 | if((i = sleepproc(&proctab, 1)) < 0){ |
613 | qunlock(&proctab); |
614 | return i; |
615 | } |
616 | } |
617 | |
618 | found: |
619 | pid = p->pid; |
620 | status = p->exitcode; |
621 | p->wevent &= ~(p->wevent & m); |
622 | if(p->wstate & WEXITED){ |
623 | trace("sys_waitpid(): found zombie %d exitcode %d", pid, status); |
624 | freeproc(p); |
625 | } |
626 | qunlock(&proctab); |
627 | if(pexit) |
628 | *pexit = status; |
629 | return pid; |
630 | } |
631 | |
632 | struct linux_rusage { |
633 | struct linux_timeval ru_utime; /* user time used */ |
634 | struct linux_timeval ru_stime; /* system time used */ |
635 | long ru_maxrss; /* maximum resident set size */ |
636 | long ru_ixrss; /* integral shared memory size */ |
637 | long ru_idrss; /* integral unshared data size */ |
638 | long ru_isrss; /* integral unshared stack size */ |
639 | long ru_minflt; /* page reclaims */ |
640 | long ru_majflt; /* page faults */ |
641 | long ru_nswap; /* swaps */ |
642 | long ru_inblock; /* block input operations */ |
643 | long ru_oublock; /* block output operations */ |
644 | long ru_msgsnd; /* messages sent */ |
645 | long ru_msgrcv; /* messages received */ |
646 | long ru_nsignals; /* signals received */ |
647 | long ru_nvcsw; /* voluntary context switches */ |
648 | long ru_nivcsw; /* involuntary context switches */ |
649 | }; |
650 | |
651 | int sys_wait4(int pid, int *pexit, int opt, void *prusage) |
652 | { |
653 | int ret; |
654 | struct linux_rusage *ru = prusage; |
655 | |
656 | trace("sys_wait4(%d, %p, %d, %p)", pid, pexit, opt, prusage); |
657 | |
658 | ret = sys_waitpid(pid, pexit, opt); |
659 | if(ru != nil) |
660 | memset(ru, 0, sizeof(*ru)); |
661 | |
662 | return ret; |
663 | } |
664 | |
665 | int |
666 | threadcount(int pid) |
667 | { |
668 | Uproc *p; |
669 | int i, n; |
670 | |
671 | n = 0; |
672 | for(i = 0; i<MAXPROC; i++){ |
673 | p = getprocn(i); |
674 | if(p != nil && p->pid == pid) |
675 | n++; |
676 | } |
677 | return n; |
678 | } |
679 | |
680 | int |
681 | killproc(Uproc *p, Usiginfo *info, int group) |
682 | { |
683 | int i, n; |
684 | Uproc *w; |
685 | int sig, err; |
686 | |
687 | if((err = sendsignal(p, info, group)) <= 0) |
688 | return err; |
689 | w = p; |
690 | sig = info->signo; |
691 | if(group && !wantssignal(w, sig)){ |
692 | for(i=1, n = p->tid + 1; i<MAXPROC; i++, n++){ |
693 | if((p = getprocn(pidhash(n))) == nil) |
694 | continue; |
695 | if(p->pid != w->pid) |
696 | continue; |
697 | if(!wantssignal(p, info->signo)) |
698 | continue; |
699 | w = p; |
700 | break; |
701 | } |
702 | } |
703 | wakeup(w, Abort, (sig == SIGKILL || sig == SIGSTOP || sig == SIGALRM)); |
704 | return 0; |
705 | } |
706 | |
707 | enum |
708 | { |
709 | CLD_EXITED = 1, |
710 | CLD_KILLED, |
711 | CLD_DUMPED, |
712 | CLD_TRAPPED, |
713 | CLD_STOPPED, |
714 | CLD_CONTINUED, |
715 | }; |
716 | |
717 | /* |
718 | * queue the exit signal into the parent process. this |
719 | * doesnt do the wakeup like killproc(). |
720 | */ |
721 | static int |
722 | sendexitsignal(Uproc *parent, Uproc *proc, int sig, int code) |
723 | { |
724 | Usiginfo si; |
725 | |
726 | memset(&si, 0, sizeof(si)); |
727 | switch(si.signo = sig){ |
728 | case SIGCHLD: |
729 | switch(code & 0xFF){ |
730 | case 0: |
731 | si.code = CLD_EXITED; |
732 | break; |
733 | case SIGSTOP: |
734 | si.code = CLD_STOPPED; |
735 | break; |
736 | case SIGCONT: |
737 | si.code = CLD_CONTINUED; |
738 | break; |
739 | case SIGKILL: |
740 | si.code = CLD_KILLED; |
741 | break; |
742 | default: |
743 | si.code = CLD_DUMPED; |
744 | break; |
745 | } |
746 | si.chld.pid = proc->pid; |
747 | si.chld.uid = proc->uid; |
748 | si.chld.status = code; |
749 | } |
750 | return sendsignal(parent, &si, 1); |
751 | } |
752 | |
753 | /* |
754 | * wakeup all threads who are in the same thread group |
755 | * as p including p. must be called with proctab locked. |
756 | */ |
757 | static void |
758 | wakeupall(Uproc *p, char *m, int force) |
759 | { |
760 | int pid, i, n; |
761 | |
762 | pid = p->pid; |
763 | for(i=0, n = p->tid; i<MAXPROC; i++, n++) |
764 | if(p = getprocn(pidhash(n))) |
765 | if(p->pid == pid) |
766 | wakeup(p, m, force); |
767 | } |
768 | |
769 | static void |
770 | zap(void *) |
771 | { |
772 | exitproc(current, 0, 0); |
773 | } |
774 | |
775 | void |
776 | zapthreads(void) |
777 | { |
778 | Uproc *p; |
779 | int i, n, z; |
780 | |
781 | for(;;){ |
782 | z = 0; |
783 | for(i=1, n = current->tid+1; i<MAXPROC; i++, n++){ |
784 | if((p = getprocn(pidhash(n))) == nil) |
785 | continue; |
786 | if(p->pid != current->pid || p == current) |
787 | continue; |
788 | if(p->kpid <= 0) |
789 | continue; |
790 | |
791 | trace("zapthreads() zapping thread %p", p); |
792 | p->tracearg = current; |
793 | p->traceproc = zap; |
794 | wakeup(p, Abort, 1); |
795 | z++; |
796 | } |
797 | if(z == 0) |
798 | break; |
799 | sleepproc(&proctab, 0); |
800 | } |
801 | } |
802 | |
803 | struct kexitprocargs |
804 | { |
805 | Uproc *proc; |
806 | int code; |
807 | int group; |
808 | }; |
809 | |
810 | #pragma profile off |
811 | |
812 | static int |
813 | kexitproc(void *arg) |
814 | { |
815 | struct kexitprocargs *args; |
816 | Uproc *proc; |
817 | int code, group; |
818 | Uproc *parent, *child, **pp; |
819 | int i; |
820 | |
821 | args = arg; |
822 | proc = args->proc; |
823 | code = args->code; |
824 | group = args->group; |
825 | |
826 | if(proc == current){ |
827 | trace("kexitproc: cleartidptr = %p", proc->cleartidptr); |
828 | if(okaddr(proc->cleartidptr, sizeof(*proc->cleartidptr), 1)) |
829 | *proc->cleartidptr = 0; |
830 | sys_futex((ulong*)proc->cleartidptr, 1, MAXPROC, nil, nil, 0); |
831 | |
832 | qlock(&proctab); |
833 | exitsignal(); |
834 | qunlock(&proctab); |
835 | |
836 | exitmem(); |
837 | } |
838 | |
839 | exitfile(proc); |
840 | |
841 | close(proc->notefd); proc->notefd = -1; |
842 | close(proc->argsfd); proc->argsfd = -1; |
843 | |
844 | qlock(&proctab); |
845 | |
846 | for(pp = &alarmq; *pp; pp = &((*pp)->alarmq)){ |
847 | if(*pp == proc){ |
848 | *pp = proc->alarmq; |
849 | proc->alarmq = nil; |
850 | break; |
851 | } |
852 | } |
853 | |
854 | /* reparent children, and reap when zombies */ |
855 | for(i=0; i<MAXPROC; i++){ |
856 | if((child = getprocn(i)) == nil) |
857 | continue; |
858 | if(child->ppid != proc->pid) |
859 | continue; |
860 | child->ppid = 0; |
861 | if(child->wstate & WEXITED) |
862 | freeproc(child); |
863 | } |
864 | |
865 | /* if we got zapped, just free the proc and wakeup zapper */ |
866 | if((proc == current) && (proc->traceproc == zap) && (parent = proc->tracearg)){ |
867 | freeproc(proc); |
868 | wakeup(parent, Wakeup, 0); |
869 | goto zapped; |
870 | } |
871 | |
872 | if(group && proc == current) |
873 | zapthreads(); |
874 | |
875 | parent = getproc(proc->ppid); |
876 | if((threadcount(proc->pid)==1) && parent && |
877 | (proc->exitsignal == SIGCHLD) && !ignoressignal(parent, SIGCHLD)){ |
878 | |
879 | /* we are zombie */ |
880 | proc->exitcode = code; |
881 | proc->wstate = WEXITED; |
882 | proc->wevent = proc->wstate; |
883 | if(proc == current){ |
884 | current->kpid = 0; |
885 | sendexitsignal(parent, proc, proc->exitsignal, code); |
886 | wakeupall(parent, Abort, 0); |
887 | qunlock(&proctab); |
888 | longjmp(exitjmp, 1); |
889 | } else { |
890 | sendexitsignal(parent, proc, proc->exitsignal, code); |
891 | } |
892 | } else { |
893 | /* we are clone */ |
894 | if(parent && proc->exitsignal > 0) |
895 | sendexitsignal(parent, proc, proc->exitsignal, code); |
896 | freeproc(proc); |
897 | } |
898 | if(parent) |
899 | wakeupall(parent, Abort, 0); |
900 | |
901 | zapped: |
902 | qunlock(&proctab); |
903 | |
904 | if(proc == current) |
905 | longjmp(exitjmp, 1); |
906 | |
907 | return 0; |
908 | } |
909 | |
910 | void exitproc(Uproc *proc, int code, int group) |
911 | { |
912 | struct kexitprocargs args; |
913 | |
914 | trace("exitproc(%p, %d, %d)", proc, code, group); |
915 | |
916 | args.proc = proc; |
917 | args.code = code; |
918 | args.group = group; |
919 | |
920 | if(proc == current){ |
921 | onstack(kstack, kexitproc, &args); |
922 | } else { |
923 | kexitproc(&args); |
924 | } |
925 | } |
926 | |
927 | struct kstoparg |
928 | { |
929 | Uproc *stopper; |
930 | int code; |
931 | }; |
932 | |
933 | static void |
934 | stop(void *aux) |
935 | { |
936 | struct kstoparg *arg = aux; |
937 | |
938 | stopproc(current, arg->code, 0); |
939 | } |
940 | |
941 | void stopproc(Uproc *proc, int code, int group) |
942 | { |
943 | struct kstoparg *arg; |
944 | Uproc *p, *parent; |
945 | int i, n, z; |
946 | |
947 | trace("stopproc(%p, %d, %d)", proc, code, group); |
948 | |
949 | qlock(&proctab); |
950 | proc->exitcode = code; |
951 | proc->wstate = WSTOPPED; |
952 | proc->wevent = proc->wstate; |
953 | |
954 | if((proc == current) && (proc->traceproc == stop) && (arg = proc->tracearg)){ |
955 | proc->traceproc = nil; |
956 | proc->tracearg = nil; |
957 | wakeup(arg->stopper, Wakeup, 0); |
958 | qunlock(&proctab); |
959 | return; |
960 | } |
961 | |
962 | /* put all threads in the stopped state */ |
963 | arg = nil; |
964 | while(group){ |
965 | if(arg == nil){ |
966 | arg = kmalloc(sizeof(*arg)); |
967 | arg->stopper = current; |
968 | arg->code = code; |
969 | } |
970 | z = 0; |
971 | for(i=1, n = proc->tid+1; i<MAXPROC; i++, n++){ |
972 | if((p = getprocn(pidhash(n))) == nil) |
973 | continue; |
974 | if(p->pid != proc->pid || p == proc) |
975 | continue; |
976 | if(p->kpid <= 0) |
977 | continue; |
978 | if(p->wstate & (WSTOPPED | WEXITED)) |
979 | continue; |
980 | |
981 | trace("stopproc() stopping thread %p", p); |
982 | p->tracearg = arg; |
983 | p->traceproc = stop; |
984 | wakeup(p, Abort, 1); |
985 | z++; |
986 | } |
987 | if(z == 0) |
988 | break; |
989 | sleepproc(&proctab, 0); |
990 | } |
991 | free(arg); |
992 | |
993 | if(parent = getproc(proc->ppid)){ |
994 | if(group && !ignoressignal(parent, SIGCHLD)) |
995 | sendexitsignal(parent, proc, SIGCHLD, code); |
996 | wakeupall(parent, Abort, 0); |
997 | } |
998 | qunlock(&proctab); |
999 | } |
1000 | |
1001 | void contproc(Uproc *proc, int code, int group) |
1002 | { |
1003 | Uproc *p, *parent; |
1004 | int i, n; |
1005 | |
1006 | trace("contproc(%p, %d, %d)", proc, code, group); |
1007 | |
1008 | qlock(&proctab); |
1009 | proc->exitcode = code; |
1010 | proc->wstate = WCONTINUED; |
1011 | proc->wevent = proc->wstate; |
1012 | if(group){ |
1013 | for(i=1, n = proc->tid+1; i<MAXPROC; i++, n++){ |
1014 | if((p = getprocn(pidhash(n))) == nil) |
1015 | continue; |
1016 | if(p->pid != proc->pid || p == proc) |
1017 | continue; |
1018 | if(p->kpid <= 0) |
1019 | continue; |
1020 | if((p->wstate & WSTOPPED) == 0) |
1021 | continue; |
1022 | if(p->wstate & (WCONTINUED | WEXITED)) |
1023 | continue; |
1024 | |
1025 | trace("contproc() waking thread %p", p); |
1026 | p->exitcode = code; |
1027 | p->wstate = WCONTINUED; |
1028 | p->wevent = p->wstate; |
1029 | wakeup(p, Wakeup, 0); |
1030 | } |
1031 | } |
1032 | if(parent = getproc(proc->ppid)){ |
1033 | if(group && !ignoressignal(parent, SIGCHLD)) |
1034 | sendexitsignal(parent, proc, SIGCHLD, code); |
1035 | wakeupall(parent, Abort, 0); |
1036 | } |
1037 | qunlock(&proctab); |
1038 | } |
1039 | |
1040 | int sys_exit(int code) |
1041 | { |
1042 | trace("sys_exit(%d)", code); |
1043 | |
1044 | exitproc(current, (code & 0xFF)<<8, 0); |
1045 | return -1; |
1046 | } |
1047 | |
1048 | int sys_exit_group(int code) |
1049 | { |
1050 | trace("sys_exit_group(%d)", code); |
1051 | |
1052 | exitproc(current, (code & 0xFF)<<8, 1); |
1053 | return -1; |
1054 | } |
1055 | |
1056 | struct kcloneprocargs |
1057 | { |
1058 | int flags; |
1059 | void *newstack; |
1060 | int *parenttidptr; |
1061 | void *tlsdescr; |
1062 | int *childtidptr; |
1063 | }; |
1064 | |
1065 | static int |
1066 | kcloneproc(void *arg) |
1067 | { |
1068 | struct kcloneprocargs args; |
1069 | struct linux_user_desc tls; |
1070 | Ureg ureg; |
1071 | int rflags, pid, tid; |
1072 | char buf[80]; |
1073 | Uproc *new; |
1074 | |
1075 | memmove(&args, arg, sizeof(args)); |
1076 | memmove(&ureg, current->ureg, sizeof(ureg)); |
1077 | if(args.flags & CLONE_SETTLS){ |
1078 | if(!okaddr(args.tlsdescr, sizeof(tls), 0)) |
1079 | return -EFAULT; |
1080 | memmove(&tls, args.tlsdescr, sizeof(tls)); |
1081 | } |
1082 | |
1083 | qlock(&proctab); |
1084 | if((new = allocproc()) == nil){ |
1085 | qunlock(&proctab); |
1086 | return -EAGAIN; |
1087 | } |
1088 | tid = new->tid; |
1089 | |
1090 | if(args.flags & CLONE_PARENT_SETTID){ |
1091 | if(!okaddr(args.parenttidptr, sizeof(*args.parenttidptr), 1)){ |
1092 | freeproc(new); |
1093 | qunlock(&proctab); |
1094 | return -EFAULT; |
1095 | } |
1096 | *args.parenttidptr = tid; |
1097 | } |
1098 | |
1099 | rflags = RFPROC; |
1100 | if(args.flags & CLONE_VM) |
1101 | rflags |= RFMEM; |
1102 | |
1103 | qlock(current); |
1104 | if((pid = rfork(rflags)) < 0){ |
1105 | freeproc(new); |
1106 | qunlock(current); |
1107 | qunlock(&proctab); |
1108 | |
1109 | trace("kcloneproc(): rfork failed: %r"); |
1110 | return mkerror(); |
1111 | } |
1112 | |
1113 | if(pid){ |
1114 | /* parent */ |
1115 | new->kpid = pid; |
1116 | new->exitsignal = args.flags & 0xFF; |
1117 | new->innote = 0; |
1118 | new->ureg = &ureg; |
1119 | new->syscall = current->syscall; |
1120 | new->sysret = current->sysret; |
1121 | new->comm = nil; |
1122 | new->ncomm = 0; |
1123 | new->linkloop = 0; |
1124 | new->root = current->root ? kstrdup(current->root) : nil; |
1125 | new->cwd = kstrdup(current->cwd); |
1126 | new->kcwd = kstrdup(current->kcwd); |
1127 | new->starttime = nsec(); |
1128 | |
1129 | snprint(buf, sizeof(buf), "/proc/%d/note", pid); |
1130 | new->notefd = open(buf, OWRITE); |
1131 | snprint(buf, sizeof(buf), "/proc/%d/args", pid); |
1132 | new->argsfd = open(buf, ORDWR); |
1133 | |
1134 | if(args.flags & (CLONE_THREAD | CLONE_PARENT)){ |
1135 | new->ppid = current->ppid; |
1136 | } else { |
1137 | new->ppid = current->pid; |
1138 | } |
1139 | |
1140 | if(args.flags & CLONE_THREAD) |
1141 | new->pid = current->pid; |
1142 | |
1143 | new->cleartidptr = nil; |
1144 | if(args.flags & CLONE_CHILD_CLEARTID) |
1145 | new->cleartidptr = args.childtidptr; |
1146 | |
1147 | new->pgid = current->pgid; |
1148 | new->psid = current->psid; |
1149 | new->uid = current->uid; |
1150 | new->gid = current->gid; |
1151 | |
1152 | clonetrace(new, !(args.flags & CLONE_THREAD)); |
1153 | clonesignal(new, !(args.flags & CLONE_SIGHAND), !(args.flags & CLONE_THREAD)); |
1154 | clonemem(new, !(args.flags & CLONE_VM)); |
1155 | clonefile(new, !(args.flags & CLONE_FILES)); |
1156 | clonetls(new); |
1157 | qunlock(&proctab); |
1158 | |
1159 | while(rendezvous(new, 0) == (void*)~0) |
1160 | ; |
1161 | |
1162 | qunlock(current); |
1163 | |
1164 | return tid; |
1165 | } |
1166 | |
1167 | /* child */ |
1168 | current = new; |
1169 | profme(); |
1170 | |
1171 | /* wait for parent to copy our resources */ |
1172 | while(rendezvous(new, 0) == (void*)~0) |
1173 | ; |
1174 | |
1175 | trace("kcloneproc(): hello world"); |
1176 | |
1177 | if(args.flags & CLONE_SETTLS) |
1178 | sys_set_thread_area(&tls); |
1179 | |
1180 | if(args.flags & CLONE_CHILD_SETTID) |
1181 | if(okaddr(args.childtidptr, sizeof(*args.childtidptr), 1)) |
1182 | *args.childtidptr = tid; |
1183 | |
1184 | if(args.newstack != nil) |
1185 | current->ureg->sp = (ulong)args.newstack; |
1186 | current->sysret(0); |
1187 | retuser(); |
1188 | |
1189 | return -1; |
1190 | } |
1191 | |
1192 | #pragma profile on |
1193 | |
1194 | int sys_linux_clone(int flags, void *newstack, int *parenttidptr, int *tlsdescr, void *childtidptr) |
1195 | { |
1196 | struct kcloneprocargs a; |
1197 | |
1198 | trace("sys_linux_clone(%x, %p, %p, %p, %p)", flags, newstack, parenttidptr, childtidptr, tlsdescr); |
1199 | |
1200 | a.flags = flags; |
1201 | a.newstack = newstack; |
1202 | a.parenttidptr = parenttidptr; |
1203 | a.childtidptr = childtidptr; |
1204 | a.tlsdescr = tlsdescr; |
1205 | |
1206 | return onstack(kstack, kcloneproc, &a); |
1207 | } |
1208 | |
1209 | int sys_fork(void) |
1210 | { |
1211 | trace("sys_fork()"); |
1212 | |
1213 | return sys_linux_clone(SIGCHLD, nil, nil, nil, nil); |
1214 | } |
1215 | |
1216 | int sys_vfork(void) |
1217 | { |
1218 | trace("sys_vfork()"); |
1219 | |
1220 | return sys_fork(); |
1221 | } |
1222 | |
1223 | int sys_getpid(void) |
1224 | { |
1225 | trace("sys_getpid()"); |
1226 | |
1227 | return current->pid; |
1228 | } |
1229 | |
1230 | int sys_getppid(void) |
1231 | { |
1232 | trace("sys_getppid()"); |
1233 | |
1234 | return current->ppid; |
1235 | } |
1236 | |
1237 | int sys_gettid(void) |
1238 | { |
1239 | trace("sys_gettid()"); |
1240 | |
1241 | return current->tid; |
1242 | } |
1243 | |
1244 | int sys_setpgid(int pid, int pgid) |
1245 | { |
1246 | int i, n; |
1247 | |
1248 | trace("sys_setpgid(%d, %d)", pid, pgid); |
1249 | |
1250 | if(pgid == 0) |
1251 | pgid = current->pgid; |
1252 | if(pid == 0) |
1253 | pid = current->pid; |
1254 | |
1255 | n = 0; |
1256 | qlock(&proctab); |
1257 | for(i=0; i<MAXPROC; i++){ |
1258 | Uproc *p; |
1259 | |
1260 | if((p = getprocn(i)) == nil) |
1261 | continue; |
1262 | if(p->pid != pid) |
1263 | continue; |
1264 | |
1265 | p->pgid = pgid; |
1266 | n++; |
1267 | } |
1268 | qunlock(&proctab); |
1269 | |
1270 | return n ? 0 : -ESRCH; |
1271 | } |
1272 | |
1273 | int sys_getpgid(int pid) |
1274 | { |
1275 | int i; |
1276 | int pgid; |
1277 | |
1278 | trace("sys_getpgid(%d)", pid); |
1279 | |
1280 | pgid = -ESRCH; |
1281 | if(pid == 0) |
1282 | return current->pgid; |
1283 | qlock(&proctab); |
1284 | for(i=0; i<MAXPROC; i++){ |
1285 | Uproc *p; |
1286 | |
1287 | if((p = getprocn(i)) == nil) |
1288 | continue; |
1289 | if(p->pid != pid) |
1290 | continue; |
1291 | |
1292 | pgid = p->pgid; |
1293 | break; |
1294 | } |
1295 | qunlock(&proctab); |
1296 | |
1297 | return pgid; |
1298 | } |
1299 | |
1300 | int sys_getpgrp(void) |
1301 | { |
1302 | trace("sys_getpgrp()"); |
1303 | |
1304 | return sys_getpgid(0); |
1305 | } |
1306 | |
1307 | int sys_getuid(void) |
1308 | { |
1309 | trace("sys_getuid()"); |
1310 | |
1311 | return current->uid; |
1312 | } |
1313 | |
1314 | int sys_getgid(void) |
1315 | { |
1316 | trace("sys_getgid()"); |
1317 | |
1318 | return current->gid; |
1319 | } |
1320 | |
1321 | int sys_setuid(int uid) |
1322 | { |
1323 | trace("sys_setuid(%d)", uid); |
1324 | |
1325 | current->uid = uid; |
1326 | return 0; |
1327 | } |
1328 | |
1329 | int sys_setgid(int gid) |
1330 | { |
1331 | trace("sys_setgid(%d)", gid); |
1332 | |
1333 | current->gid = gid; |
1334 | return 0; |
1335 | } |
1336 | |
1337 | int sys_setresuid(int ruid, int euid, int suid) |
1338 | { |
1339 | trace("sys_setresuid(%d, %d, %d)", ruid, euid, suid); |
1340 | |
1341 | return 0; |
1342 | } |
1343 | |
1344 | int sys_setresgid(int rgid, int egid, int sgid) |
1345 | { |
1346 | trace("sys_setresgid(%d, %d, %d)", rgid, egid, sgid); |
1347 | |
1348 | return 0; |
1349 | } |
1350 | int sys_setreuid(int ruid, int euid) |
1351 | { |
1352 | trace("sys_setreuid(%d, %d)", ruid, euid); |
1353 | |
1354 | return 0; |
1355 | } |
1356 | |
1357 | int sys_setregid(int rgid, int egid) |
1358 | { |
1359 | trace("sys_setregid(%d, %d)", rgid, egid); |
1360 | |
1361 | return 0; |
1362 | } |
1363 | |
1364 | int sys_getresuid(int *ruid, int *euid, int *suid) |
1365 | { |
1366 | trace("sys_getresuid(%p, %p, %p)", ruid, euid, suid); |
1367 | |
1368 | if(ruid == nil) |
1369 | return -EINVAL; |
1370 | if(euid == nil) |
1371 | return -EINVAL; |
1372 | if(suid == nil) |
1373 | return -EINVAL; |
1374 | |
1375 | *ruid = current->uid; |
1376 | *euid = current->uid; |
1377 | *suid = current->uid; |
1378 | |
1379 | return 0; |
1380 | } |
1381 | |
1382 | int sys_getresgid(int *rgid, int *egid, int *sgid) |
1383 | { |
1384 | trace("sys_getresgid(%p, %p, %p)", rgid, egid, sgid); |
1385 | |
1386 | if(rgid == nil) |
1387 | return -EINVAL; |
1388 | if(egid == nil) |
1389 | return -EINVAL; |
1390 | if(sgid == nil) |
1391 | return -EINVAL; |
1392 | |
1393 | *rgid = current->gid; |
1394 | *egid = current->gid; |
1395 | *sgid = current->gid; |
1396 | |
1397 | return 0; |
1398 | } |
1399 | |
1400 | int sys_setsid(void) |
1401 | { |
1402 | int i; |
1403 | |
1404 | trace("sys_setsid()"); |
1405 | |
1406 | if(current->pid == current->pgid) |
1407 | return -EPERM; |
1408 | |
1409 | qlock(&proctab); |
1410 | for(i=0; i<MAXPROC; i++){ |
1411 | Uproc *p; |
1412 | |
1413 | if((p = getprocn(i)) == nil) |
1414 | continue; |
1415 | if(p->pid != current->pid) |
1416 | continue; |
1417 | p->pgid = current->pid; |
1418 | p->psid = current->pid; |
1419 | } |
1420 | qunlock(&proctab); |
1421 | |
1422 | settty(nil); |
1423 | |
1424 | return current->pgid; |
1425 | } |
1426 | |
1427 | int sys_getsid(int pid) |
1428 | { |
1429 | int i, pgid; |
1430 | |
1431 | trace("sys_getsid(%d)", pid); |
1432 | |
1433 | pgid = -ESRCH; |
1434 | if(pid == 0) |
1435 | pid = current->pid; |
1436 | qlock(&proctab); |
1437 | for(i=0; i<MAXPROC; i++){ |
1438 | Uproc *p; |
1439 | |
1440 | if((p = getprocn(i)) == nil) |
1441 | continue; |
1442 | if(p->pid != pid) |
1443 | continue; |
1444 | if(p->pid != p->psid) |
1445 | continue; |
1446 | pgid = p->pgid; |
1447 | break; |
1448 | } |
1449 | qunlock(&proctab); |
1450 | |
1451 | return pgid; |
1452 | } |
1453 | |
1454 | int sys_getgroups(int size, int *groups) |
1455 | { |
1456 | trace("sys_getgroups(%d, %p)", size, groups); |
1457 | if(size < 0) |
1458 | return -EINVAL; |
1459 | return 0; |
1460 | } |
1461 | |
1462 | int sys_setgroups(int size, int *groups) |
1463 | { |
1464 | trace("sys_setgroups(%d, %p)", size, groups); |
1465 | return 0; |
1466 | } |
1467 | |
1468 | struct linux_utsname |
1469 | { |
1470 | char sysname[65]; |
1471 | char nodename[65]; |
1472 | char release[65]; |
1473 | char version[65]; |
1474 | char machine[65]; |
1475 | char domainname[65]; |
1476 | }; |
1477 | |
1478 | int sys_uname(void *a) |
1479 | { |
1480 | struct linux_utsname *p = a; |
1481 | |
1482 | trace("sys_uname(%p)", a); |
1483 | |
1484 | strncpy(p->sysname, "Linux", 65); |
1485 | strncpy(p->nodename, sysname(), 65); |
1486 | strncpy(p->release, "3.2.1", 65); |
1487 | strncpy(p->version, "linuxemu", 65); |
1488 | strncpy(p->machine, "i386", 65); |
1489 | strncpy(p->domainname, sysname(), 65); |
1490 | |
1491 | return 0; |
1492 | } |
1493 | |
1494 | int sys_personality(ulong p) |
1495 | { |
1496 | trace("sys_personality(%lux)", p); |
1497 | |
1498 | if(p != 0 && p != 0xffffffff) |
1499 | return -EINVAL; |
1500 | return 0; |
1501 | } |
1502 | |
1503 | int sys_tkill(int tid, int sig) |
1504 | { |
1505 | int err; |
1506 | |
1507 | trace("sys_tkill(%d, %S)", tid, sig); |
1508 | |
1509 | err = -EINVAL; |
1510 | if(tid > 0){ |
1511 | Uproc *p; |
1512 | |
1513 | err = -ESRCH; |
1514 | qlock(&proctab); |
1515 | if(p = getproc(tid)){ |
1516 | Usiginfo si; |
1517 | |
1518 | memset(&si, 0, sizeof(si)); |
1519 | si.signo = sig; |
1520 | si.code = SI_TKILL; |
1521 | si.kill.pid = current->tid; |
1522 | si.kill.uid = current->uid; |
1523 | err = killproc(p, &si, 0); |
1524 | } |
1525 | qunlock(&proctab); |
1526 | } |
1527 | return err; |
1528 | } |
1529 | |
1530 | int sys_tgkill(int pid, int tid, int sig) |
1531 | { |
1532 | int err; |
1533 | |
1534 | trace("sys_tgkill(%d, %d, %S)", pid, tid, sig); |
1535 | |
1536 | err = -EINVAL; |
1537 | if(tid > 0){ |
1538 | Uproc *p; |
1539 | |
1540 | err = -ESRCH; |
1541 | qlock(&proctab); |
1542 | if((p = getproc(tid)) && (p->pid == pid)){ |
1543 | Usiginfo si; |
1544 | |
1545 | memset(&si, 0, sizeof(si)); |
1546 | si.signo = sig; |
1547 | si.code = SI_TKILL; |
1548 | si.kill.pid = current->tid; |
1549 | si.kill.uid = current->uid; |
1550 | err = killproc(p, &si, 0); |
1551 | } |
1552 | qunlock(&proctab); |
1553 | } |
1554 | return err; |
1555 | } |
1556 | |
1557 | int sys_rt_sigqueueinfo(int pid, int sig, void *info) |
1558 | { |
1559 | int err; |
1560 | Uproc *p; |
1561 | Usiginfo si; |
1562 | |
1563 | trace("sys_rt_sigqueueinfo(%d, %S, %p)", pid, sig, info); |
1564 | |
1565 | err = -ESRCH; |
1566 | qlock(&proctab); |
1567 | if(p = getproc(pid)){ |
1568 | memset(&si, 0, sizeof(si)); |
1569 | linux2siginfo(info, &si); |
1570 | si.signo = sig; |
1571 | si.code = SI_QUEUE; |
1572 | err = killproc(p, &si, 1); |
1573 | } |
1574 | qunlock(&proctab); |
1575 | return err; |
1576 | } |
1577 | |
1578 | enum { |
1579 | PIDMAPBITS1 = 8*sizeof(ulong), |
1580 | }; |
1581 | |
1582 | int sys_kill(int pid, int sig) |
1583 | { |
1584 | int i, j, n; |
1585 | Uproc *p; |
1586 | Usiginfo si; |
1587 | ulong pidmap[(MAXPROC + PIDMAPBITS1-1) / PIDMAPBITS1]; |
1588 | ulong m; |
1589 | |
1590 | trace("sys_kill(%d, %S)", pid, sig); |
1591 | |
1592 | n = 0; |
1593 | memset(pidmap, 0, sizeof(pidmap)); |
1594 | qlock(&proctab); |
1595 | for(i=0; i<MAXPROC; i++){ |
1596 | if((p = getprocn(i)) == nil) |
1597 | continue; |
1598 | if(p->wstate & WEXITED) |
1599 | continue; |
1600 | if(p->kpid <= 0) |
1601 | continue; |
1602 | |
1603 | if(pid == 0){ |
1604 | if(p->pgid != current->pgid) |
1605 | continue; |
1606 | } else if(pid == -1){ |
1607 | if(p->pid <= 1) |
1608 | continue; |
1609 | if(p->tid == current->tid) |
1610 | continue; |
1611 | } else if(pid < -1) { |
1612 | if(p->pgid != -pid) |
1613 | continue; |
1614 | } else { |
1615 | if(p->pid != pid) |
1616 | continue; |
1617 | } |
1618 | |
1619 | /* make sure we send only one signal per pid */ |
1620 | j = pidhash(p->pid); |
1621 | m = 1 << (j % PIDMAPBITS1); |
1622 | j /= PIDMAPBITS1; |
1623 | if(pidmap[j] & m) |
1624 | continue; |
1625 | pidmap[j] |= m; |
1626 | |
1627 | if(sig > 0){ |
1628 | memset(&si, 0, sizeof(si)); |
1629 | si.signo = sig; |
1630 | si.code = SI_USER; |
1631 | si.kill.pid = current->tid; |
1632 | si.kill.uid = current->uid; |
1633 | killproc(p, &si, 1); |
1634 | } |
1635 | n++; |
1636 | } |
1637 | qunlock(&proctab); |
1638 | if(n == 0) |
1639 | return -ESRCH; |
1640 | return 0; |
1641 | } |
1642 | |
1643 | int sys_set_tid_address(int *tidptr) |
1644 | { |
1645 | trace("sys_set_tid_address(%p)", tidptr); |
1646 | |
1647 | current->cleartidptr = tidptr; |
1648 | return current->pid; |
1649 | } |
1650 | |
1651 | struct linux_sched_param |
1652 | { |
1653 | int sched_priority; |
1654 | }; |
1655 | |
1656 | int sys_sched_setscheduler(int pid, int policy, void *param) |
1657 | { |
1658 | trace("sys_sched_setscheduler(%d, %d, %p)", pid, policy, param); |
1659 | |
1660 | if(getproc(pid) == nil) |
1661 | return -ESRCH; |
1662 | return 0; |
1663 | } |
1664 | |
1665 | int sys_sched_getscheduler(int pid) |
1666 | { |
1667 | trace("sys_sched_getscheduler(%d)", pid); |
1668 | |
1669 | if(getproc(pid) == nil) |
1670 | return -ESRCH; |
1671 | return 0; |
1672 | } |
1673 | |
1674 | int sys_sched_setparam(int pid, void *param) |
1675 | { |
1676 | trace("sys_sched_setparam(%d, %p)", pid, param); |
1677 | |
1678 | if(getproc(pid) == nil) |
1679 | return -ESRCH; |
1680 | return 0; |
1681 | } |
1682 | |
1683 | int sys_sched_getparam(int pid, void *param) |
1684 | { |
1685 | struct linux_sched_param *p = param; |
1686 | |
1687 | trace("sys_sched_getparam(%d, %p)", pid, param); |
1688 | |
1689 | if(getproc(pid) == nil) |
1690 | return -ESRCH; |
1691 | if(p == nil) |
1692 | return -EINVAL; |
1693 | p->sched_priority = 0; |
1694 | |
1695 | return 0; |
1696 | } |
1697 | |
1698 | int sys_sched_yield(void) |
1699 | { |
1700 | trace("sys_sched_yield()"); |
1701 | |
1702 | sleep(0); |
1703 | return 0; |
1704 | } |
1705 | |
1706 | enum { |
1707 | RLIMIT_CPU, |
1708 | RLIMIT_FSIZE, |
1709 | RLIMIT_DATA, |
1710 | RLIMIT_STACK, |
1711 | RLIMIT_CORE, |
1712 | RLIMIT_RSS, |
1713 | RLIMIT_NPROC, |
1714 | RLIMIT_NOFILE, |
1715 | RLIMIT_MEMLOCK, |
1716 | RLIMIT_AS, |
1717 | RLIMIT_LOCKS, |
1718 | RLIMIT_SIGPENDING, |
1719 | RLIMIT_MSGQUEUE, |
1720 | |
1721 | RLIM_NLIMITS, |
1722 | |
1723 | RLIM_INFINITY = ~0UL, |
1724 | }; |
1725 | |
1726 | struct linux_rlimit |
1727 | { |
1728 | ulong rlim_cur; |
1729 | ulong rlim_max; |
1730 | }; |
1731 | |
1732 | int sys_getrlimit(long resource, void *rlim) |
1733 | { |
1734 | struct linux_rlimit *r = rlim; |
1735 | |
1736 | trace("sys_getrlimit(%ld, %p)", resource, rlim); |
1737 | |
1738 | if(resource >= RLIM_NLIMITS) |
1739 | return -EINVAL; |
1740 | if(rlim == nil) |
1741 | return -EFAULT; |
1742 | |
1743 | r->rlim_cur = RLIM_INFINITY; |
1744 | r->rlim_max = RLIM_INFINITY; |
1745 | |
1746 | switch(resource){ |
1747 | case RLIMIT_STACK: |
1748 | r->rlim_cur = USTACK; |
1749 | r->rlim_max = USTACK; |
1750 | break; |
1751 | case RLIMIT_CORE: |
1752 | r->rlim_cur = 0; |
1753 | break; |
1754 | case RLIMIT_NPROC: |
1755 | r->rlim_cur = MAXPROC; |
1756 | r->rlim_max = MAXPROC; |
1757 | break; |
1758 | case RLIMIT_NOFILE: |
1759 | r->rlim_cur = MAXFD; |
1760 | r->rlim_max = MAXFD; |
1761 | break; |
1762 | } |
1763 | return 0; |
1764 | } |
1765 | |
1766 | int sys_setrlimit(long resource, void *rlim) |
1767 | { |
1768 | trace("sys_setrlimit(%ld, %p)", resource, rlim); |
1769 | |
1770 | if(resource >= RLIM_NLIMITS) |
1771 | return -EINVAL; |
1772 | if(rlim == nil) |
1773 | return -EFAULT; |
1774 | |
1775 | return -EPERM; |
1776 | } |
1777 | |