Home | History | Annotate | Line # | Download | only in rumpkern
signals.c revision 1.5
      1 /*	$NetBSD: signals.c,v 1.5 2011/01/03 14:57:06 pooka Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: signals.c,v 1.5 2011/01/03 14:57:06 pooka Exp $");
     30 
     31 #include <sys/param.h>
     32 #include <sys/atomic.h>
     33 #include <sys/event.h>
     34 #include <sys/proc.h>
     35 #include <sys/signal.h>
     36 
     37 #include <rump/rump.h>
     38 #include <rump/rumpuser.h>
     39 
     40 #include "rumpkern_if_priv.h"
     41 
     42 const struct filterops sig_filtops = {
     43 	.f_attach = (void *)eopnotsupp,
     44 };
     45 
     46 sigset_t sigcantmask;
     47 
     48 /* RUMP_SIGMODEL_PANIC */
     49 
     50 static void
     51 rumpsig_panic(pid_t target, int signo)
     52 {
     53 
     54 	switch (signo) {
     55 	case SIGSYS:
     56 		break;
     57 	default:
     58 		panic("unhandled signal %d", signo);
     59 	}
     60 }
     61 
     62 /* RUMP_SIGMODEL_IGNORE */
     63 
     64 static void
     65 rumpsig_ignore(pid_t target, int signo)
     66 {
     67 
     68 	return;
     69 }
     70 
     71 /* RUMP_SIGMODEL_HOST */
     72 
     73 static void
     74 rumpsig_host(pid_t target, int signo)
     75 {
     76 	int error;
     77 
     78 	rumpuser_kill(target, signo, &error);
     79 }
     80 
     81 /* RUMP_SIGMODEL_RAISE */
     82 
     83 static void
     84 rumpsig_raise(pid_t target, int signo)
     85 {
     86 	int error;
     87 
     88 	rumpuser_kill(RUMPUSER_PID_SELF, signo, &error);
     89 }
     90 
     91 static void
     92 rumpsig_record(pid_t target, int sig)
     93 {
     94 	struct proc *p = NULL;
     95 	struct pgrp *pgrp = NULL;
     96 
     97 	/* well this is a little silly */
     98 	mutex_enter(proc_lock);
     99 	if (target >= 0)
    100 		p = proc_find_raw(target);
    101 	else
    102 		pgrp = pgrp_find(target);
    103 
    104 	if (p) {
    105 		mutex_enter(p->p_lock);
    106 		if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
    107 			sigaddset(&p->p_sigpend.sp_set, sig);
    108 		}
    109 		mutex_exit(p->p_lock);
    110 	} else if (pgrp) {
    111 		LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
    112 			mutex_enter(p->p_lock);
    113 			if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
    114 				sigaddset(&p->p_sigpend.sp_set, sig);
    115 			}
    116 			mutex_exit(p->p_lock);
    117 		}
    118 	}
    119 	mutex_exit(proc_lock);
    120 }
    121 
    122 typedef void (*rumpsig_fn)(pid_t pid, int sig);
    123 
    124 rumpsig_fn rumpsig = rumpsig_panic;
    125 
    126 /*
    127  * Set signal delivery model.  It would be nice if we could
    128  * take a functional argument.  But then we'd need some
    129  * OS independent way to represent a signal number and also
    130  * a method for easy processing (parsing is boring).
    131  *
    132  * Plus, upcalls from the rump kernel into process space except
    133  * via rumpuser is a somewhat gray area now.
    134  */
    135 void
    136 rump_boot_setsigmodel(enum rump_sigmodel model)
    137 {
    138 
    139 	switch (model) {
    140 	case RUMP_SIGMODEL_PANIC:
    141 		rumpsig = rumpsig_panic;
    142 		break;
    143 	case RUMP_SIGMODEL_IGNORE:
    144 		rumpsig = rumpsig_ignore;
    145 		break;
    146 	case RUMP_SIGMODEL_HOST:
    147 		rumpsig = rumpsig_host;
    148 		break;
    149 	case RUMP_SIGMODEL_RAISE:
    150 		rumpsig = rumpsig_raise;
    151 		break;
    152 	case RUMP_SIGMODEL_RECORD:
    153 		rumpsig = rumpsig_record;
    154 		break;
    155 	}
    156 }
    157 
    158 void
    159 psignal(struct proc *p, int sig)
    160 {
    161 
    162 	rumpsig(p->p_pid, sig);
    163 }
    164 
    165 void
    166 pgsignal(struct pgrp *pgrp, int sig, int checktty)
    167 {
    168 
    169 	rumpsig(-pgrp->pg_id, sig);
    170 }
    171 
    172 void
    173 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
    174 {
    175 
    176 	rumpsig(p->p_pid, ksi->ksi_signo);
    177 }
    178 
    179 void
    180 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
    181 {
    182 
    183 	rumpsig(-pgrp->pg_id, ksi->ksi_signo);
    184 }
    185 
    186 int
    187 sigispending(struct lwp *l, int signo)
    188 {
    189 	struct proc *p = l->l_proc;
    190 	sigset_t tset;
    191 
    192 	tset = p->p_sigpend.sp_set;
    193 
    194 	if (signo == 0) {
    195 		if (firstsig(&tset) != 0)
    196 			return EINTR;
    197 	} else if (sigismember(&tset, signo))
    198 		return EINTR;
    199 	return 0;
    200 }
    201 
    202 void
    203 sigpending1(struct lwp *l, sigset_t *ss)
    204 {
    205 	struct proc *p = l->l_proc;
    206 
    207 	mutex_enter(p->p_lock);
    208 	*ss = l->l_proc->p_sigpend.sp_set;
    209 	mutex_exit(p->p_lock);
    210 }
    211 
    212 int
    213 sigismasked(struct lwp *l, int sig)
    214 {
    215 
    216 	return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig);
    217 }
    218 
    219 void
    220 sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq)
    221 {
    222 
    223 	if (mask == NULL)
    224 		sigemptyset(&sp->sp_set);
    225 	else
    226 		sigminusset(mask, &sp->sp_set);
    227 }
    228 
    229 void
    230 sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq)
    231 {
    232 
    233 	/* don't assert proc lock, hence callable from user context */
    234 	sigclear(&p->p_sigpend, mask, kq);
    235 }
    236 
    237 void
    238 ksiginfo_queue_drain0(ksiginfoq_t *kq)
    239 {
    240 
    241 	if (!(CIRCLEQ_EMPTY(kq)))
    242 		panic("how did that get there?");
    243 }
    244 
    245 int
    246 sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
    247 {
    248 	sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore;
    249 
    250 	KASSERT(mutex_owned(l->l_proc->p_lock));
    251 
    252 	if (oss)
    253 		*oss = *mask;
    254 
    255 	if (nss) {
    256 		switch (how) {
    257 		case SIG_BLOCK:
    258 			sigplusset(nss, mask);
    259 			break;
    260 		case SIG_UNBLOCK:
    261 			sigminusset(nss, mask);
    262 			break;
    263 		case SIG_SETMASK:
    264 			*mask = *nss;
    265 			break;
    266 		default:
    267 			return EINVAL;
    268 		}
    269 	}
    270 
    271 	return 0;
    272 }
    273 
    274 void
    275 siginit(struct proc *p)
    276 {
    277 
    278 	sigemptyset(&p->p_sigctx.ps_sigignore);
    279 	sigemptyset(&p->p_sigpend.sp_set);
    280 }
    281