Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern handle siginfo for deferred signals. Allocate a ksi...



details:   https://anonhg.NetBSD.org/src/rev/96849fe9ff08
branches:  trunk
changeset: 551928:96849fe9ff08
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Sep 14 06:59:13 2003 +0000

description:
handle siginfo for deferred signals. Allocate a ksiginfo pool, and store
the information there.
TODO:
1. since timer stuff gets called from an interrupt context, we could
   preallocate ksiginfo_t's from the pool, so we don't need a kmem
   pool.
2. probably the sa signal delivery syscall can be changed to take
   a ksiginfo_t so we can use only one pool.
3. maybe when we add realtime signal support, add a resource limit
   on the number of ksiginfo_t's a process can allocate.

diffstat:

 sys/kern/core_elf32.c  |    8 +-
 sys/kern/core_netbsd.c |    8 +-
 sys/kern/kern_sig.c    |  168 +++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 151 insertions(+), 33 deletions(-)

diffs (truncated from 382 to 300 lines):

diff -r fdd3e85666bc -r 96849fe9ff08 sys/kern/core_elf32.c
--- a/sys/kern/core_elf32.c     Sun Sep 14 06:56:22 2003 +0000
+++ b/sys/kern/core_elf32.c     Sun Sep 14 06:59:13 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: core_elf32.c,v 1.11 2003/09/06 22:03:09 christos Exp $ */
+/*     $NetBSD: core_elf32.c,v 1.12 2003/09/14 06:59:13 christos Exp $ */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.11 2003/09/06 22:03:09 christos Exp $");
+__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.12 2003/09/14 06:59:13 christos Exp $");
 
 /* If not included by core_elf64.c, ELFSIZE won't be defined. */
 #ifndef ELFSIZE
@@ -303,8 +303,8 @@
        if (offset) {
                cpi.cpi_version = NETBSD_ELFCORE_PROCINFO_VERSION;
                cpi.cpi_cpisize = sizeof(cpi);
-               cpi.cpi_signo = p->p_sigctx.ps_siginfo.ksi_signo;
-               cpi.cpi_sigcode = p->p_sigctx.ps_siginfo.ksi_trap;
+               cpi.cpi_signo = p->p_sigctx.ps_signo;
+               cpi.cpi_sigcode = p->p_sigctx.ps_code;
                cpi.cpi_siglwp = p->p_sigctx.ps_lwp;
 
                memcpy(&cpi.cpi_sigpend, &p->p_sigctx.ps_siglist,
diff -r fdd3e85666bc -r 96849fe9ff08 sys/kern/core_netbsd.c
--- a/sys/kern/core_netbsd.c    Sun Sep 14 06:56:22 2003 +0000
+++ b/sys/kern/core_netbsd.c    Sun Sep 14 06:59:13 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: core_netbsd.c,v 1.6 2003/09/06 22:03:09 christos Exp $ */
+/*     $NetBSD: core_netbsd.c,v 1.7 2003/09/14 06:59:14 christos Exp $ */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.6 2003/09/06 22:03:09 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.7 2003/09/14 06:59:14 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -82,8 +82,8 @@
        cs.core.c_midmag = 0;
        strncpy(cs.core.c_name, p->p_comm, MAXCOMLEN);
        cs.core.c_nseg = 0;
-       cs.core.c_signo = p->p_sigctx.ps_siginfo.ksi_signo;
-       cs.core.c_ucode = p->p_sigctx.ps_siginfo.ksi_trap;
+       cs.core.c_signo = p->p_sigctx.ps_signo;
+       cs.core.c_ucode = p->p_sigctx.ps_code;
        cs.core.c_cpusize = 0;
        cs.core.c_tsize = (u_long)ctob(vm->vm_tsize);
        cs.core.c_dsize = (u_long)ctob(vm->vm_dsize);
diff -r fdd3e85666bc -r 96849fe9ff08 sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c       Sun Sep 14 06:56:22 2003 +0000
+++ b/sys/kern/kern_sig.c       Sun Sep 14 06:59:13 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sig.c,v 1.151 2003/09/13 15:32:41 christos Exp $  */
+/*     $NetBSD: kern_sig.c,v 1.152 2003/09/14 06:59:14 christos Exp $  */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.151 2003/09/13 15:32:41 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.152 2003/09/14 06:59:14 christos Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_compat_sunos.h"
@@ -82,10 +82,17 @@
 static void    child_psignal(struct proc *, int);
 static void    proc_stop(struct proc *);
 static int     build_corename(struct proc *, char [MAXPATHLEN]);
+static void    ksiginfo_exithook(struct proc *, void *);
+static void    ksiginfo_save(struct proc *, ksiginfo_t *);
+static void    ksiginfo_del(struct proc *p, ksiginfo_t *);
+static void    ksiginfo_put(struct proc *, ksiginfo_t *);
+static ksiginfo_t *ksiginfo_get(struct proc *, int);
+
 sigset_t       contsigmask, stopsigmask, sigcantmask;
 
 struct pool    sigacts_pool;   /* memory pool for sigacts structures */
 struct pool    siginfo_pool;   /* memory pool for siginfo structures */
+struct pool    ksiginfo_pool;  /* memory pool for ksiginfo structures */
 
 /*
  * Can process p, with pcred pc, send the signal signum to process q?
@@ -99,16 +106,101 @@
            ((signum) == SIGCONT && (q)->p_session == (p)->p_session))
 
 /*
+ * return the first ksiginfo struct from our hash table
+ */
+static ksiginfo_t *
+ksiginfo_get(struct proc *p, int signo)
+{
+       ksiginfo_t *ksi, *hp = p->p_sigctx.ps_siginfo;
+
+       if ((ksi = hp) == NULL)
+               return NULL;
+
+       for (;;) {
+               if (ksi->ksi_signo == signo)
+                       return ksi;
+               if ((ksi = ksi->ksi_next) == hp)
+                       return NULL;
+       }
+}
+
+static void
+ksiginfo_put(struct proc *p, ksiginfo_t *ksi)
+{
+       ksiginfo_t *hp = p->p_sigctx.ps_siginfo;
+
+       if (hp == NULL)
+               p->p_sigctx.ps_siginfo = ksi->ksi_next = ksi->ksi_prev = ksi;
+       else {
+               ksi->ksi_prev = hp->ksi_prev;
+               hp->ksi_prev->ksi_next = ksi;
+               hp->ksi_prev = ksi;
+               ksi->ksi_next = hp;
+       }
+}
+
+static void
+ksiginfo_del(struct proc *p, ksiginfo_t *ksi)
+{
+       if (ksi->ksi_next == ksi)
+               p->p_sigctx.ps_siginfo = NULL;
+       else {
+               ksi->ksi_prev->ksi_next = ksi->ksi_next;
+               ksi->ksi_next->ksi_prev = ksi->ksi_prev;
+       }
+}
+
+static void
+ksiginfo_save(struct proc *p, ksiginfo_t *ksi)
+{
+       ksiginfo_t *kpool = NULL;
+       if ((SIGACTION_PS(p->p_sigacts, ksi->ksi_signo).sa_flags & SA_SIGINFO)
+           == 0)
+               return;
+       if (
+#ifdef notyet  /* XXX: QUEUING */
+           ksi->ksi_signo >= SIGRTMIN ||
+#endif
+           (kpool = ksiginfo_get(p, ksi->ksi_signo)) == NULL) {
+               if ((kpool = pool_get(&ksiginfo_pool, PR_NOWAIT)) == NULL)
+                       return;
+               *kpool = *ksi;
+               ksiginfo_put(p, kpool);
+       } else
+               *kpool = *ksi;
+}
+
+/*
+ * free all pending ksiginfo on exit
+ */
+static void
+ksiginfo_exithook(struct proc *p, void *v)
+{
+       ksiginfo_t *ksi, *hp = p->p_sigctx.ps_siginfo;
+
+       if (hp == NULL)
+               return;
+       for (;;) {
+               pool_put(&ksiginfo_pool, ksi);
+               if ((ksi = ksi->ksi_next) == hp)
+                       break;
+       }
+}
+
+/*
  * Initialize signal-related data structures.
  */
 void
 signal_init(void)
 {
-
        pool_init(&sigacts_pool, sizeof(struct sigacts), 0, 0, 0, "sigapl",
            &pool_allocator_nointr);
        pool_init(&siginfo_pool, sizeof(siginfo_t), 0, 0, 0, "siginfo",
            &pool_allocator_nointr);
+       pool_init(&ksiginfo_pool, sizeof(ksiginfo_t), 0, 0, 0, "ksiginfo",
+           NULL);
+       exithook_establish(ksiginfo_exithook, NULL);
+       exechook_establish(ksiginfo_exithook, NULL);
 }
 
 /*
@@ -812,9 +904,10 @@
                }
                (void) spl0();          /* XXXSMP */
        } else {
+               p->p_sigctx.ps_lwp = l->l_lid;
                /* XXX for core dump/debugger */
-               p->p_sigctx.ps_siginfo = *ksi;
-               p->p_sigctx.ps_lwp = l->l_lid;
+               p->p_sigctx.ps_signo = ksi->ksi_signo;
+               p->p_sigctx.ps_code = ksi->ksi_trap;
                kpsignal(p, ksi, NULL);
        }
 }
@@ -961,11 +1054,12 @@
        if ((prop & SA_CANTMASK) == 0
            && p->p_sigctx.ps_sigwaited < 0
            && sigismember(&p->p_sigctx.ps_sigwait, signum)
-           &&  p->p_stat != SSTOP) {
+           && p->p_stat != SSTOP) {
+               if (action == SIG_CATCH)
+                       ksiginfo_save(p, ksi);
                sigdelset(&p->p_sigctx.ps_siglist, signum);
                p->p_sigctx.ps_sigwaited = signum;
                sigemptyset(&p->p_sigctx.ps_sigwait);
-
                if (dolock)
                        wakeup_one(&p->p_sigctx.ps_sigwait);
                else
@@ -977,8 +1071,11 @@
         * Defer further processing for signals which are held,
         * except that stopped processes must be continued by SIGCONT.
         */
-       if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP))
+       if (action == SIG_HOLD &&
+           ((prop & SA_CONT) == 0 || p->p_stat != SSTOP)) {
+               ksiginfo_save(p, ksi);
                return;
+       }
        /* XXXSMP: works, but icky */
        if (dolock)
                SCHED_LOCK(s);
@@ -1040,7 +1137,7 @@
                         */
                        if ((prop & SA_CONT) && action == SIG_DFL) {
                                sigdelset(&p->p_sigctx.ps_siglist, signum);
-                               goto out;
+                               goto done;
                        }
 
                        /*
@@ -1052,8 +1149,9 @@
                                 * If a child holding parent blocked,
                                 * stopping could cause deadlock.
                                 */
-                               if (p->p_flag & P_PPWAIT)
+                               if (p->p_flag & P_PPWAIT) {
                                        goto out;
+                               }
                                sigdelset(&p->p_sigctx.ps_siglist, signum);
                                p->p_xstat = signum;
                                if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0) {
@@ -1064,7 +1162,7 @@
                                        child_psignal(p, 0);
                                }
                                proc_stop(p);   /* XXXSMP: recurse? */
-                               goto out;
+                               goto done;
                        }
 
                        if (l == NULL) {
@@ -1077,7 +1175,7 @@
                                 */
                                if (allsusp && (signum == SIGKILL))
                                        lwp_continue(suspended);
-                               goto out;
+                               goto done;
                        }
                        /*
                         * All other (caught or default) signals
@@ -1092,7 +1190,7 @@
                         * then no further action is necessary.
                         */
                        if (p->p_flag & P_TRACED)
-                               goto out;
+                               goto done;
 
                        /*
                         * Kill signal always sets processes running,
@@ -1102,7 +1200,7 @@
                                l = proc_unstop(p);
                                if (l)
                                        goto runfast;
-                               goto out;
+                               goto done;
                        }
                        
                        if (prop & SA_CONT) {
@@ -1135,7 +1233,7 @@
                                 * (If we did the shell could get confused.)
                                 */
                                sigdelset(&p->p_sigctx.ps_siglist, signum);
-                               goto out;
+                               goto done;



Home | Main Index | Thread Index | Old Index