add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / signal.c
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 typedef struct Signal Signal;
9 typedef struct Action Action;
10 typedef struct Queue Queue;
11 typedef struct Timers Timers;
12 typedef struct Handlers Handlers;
13 typedef struct Private Private;
14
15 struct Signal
16 {
17 Usiginfo;
18 Signal *next;
19 };
20
21 struct Action
22 {
23 void *handler;
24 int flags;
25 uvlong block;
26 };
27
28 struct Queue
29 {
30 Ref;
31 QLock;
32
33 Signal *head;
34 Signal **tailp;
35 Signal *free;
36 Signal a[64];
37
38 Ufile *tty;
39 };
40
41 struct Timers
42 {
43 Ref;
44 struct {
45 vlong interval;
46 vlong expire;
47 } itimer[2];
48 };
49
50 struct Handlers
51 {
52 Ref;
53 QLock;
54 Action a[SIGMAX-1];
55 };
56
57 struct Private
58 {
59 Handlers *h;
60 Queue *q;
61 Timers *t;
62
63 struct {
64 ulong sp;
65 ulong size;
66 } altstack;
67
68 uvlong block;
69
70 Urestart *freerestart;
71 };
72
73 enum
74 {
75 SIG_ERR = -1,
76 SIG_DFL = 0,
77 SIG_IGN = 1,
78 SIG_HOLD = 2,
79 };
80
81 enum
82 {
83 SA_NOCLDSTOP = 1,
84 SA_NOCLDWAIT = 2,
85 SA_SIGINFO = 4,
86 SA_ONSTACK = 0x08000000,
87 SA_RESTART = 0x10000000,
88 SA_NODEFER = 0x40000000,
89 SA_RESETHAND = 0x80000000,
90 };
91
92 enum
93 {
94 SS_ONSTACK = 1,
95 SS_DISABLE = 2,
96 };
97
98 #define MASK(sig) (1LL << ((sig)-1))
99
100 static void
101 nextsignal(uvlong rblock, int wait);
102
103 static int
104 getsignal(Private *p, Usiginfo *pinfo, int wait);
105
106 static void
107 initrestart(Uproc *proc)
108 {
109 Urestart *r;
110
111 r = &proc->restart0;
112 r->syscall = nil;
113 r->link = nil;
114 proc->restart = r;
115 }
116
117 static void
118 poprestart(Private *p)
119 {
120 Urestart *r;
121
122 for(;;){
123 r = current->restart;
124 if(r->link==nil || r->syscall)
125 break;
126 current->restart = r->link;
127
128 r->link = p->freerestart;
129 p->freerestart = r;
130 }
131 if(r->syscall)
132 current->syscall = r->syscall;
133 }
134
135 static Queue*
136 mkqueue(void)
137 {
138 Queue *q;
139 int i;
140
141 q = kmallocz(sizeof(Queue), 1);
142 q->ref = 1;
143 q->head = nil;
144 q->tailp = &q->head;
145 for(i=0; i<nelem(q->a); i++)
146 q->a[i].next = (i+1 == nelem(q->a)) ? nil : &q->a[i+1];
147 q->free = q->a;
148
149 return q;
150 }
151
152 static Handlers*
153 mkhandlers(void)
154 {
155 Handlers *h;
156 int i;
157
158 h = kmallocz(sizeof(Handlers), 1);
159 h->ref = 1;
160 for(i=1; i<SIGMAX; i++)
161 h->a[i-1].handler = (void*)SIG_DFL;
162 return h;
163 }
164
165 static Timers*
166 mktimers(void)
167 {
168 Timers *t;
169
170 t = kmallocz(sizeof(Timers), 1);
171 t->ref = 1;
172 return t;
173 }
174
175 /* bits.s */
176 extern int get_ds(void);
177 extern int get_cs(void);
178 static ulong user_cs, user_ds;
179
180 void initsignal(void)
181 {
182 Private *p;
183
184 if(user_ds==0 && user_cs==0){
185 user_ds = get_ds();
186 user_cs = get_cs();
187 }
188
189 p = kmallocz(sizeof(*p), 1);
190 p->block = 0;
191
192 p->q = mkqueue();
193 p->h = mkhandlers();
194 p->t = mktimers();
195
196 current->signal = p;
197 initrestart(current);
198 }
199
200 void exitsignal(void)
201 {
202 Private *p;
203 Queue *q;
204 Timers *t;
205 Signal **i;
206 Handlers *h;
207 Urestart *r;
208
209 if((p = current->signal) == nil)
210 return;
211 current->signal = nil;
212 q = p->q;
213 qlock(q);
214 again:
215 for(i=&q->head; *i; i=&((*i)->next)){
216 Signal *r;
217 r = *i;
218 if(!r->group && (r->topid == current->tid)){
219 if((*i = r->next) == nil)
220 q->tailp = i;
221 r->next = q->free;
222 q->free = r;
223 goto again;
224 }
225 }
226 qunlock(q);
227 if(!decref(q)){
228 putfile(q->tty);
229 q->tty = nil;
230 free(q);
231 }
232 h = p->h;
233 if(!decref(h))
234 free(h);
235 t = p->t;
236 if(!decref(t))
237 free(t);
238 while(r = current->restart){
239 if(r->link == nil)
240 break;
241 current->restart = r->link;
242 r->link = p->freerestart;
243 p->freerestart = r;
244 }
245 current->restart = nil;
246 while(r = p->freerestart){
247 p->freerestart = r->link;
248 free(r);
249 }
250 free(p);
251 }
252
253 void clonesignal(Uproc *new, int copyhand, int newproc)
254 {
255 Private *p, *n;
256
257 if((p = current->signal) == nil)
258 return;
259
260 n = kmallocz(sizeof(*n), 1);
261 if(copyhand){
262 n->h = mkhandlers();
263
264 qlock(p->h);
265 memmove(n->h->a, p->h->a, sizeof(n->h->a));
266 qunlock(p->h);
267 } else {
268 incref(p->h);
269 n->h = p->h;
270 }
271
272 qlock(p->q);
273 if(newproc){
274 n->q = mkqueue();
275 n->q->tty = getfile(p->q->tty);
276 n->t = mktimers();
277 n->altstack = p->altstack;
278 } else {
279 incref(p->q);
280 n->q = p->q;
281 incref(p->t);
282 n->t = p->t;
283 }
284 qunlock(p->q);
285
286 n->block = p->block;
287 new->signal = n;
288
289 initrestart(new);
290 }
291
292 void
293 settty(Ufile *tty)
294 {
295 Private *p;
296 Ufile *old;
297
298 if((p = current->signal) == nil)
299 return;
300 tty = getfile(tty);
301 qlock(p->q);
302 old = p->q->tty;
303 p->q->tty = tty;
304 qunlock(p->q);
305 putfile(old);
306 }
307
308 Ufile*
309 gettty(void)
310 {
311 Private *p;
312 Ufile *tty;
313
314 if((p = current->signal) == nil)
315 return nil;
316 qlock(p->q);
317 tty = getfile(p->q->tty);
318 qunlock(p->q);
319 return tty;
320 }
321
322 int ignoressignal(Uproc *proc, int sig)
323 {
324 Private *p;
325 int a, f;
326
327 if((p = proc->signal) == nil)
328 return 1;
329 qlock(p->h);
330 a = (int)p->h->a[sig-1].handler;
331 f = p->h->a[sig-1].flags;
332 qunlock(p->h);
333 switch(sig){
334 case SIGKILL:
335 case SIGSTOP:
336 return 0;
337 case SIGCHLD:
338 if(f & SA_NOCLDWAIT)
339 return 1;
340 break;
341 case SIGWINCH:
342 case SIGURG:
343 if(a == SIG_DFL)
344 return 1;
345 }
346 return (a == SIG_IGN);
347 }
348
349 int wantssignal(Uproc *proc, int sig)
350 {
351 Private *p;
352
353 p = proc->signal;
354 if(p == nil || p->block & MASK(sig))
355 return 0;
356 return !ignoressignal(proc, sig);
357 }
358
359 int sendsignal(Uproc *proc, Usiginfo *info, int group)
360 {
361 Private *p;
362 Signal *s;
363
364 trace("sendsignal(%S) to %d from %d",
365 info->signo, proc->tid, (current != nil) ? current->tid : 0);
366
367 if(ignoressignal(proc, info->signo)){
368 trace("sendsignal(): ignored signal %S", info->signo);
369 return 0;
370 }
371
372 p = proc->signal;
373 qlock(p->q);
374 if(info->signo < SIGRT1){
375 for(s=p->q->head; s; s=s->next){
376 if(!s->group && (s->topid != proc->tid))
377 continue;
378 if(s->signo == info->signo){
379 qunlock(p->q);
380 trace("sendsignal(): droping follow up signal %S", info->signo);
381 return 0;
382 }
383 }
384 }
385 if((s = p->q->free) == nil){
386 qunlock(p->q);
387 trace("sendsignal(): out of signal buffers");
388 return -EAGAIN;
389 }
390 p->q->free = s->next;
391 s->next = nil;
392 memmove(s, info, sizeof(*info));
393 s->group = group;
394 s->topid = group ? proc->pid : proc->tid;
395 *p->q->tailp = s;
396 p->q->tailp = &s->next;
397 qunlock(p->q);
398 return 1;
399 }
400
401 int
402 signalspending(Uproc *proc)
403 {
404 Private *p;
405 Signal *s;
406 int ret;
407
408 p = proc->signal;
409 if(p == nil || p->q->head == nil)
410 return 0;
411
412 ret = 0;
413 qlock(p->q);
414 for(s=p->q->head; s; s=s->next){
415 if(!s->group && (s->topid != current->tid))
416 continue;
417 if(MASK(s->signo) & p->block)
418 continue;
419 ret = 1;
420 break;
421 }
422 qunlock(p->q);
423
424 return ret;
425 }
426
427 static int
428 getsignal(Private *p, Usiginfo *pinfo, int wait)
429 {
430 Signal *r;
431 Signal **i;
432 int sig;
433
434 if(!wait && p->q->head == nil)
435 return 0;
436
437 sig = 0;
438 qlock(p->q);
439 for(;;){
440 for(i=&p->q->head; *i; i=&((*i)->next)){
441 r = *i;
442
443 if(!r->group && (r->topid != current->tid))
444 continue;
445
446 if(p->block & MASK(r->signo)){
447 if(sig == 0)
448 sig = -r->signo;
449 continue;
450 }
451 sig = r->signo;
452
453 /* dequeue nonblocked signal */
454 memmove(pinfo, r, sizeof(*pinfo));
455 if((*i = r->next) == nil)
456 p->q->tailp = i;
457 r->next = p->q->free;
458 p->q->free = r;
459 break;
460 }
461 if(wait && sig <= 0){
462 if(sleepproc(p->q, 0) == 0)
463 continue;
464 }
465 break;
466 }
467 qunlock(p->q);
468
469 return sig;
470 }
471
472 static uvlong
473 sigset2uvlong(uchar *set, int setsize)
474 {
475 uvlong r;
476 int i;
477
478 r = 0;
479 if(setsize > sizeof(uvlong))
480 setsize = sizeof(uvlong);
481 for(i=0; i<setsize; i++)
482 r |= (uvlong)set[i] << (i * 8);
483 return r;
484 }
485
486 static void
487 uvlong2sigset(uchar *set, int setsize, uvlong mask)
488 {
489 int i;
490
491 for(i=0; i<setsize; i++){
492 if(i < sizeof(uvlong)){
493 set[i] = ((mask >> (i*8)) & 0xff);
494 } else {
495 set[i] = 0;
496 }
497 }
498 }
499
500 struct linux_siginfo {
501 int signo;
502 int errno;
503 int code;
504
505 union {
506 int _pad[29];
507
508 /* kill() */
509 struct {
510 int pid; /* sender's pid */
511 int uid; /* sender's uid */
512 } kill;
513
514 /* POSIX.1b timers */
515 struct {
516 int tid; /* timer id */
517 int overrun; /* overrun count */
518 int val; /* same as below */
519 } timer;
520
521 /* POSIX.1b signals */
522 struct {
523 int pid; /* sender's pid */
524 int uid; /* sender's uid */
525 int val;
526 } rt;
527
528 /* SIGCHLD */
529 struct {
530 int pid; /* which child */
531 int uid; /* sender's uid */
532 int status; /* exit code */
533 long utime;
534 long stime;
535 } chld;
536
537 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
538 struct {
539 void *addr; /* faulting insn/memory ref. */
540 int trapno; /* TRAP # which caused the signal */
541 } fault;
542
543 /* SIGPOLL */
544 struct {
545 long band; /* POLL_IN, POLL_OUT, POLL_MSG */
546 int fd;
547 } poll;
548 };
549 };
550
551 void
552 siginfo2linux(Usiginfo *info, void *p)
553 {
554 struct linux_siginfo *li = p;
555 int sig;
556
557 sig = info->signo;
558
559 li->signo = sig;
560 li->errno = info->errno;
561 li->code = info->code;
562
563 switch(sig){
564 case SIGALRM:
565 li->timer.tid = info->timer.tid;
566 li->timer.overrun = info->timer.overrun;
567 li->timer.val = info->timer.val;
568 break;
569 case SIGCHLD:
570 li->chld.pid = info->chld.pid;
571 li->chld.uid = info->chld.uid;
572 li->chld.status = info->chld.status;
573 li->chld.utime = info->chld.utime;
574 li->chld.stime = info->chld.stime;
575 break;
576 case SIGILL:
577 case SIGBUS:
578 case SIGFPE:
579 case SIGSEGV:
580 li->fault.addr = info->fault.addr;
581 li->fault.trapno = info->fault.trapno;
582 break;
583 case SIGPOLL:
584 li->poll.fd = info->poll.fd;
585 li->poll.band = info->poll.band;
586 break;
587 case SIGRT1:
588 case SIGRT2:
589 case SIGRT3:
590 case SIGRT4:
591 case SIGRT5:
592 case SIGRT6:
593 case SIGRT7:
594 case SIGRT8:
595 li->rt.pid = info->rt.pid;
596 li->rt.uid = info->rt.uid;
597 li->rt.val = info->rt.val;
598 break;
599 default:
600 li->kill.pid = info->kill.pid;
601 li->kill.uid = info->kill.uid;
602 }
603 }
604
605 void
606 linux2siginfo(void *p, Usiginfo *info)
607 {
608 struct linux_siginfo *li = p;
609 int sig;
610
611 sig = li->signo;
612
613 info->signo = sig;
614 info->errno = li->errno;
615 info->code = li->code;
616
617 switch(sig){
618 case SIGALRM:
619 info->timer.tid = li->timer.tid;
620 info->timer.overrun = li->timer.overrun;
621 info->timer.val = li->timer.val;
622 break;
623 case SIGCHLD:
624 info->chld.pid = li->chld.pid;
625 info->chld.uid = li->chld.uid;
626 info->chld.status = li->chld.status;
627 info->chld.utime = li->chld.utime;
628 info->chld.stime = li->chld.stime;
629 break;
630 case SIGILL:
631 case SIGBUS:
632 case SIGFPE:
633 case SIGSEGV:
634 info->fault.addr = li->fault.addr;
635 info->fault.trapno = li->fault.trapno;
636 break;
637 case SIGPOLL:
638 info->poll.fd = li->poll.fd;
639 info->poll.band = li->poll.band;
640 break;
641 case SIGRT1:
642 case SIGRT2:
643 case SIGRT3:
644 case SIGRT4:
645 case SIGRT5:
646 case SIGRT6:
647 case SIGRT7:
648 case SIGRT8:
649 info->rt.pid = li->rt.pid;
650 info->rt.uid = li->rt.uid;
651 info->rt.val = li->rt.val;
652 break;
653 default:
654 info->kill.pid = li->kill.pid;
655 info->kill.uid = li->kill.uid;
656 }
657 }
658
659 struct linux_sigcontext {
660 ulong gs;
661 ulong fs;
662 ulong es;
663 ulong ds;
664 ulong di;
665 ulong si;
666 ulong bp;
667 ulong sp;
668 ulong bx;
669 ulong dx;
670 ulong cx;
671 ulong ax;
672 ulong trapno;
673 ulong err;
674 ulong ip;
675 ulong cs;
676 ulong flags;
677 ulong sp_at_signal;
678 ulong ss;
679 void* fpstate;
680 ulong oldmask;
681 ulong cr2;
682 };
683
684 static void
685 ureg2linuxsigcontext(Ureg *u, struct linux_sigcontext *sc)
686 {
687 sc->gs = u->gs;
688 sc->fs = u->fs;
689 sc->es = u->es;
690 sc->ds = u->ds;
691 sc->di = u->di;
692 sc->si = u->si;
693 sc->bp = u->bp;
694 sc->sp = u->sp;
695 sc->bx = u->bx;
696 sc->dx = u->dx;
697 sc->cx = u->cx;
698 sc->ax = u->ax;
699 sc->trapno = u->trap;
700 sc->err = u->ecode;
701 sc->ip = u->pc;
702 sc->cs = u->cs;
703 sc->flags = u->flags;
704 sc->sp_at_signal = u->sp;
705 sc->ss = u->ss;
706 sc->cr2 = 0;
707 }
708
709 struct linux_sigset {
710 ulong sig[2];
711 };
712
713 struct linux_signalstack {
714 ulong sp;
715 int flags;
716 ulong size;
717 };
718
719 struct linux_ucontext {
720 ulong flags;
721 struct linux_ucontext *link;
722 struct linux_signalstack stack;
723 struct linux_sigcontext context;
724 struct linux_sigset sigmask;
725 };
726
727 static void
728 linuxsigcontext2ureg(struct linux_sigcontext *sc, Ureg *u)
729 {
730 u->pc = sc->ip;
731 u->sp = sc->sp;
732 u->ax = sc->ax;
733 u->bx = sc->bx;
734 u->cx = sc->cx;
735 u->dx = sc->dx;
736 u->di = sc->di;
737 u->si = sc->si;
738 u->bp = sc->bp;
739
740 u->cs = sc->cs;
741 u->ss = sc->ss;
742 u->ds = sc->ds;
743 u->es = sc->es;
744 u->fs = sc->fs;
745 u->gs = sc->gs;
746 }
747
748 struct linux_sigframe {
749 void *ret;
750 int sig;
751
752 union {
753 struct linux_sigcontext sc;
754
755 struct {
756 struct linux_siginfo *pinfo;
757 struct linux_ucontext *puc;
758
759 struct linux_siginfo info;
760 struct linux_ucontext uc;
761 } rt;
762 };
763 };
764
765 #pragma profile off
766
767 static int
768 linuxstackflags(Private *p, ulong sp)
769 {
770 if(p->altstack.size == 0 || p->altstack.sp == 0)
771 return SS_DISABLE;
772 if(sp - p->altstack.sp < p->altstack.size)
773 return SS_ONSTACK;
774 return 0;
775 }
776
777 static void
778 linuxsignal(Private *p, Action *a, Usiginfo *i, uvlong rblock)
779 {
780 struct linux_sigframe _frame;
781 struct linux_sigframe *f;
782 Ureg *u;
783 int stackflags;
784
785 u = current->ureg;
786
787 stackflags = linuxstackflags(p, u->sp);
788 if((a->flags & SA_ONSTACK) && (stackflags == 0)){
789 trace("linuxsignal: altstack %lux %lux", p->altstack.sp, p->altstack.size);
790 f = (struct linux_sigframe*)(p->altstack.sp + p->altstack.size);
791 f--;
792 } else {
793 f = &_frame;
794 }
795
796 trace("linuxsignal(): frame %p", f);
797 memset(f, 0, sizeof(*f));
798
799 f->sig = i->signo;
800
801 if(a->flags & SA_SIGINFO){
802 f->ret = linux_rtsigreturn;
803 siginfo2linux(i, &f->rt.info);
804 f->rt.pinfo = &f->rt.info;
805
806 f->rt.uc.stack.sp = p->altstack.sp;
807 f->rt.uc.stack.size = p->altstack.size;
808 f->rt.uc.stack.flags = stackflags;
809
810 ureg2linuxsigcontext(u, &f->rt.uc.context);
811 f->rt.uc.context.oldmask = rblock & 0xFFFFFFFF;
812 f->rt.uc.sigmask.sig[0] = rblock & 0xFFFFFFFF;
813 f->rt.uc.sigmask.sig[1] = (rblock >> 32) & 0xFFFFFFFF;
814 f->rt.puc = &f->rt.uc;
815 u->cx = (ulong)f->rt.puc;
816 u->dx = (ulong)f->rt.pinfo;
817 } else {
818 f->ret = linux_sigreturn;
819 ureg2linuxsigcontext(u, &f->sc);
820 f->sc.oldmask = rblock & 0xFFFFFFFF;
821 u->cx = 0;
822 u->dx = 0;
823 }
824
825 u->di = 0;
826 u->si = 0;
827 u->bp = 0;
828 u->bx = 0;
829
830 u->ax = (ulong)i->signo;
831
832 u->sp = (ulong)f;
833 u->pc = (ulong)a->handler;
834
835 u->cs = user_cs;
836 u->ss = user_ds;
837 u->ds = user_ds;
838 u->es = user_ds;
839
840 p->block |= a->block;
841
842 trace("linuxsignal(): retuser pc=%lux sp=%lux", u->pc, u->sp);
843 retuser();
844 }
845
846 int
847 sys_sigreturn(void)
848 {
849 struct linux_sigframe *f;
850 Private *p;
851 Ureg *u;
852
853 trace("sys_sigreturn()");
854
855 p = current->signal;
856 u = current->ureg;
857
858 f = (struct linux_sigframe*)(u->sp - 4);
859
860 trace("sys_sigreturn(): frame %p", f);
861
862 linuxsigcontext2ureg(&f->sc, u);
863 p->block &= ~0xFFFFFFFF;
864 p->block |= f->sc.oldmask;
865 nextsignal(p->block, 0);
866 poprestart(p);
867
868 trace("sys_sigreturn(): retuser pc=%lux sp=%lux", u->pc, u->sp);
869 retuser();
870
871 return -1;
872 }
873
874 int
875 sys_rt_sigreturn(void)
876 {
877 struct linux_sigframe *f;
878 Private *p;
879 Ureg *u;
880
881 trace("sys_rt_sigreturn()");
882
883 p = current->signal;
884 u = current->ureg;
885
886 f = (struct linux_sigframe*)(u->sp - 4);
887 trace("sys_rt_sigreturn(): frame %p", f);
888
889 linuxsigcontext2ureg(&f->rt.uc.context, u);
890 p->block = (uvlong)f->rt.uc.sigmask.sig[0] | (uvlong)f->rt.uc.sigmask.sig[1]<<32;
891 nextsignal(p->block, 0);
892 poprestart(p);
893
894 trace("sys_rt_sigreturn(): pc=%lux sp=%lux", u->pc, u->sp);
895 retuser();
896
897 return -1;
898 }
899
900 /*
901 * nextsignal transfers execution to the next pending
902 * signal or just returns. after the signal got executed,
903 * the block mask is restored to rblock. if heres no
904 * pending signal and wait is non zero the current
905 * process is suspended until here is a signal available.
906 */
907
908 static void
909 nextsignal(uvlong rblock, int wait)
910 {
911 Private *p;
912 int sig;
913 Usiginfo info;
914 Action a;
915 Urestart *r;
916
917 for(;;){
918 if((p = current->signal) == nil)
919 return;
920
921 if(current->wstate & WSTOPPED){
922 p->block = ~(MASK(SIGCONT) | MASK(SIGKILL));
923 sig = getsignal(p, &info, 1);
924 p->block = rblock;
925 if(sig <= 0)
926 return;
927 if(sig == SIGCONT){
928 contproc(current, sig, info.group);
929 continue;
930 }
931 } else {
932 if((sig = getsignal(p, &info, wait)) <= 0)
933 return;
934 if(sig == SIGCONT)
935 continue;
936 if(sig == SIGSTOP){
937 stopproc(current, sig, info.group);
938 continue;
939 }
940 }
941 break;
942 }
943
944 trace("nextsignal(): signal %S", sig);
945
946 qlock(p->h);
947 a = p->h->a[sig-1];
948 if(a.flags & SA_RESETHAND)
949 p->h->a[sig-1].handler = (void*)SIG_DFL;
950 if(a.flags & SA_NODEFER == 0)
951 a.block |= MASK(sig);
952 qunlock(p->h);
953
954 switch((int)a.handler){
955 case SIG_DFL:
956 switch(sig){
957 case SIGCHLD:
958 case SIGWINCH:
959 case SIGURG:
960 goto Ignored;
961 }
962 /* no break */
963 case SIG_ERR:
964 trace("nextsignal(): signal %S causes exit", sig);
965 exitproc(current, sig, 1);
966 Ignored:
967 case SIG_IGN:
968 case SIG_HOLD:
969 trace("nextsignal(): signal %S ignored", sig);
970 return;
971 }
972
973 if(current->restart->syscall){
974 if(a.flags & SA_RESTART){
975 if(r = p->freerestart)
976 p->freerestart = r->link;
977 if(r == nil)
978 r = kmalloc(sizeof(*r));
979 r->syscall = nil;
980 r->link = current->restart;
981 current->restart = r;
982 } else {
983 trace("nextsignal(): interrupting syscall %s", current->syscall);
984 current->sysret(-EINTR);
985 }
986 }
987
988 linuxsignal(p, &a, &info, rblock);
989 }
990
991 void handlesignals(void)
992 {
993 Private *p;
994
995 if(p = current->signal)
996 nextsignal(p->block, 0);
997 }
998
999 int
1000 sys_rt_sigsuspend(uchar *set, int setsize)
1001 {
1002 Private *p;
1003 uvlong b, rblock;
1004
1005 trace("sys_rt_sigsuspend(%p, %d)", set, setsize);
1006
1007 p = current->signal;
1008 b = sigset2uvlong(set, setsize);
1009 b &= ~(MASK(SIGKILL) | MASK(SIGSTOP));
1010
1011 rblock = p->block;
1012 p->block = b;
1013
1014 /*
1015 * if a signal got handled, it will pop out after the the
1016 * sigsuspend syscall with return value set to -EINTR
1017 */
1018 current->sysret(-EINTR);
1019
1020 for(;;)
1021 nextsignal(rblock, 1);
1022 }
1023
1024 #pragma profile on
1025
1026 struct linux_altstack
1027 {
1028 ulong sp;
1029 int flags;
1030 ulong size;
1031 };
1032
1033 int sys_sigaltstack(void *stk, void *ostk)
1034 {
1035 Private *p;
1036 struct linux_altstack *a = stk, *oa = ostk;
1037 int flags;
1038 ulong sp, size;
1039
1040 trace("sys_sigaltstack(%lux, %lux)", (ulong)stk, (ulong)ostk);
1041
1042 p = current->signal;
1043 sp = p->altstack.sp;
1044 size = p->altstack.size;
1045 flags = linuxstackflags(p, current->ureg->sp);
1046
1047 if(a){
1048 if(flags == SS_ONSTACK)
1049 return -EPERM;
1050
1051 if(a->flags == SS_DISABLE){
1052 p->altstack.sp = 0;
1053 p->altstack.size = 0;
1054 } else {
1055 p->altstack.sp = a->sp;
1056 p->altstack.size = a->size;
1057 }
1058
1059 trace("sys_signalstack(): new altstack %lux-%lux",
1060 p->altstack.sp, p->altstack.sp + p->altstack.size);
1061 }
1062 if(oa){
1063 oa->sp = sp;
1064 oa->size = size;
1065 oa->flags = flags;
1066 }
1067
1068 return 0;
1069 }
1070
1071 struct linux_sigaction
1072 {
1073 void *handler;
1074 ulong flags;
1075 void *restorer;
1076 uchar mask[];
1077 };
1078
1079 int sys_rt_sigaction(int sig, void *pact, void *poact, int setsize)
1080 {
1081 Private *p;
1082 Action *a;
1083 struct linux_sigaction *act;
1084 struct linux_sigaction *oact;
1085 void *handler;
1086 int flags;
1087 uvlong block;
1088
1089 trace("sys_rt_sigaction(%S, %p, %p, %d)", sig, pact, poact, setsize);
1090
1091 p = current->signal;
1092 act = (struct linux_sigaction*)pact;
1093 oact = (struct linux_sigaction*)poact;
1094
1095 if((sig < 1) || (sig >= SIGMAX))
1096 return -EINVAL;
1097
1098 qlock(p->h);
1099 a = &p->h->a[sig-1];
1100 handler = a->handler;
1101 flags = a->flags;
1102 block = a->block;
1103 if(act){
1104 trace("flags = %x", a->flags);
1105 a->handler = act->handler;
1106 a->flags = act->flags;
1107 a->block = sigset2uvlong(act->mask, setsize);
1108 }
1109 if(oact){
1110 oact->handler = handler;
1111 oact->flags = flags;
1112 oact->restorer = 0;
1113 uvlong2sigset(oact->mask, setsize, block);
1114 }
1115 qunlock(p->h);
1116
1117 return 0;
1118 }
1119
1120 int sys_rt_sigpending(uchar *set, int setsize)
1121 {
1122 Private *p;
1123 Signal *s;
1124 uvlong m;
1125
1126 trace("sys_rt_sigpending(%p, %d)", set, setsize);
1127
1128 p = current->signal;
1129 m = 0LL;
1130 qlock(p->q);
1131 for(s=p->q->head; s; s=s->next){
1132 if(!s->group && (s->topid != current->tid))
1133 continue;
1134 m |= MASK(s->signo);
1135 }
1136 qunlock(p->q);
1137
1138 uvlong2sigset(set, setsize, m);
1139 return 0;
1140 }
1141
1142 enum
1143 {
1144 SIG_BLOCK = 0,
1145 SIG_UNBLOCK = 1,
1146 SIG_SETMASK = 2,
1147 };
1148
1149 int sys_rt_sigprocmask(int how, uchar *act, uchar *oact, int setsize)
1150 {
1151 Private *p;
1152 uvlong m, block;
1153
1154 trace("sys_rt_sigprocmask(%d, %p, %p, %d)", how, act, oact, setsize);
1155
1156 p = current->signal;
1157 block = p->block;
1158 if(act){
1159 m = sigset2uvlong(act, setsize);
1160 m &= ~(MASK(SIGKILL) | MASK(SIGSTOP));
1161 switch(how){
1162 default:
1163 return -EINVAL;
1164 case SIG_BLOCK:
1165 p->block |= m;
1166 break;
1167 case SIG_UNBLOCK:
1168 p->block &= ~m;
1169 break;
1170 case SIG_SETMASK:
1171 p->block = m;
1172 break;
1173 }
1174 }
1175 if(oact)
1176 uvlong2sigset(oact, setsize, block);
1177 return 0;
1178 }
1179
1180 struct linux_itimer
1181 {
1182 struct linux_timeval it_interval;
1183 struct linux_timeval it_value;
1184 };
1185
1186 static vlong
1187 hzround(vlong t)
1188 {
1189 vlong q = 1000000000LL/HZ;
1190 return (t + q-1) / q;
1191 }
1192
1193 int sys_setitimer(int which, void *value, void *ovalue)
1194 {
1195 Private *p;
1196 Timers *t;
1197 vlong now, rem, delta;
1198 struct linux_itimer *nv = value, *ov = ovalue;
1199
1200 trace("sys_setitimer(%d, %p, %p)", which, value, ovalue);
1201
1202 p = current->signal;
1203 t = p->t;
1204
1205 if(which < 0 || which >= nelem(t->itimer))
1206 return -EINVAL;
1207
1208 now = nsec();
1209 delta = t->itimer[which].interval;
1210 rem = t->itimer[which].expire - now;
1211 if(rem < 0)
1212 rem = 0;
1213 if(nv != nil){
1214 trace("nv->{interval->{%ld, %ld}, value->{%ld, %ld}}",
1215 nv->it_interval.tv_sec, nv->it_interval.tv_usec,
1216 nv->it_value.tv_sec, nv->it_value.tv_usec);
1217 t->itimer[which].interval = hzround(nv->it_interval.tv_sec*1000000000LL +
1218 nv->it_interval.tv_usec*1000);
1219 t->itimer[which].expire = (now + nv->it_value.tv_sec*1000000000LL +
1220 nv->it_value.tv_usec*1000);
1221 setalarm(t->itimer[which].expire);
1222 }
1223
1224 if(ov != nil){
1225 ov->it_interval.tv_sec = delta / 1000000000LL;
1226 ov->it_interval.tv_usec = (delta % 1000000000LL)/1000;
1227 ov->it_value.tv_sec = rem / 1000000000LL;
1228 ov->it_value.tv_usec = (rem % 1000000000LL)/1000;
1229 trace("ov->{interval->{%ld, %ld}, value->{%ld, %ld}}",
1230 ov->it_interval.tv_sec, ov->it_interval.tv_usec,
1231 ov->it_value.tv_sec, ov->it_value.tv_usec);
1232 }
1233
1234 return 0;
1235 }
1236
1237 int sys_getitimer(int which, void *value)
1238 {
1239 Private *p;
1240 Timers *t;
1241 vlong rem, delta;
1242 struct linux_itimer *v = value;
1243
1244 trace("sys_getitimer(%d, %p)", which, value);
1245
1246 p = current->signal;
1247 t = p->t;
1248
1249 if(value == nil)
1250 return -EINVAL;
1251 if(which < 0 || which >= nelem(t->itimer))
1252 return -EINVAL;
1253
1254 delta =t->itimer[which].interval;
1255 rem = t->itimer[which].expire - nsec();
1256
1257 if(rem < 0)
1258 rem = 0;
1259 v->it_interval.tv_sec = delta / 1000000000LL;
1260 v->it_interval.tv_usec = (delta % 1000000000LL)/1000;
1261 v->it_value.tv_sec = rem / 1000000000LL;
1262 v->it_value.tv_usec = (rem % 1000000000LL)/1000;
1263
1264 return 0;
1265 }
1266
1267 int sys_alarm(long seconds)
1268 {
1269 Private *p;
1270 Timers *t;
1271 vlong old, now;
1272
1273 trace("sys_alarm(%ld)", seconds);
1274 p = current->signal;
1275 t = p->t;
1276 now = nsec();
1277 old = t->itimer[0].expire - now;
1278 if(old < 0)
1279 old = 0;
1280 t->itimer[0].interval = 0;
1281 if(seconds > 0){
1282 t->itimer[0].expire = now + (vlong)seconds * 1000000000LL;
1283 setalarm(t->itimer[0].expire);
1284 } else {
1285 t->itimer[0].expire = 0;
1286 }
1287 return old / 1000000000LL;
1288 }
1289
1290 int
1291 Sfmt(Fmt *f)
1292 {
1293 static char *t[] = {
1294 [SIGHUP] = "SIGHUP",
1295 [SIGINT] = "SIGINT",
1296 [SIGQUIT] = "SIGQUIT",
1297 [SIGILL] = "SIGILL",
1298 [SIGTRAP] = "SIGTRAP",
1299 [SIGABRT] = "SIGABRT",
1300 [SIGBUS] = "SIGBUS",
1301 [SIGFPE] = "SIGFPE",
1302 [SIGKILL] = "SIGKILL",
1303 [SIGUSR1] = "SIGUSR1",
1304 [SIGSEGV] = "SIGSEGV",
1305 [SIGUSR2] = "SIGUSR2",
1306 [SIGPIPE] = "SIGPIPE",
1307 [SIGALRM] = "SIGALRM",
1308 [SIGTERM] = "SIGTERM",
1309 [SIGSTKFLT] = "SIGSTKFLT",
1310 [SIGCHLD] = "SIGCHLD",
1311 [SIGCONT] = "SIGCONT",
1312 [SIGSTOP] = "SIGSTOP",
1313 [SIGTSTP] = "SIGTSTP",
1314 [SIGTTIN] = "SIGTTIN",
1315 [SIGTTOU] = "SIGTTOU",
1316 [SIGURG] = "SIGURG",
1317 [SIGXCPU] = "SIGXCPU",
1318 [SIGXFSZ] = "SIGXFSZ",
1319 [SIGVTALRM] = "SIGVTALRM",
1320 [SIGPROF] = "SIGPROF",
1321 [SIGWINCH] = "SIGWINCH",
1322 [SIGIO] = "SIGIO",
1323 [SIGPWR] = "SIGPWR",
1324 [SIGSYS] = "SIGSYS",
1325 [SIGRT1] = "SIGRT1",
1326 [SIGRT2] = "SIGRT2",
1327 [SIGRT3] = "SIGRT3",
1328 [SIGRT4] = "SIGRT4",
1329 [SIGRT5] = "SIGRT5",
1330 [SIGRT6] = "SIGRT6",
1331 [SIGRT7] = "SIGRT7",
1332 [SIGRT8] = "SIGRT8",
1333 };
1334
1335 int sig;
1336
1337 sig = va_arg(f->args, int);
1338 if(sig < 1 || sig >= SIGMAX)
1339 return fmtprint(f, "%d", sig);
1340 return fmtprint(f, "%d [%s]", sig, t[sig]);
1341 }
1342
1343 /* proc.c */
1344 extern int procsetalarm(Uproc *proc, vlong t);
1345
1346 void
1347 alarmtimer(Uproc *proc, vlong now)
1348 {
1349 Private *p;
1350 Timers *t;
1351 vlong expire, delta;
1352 Usiginfo si;
1353 int i, overrun;
1354
1355 if((p = proc->signal) == nil)
1356 return;
1357 t = p->t;
1358 for(i=0; i < nelem(t->itimer); i++){
1359 expire = t->itimer[i].expire;
1360 if(expire <= 0)
1361 continue;
1362 if(now < expire){
1363 procsetalarm(proc, expire);
1364 continue;
1365 }
1366 overrun = 0;
1367 delta = (t->itimer[i].interval);
1368 if(delta > 0){
1369 expire += delta;
1370 while(expire <= now){
1371 expire += delta;
1372 overrun++;
1373 }
1374 procsetalarm(proc, expire);
1375 } else {
1376 expire = 0;
1377 }
1378 t->itimer[i].expire = expire;
1379
1380 memset(&si, 0, sizeof(si));
1381 si.signo = SIGALRM;
1382 si.code = SI_TIMER;
1383 si.timer.tid = i;
1384 si.timer.overrun = overrun;
1385 killproc(proc, &si, 1);
1386 }
1387 }