Module Name: src Committed By: christos Date: Thu Aug 4 06:43:43 UTC 2016
Modified Files: src/include: limits.h src/lib/libc/gen: sysconf.c src/sys/kern: kern_sig.c sys_sig.c src/sys/sys: signal.h signalvar.h unistd.h src/tests/lib/libc/sys: t_sigqueue.c Log Message: Realtime signal support from GSoC 2016, Charles Cui. To generate a diff of this commit: cvs rdiff -u -r1.39 -r1.40 src/include/limits.h cvs rdiff -u -r1.40 -r1.41 src/lib/libc/gen/sysconf.c cvs rdiff -u -r1.327 -r1.328 src/sys/kern/kern_sig.c cvs rdiff -u -r1.45 -r1.46 src/sys/kern/sys_sig.c cvs rdiff -u -r1.70 -r1.71 src/sys/sys/signal.h cvs rdiff -u -r1.86 -r1.87 src/sys/sys/signalvar.h cvs rdiff -u -r1.60 -r1.61 src/sys/sys/unistd.h cvs rdiff -u -r1.5 -r1.6 src/tests/lib/libc/sys/t_sigqueue.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/include/limits.h diff -u src/include/limits.h:1.39 src/include/limits.h:1.40 --- src/include/limits.h:1.39 Thu Jul 21 12:01:58 2016 +++ src/include/limits.h Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: limits.h,v 1.39 2016/07/21 16:01:58 njoly Exp $ */ +/* $NetBSD: limits.h,v 1.40 2016/08/04 06:43:43 christos Exp $ */ /* * Copyright (c) 1988, 1993 @@ -94,6 +94,8 @@ #define _POSIX_TIMER_MAX 32 #define _POSIX_SEM_NSEMS_MAX 256 +#define _POSIX_SIGQUEUE_MAX 32 +#define _POSIX_REALTIME_SIGNALS 200112L #define _POSIX_DELAYTIMER_MAX 32 #define _POSIX_TTY_NAME_MAX 9 #define _POSIX_TZNAME_MAX 6 Index: src/lib/libc/gen/sysconf.c diff -u src/lib/libc/gen/sysconf.c:1.40 src/lib/libc/gen/sysconf.c:1.41 --- src/lib/libc/gen/sysconf.c:1.40 Sun Jul 3 10:24:58 2016 +++ src/lib/libc/gen/sysconf.c Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sysconf.c,v 1.40 2016/07/03 14:24:58 christos Exp $ */ +/* $NetBSD: sysconf.c,v 1.41 2016/08/04 06:43:43 christos Exp $ */ /*- * Copyright (c) 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)sysconf.c 8.2 (Berkeley) 3/20/94"; #else -__RCSID("$NetBSD: sysconf.c,v 1.40 2016/07/03 14:24:58 christos Exp $"); +__RCSID("$NetBSD: sysconf.c,v 1.41 2016/08/04 06:43:43 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -429,6 +429,10 @@ yesno: if (sysctl(mib, mib_len, &value, return _POSIX_THREAD_CPUTIME; case _SC_DELAYTIMER_MAX: return _POSIX_DELAYTIMER_MAX; + case _SC_SIGQUEUE_MAX: + return _POSIX_SIGQUEUE_MAX; + case _SC_REALTIME_SIGNALS: + return 200112L; default: errno = EINVAL; return (-1); Index: src/sys/kern/kern_sig.c diff -u src/sys/kern/kern_sig.c:1.327 src/sys/kern/kern_sig.c:1.328 --- src/sys/kern/kern_sig.c:1.327 Wed Apr 27 20:37:39 2016 +++ src/sys/kern/kern_sig.c Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sig.c,v 1.327 2016/04/28 00:37:39 christos Exp $ */ +/* $NetBSD: kern_sig.c,v 1.328 2016/08/04 06:43:43 christos Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.327 2016/04/28 00:37:39 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.328 2016/08/04 06:43:43 christos Exp $"); #include "opt_ptrace.h" #include "opt_dtrace.h" @@ -106,6 +106,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v #include <uvm/uvm_extern.h> +#define SIGQUEUE_MAX 32 static pool_cache_t sigacts_cache __read_mostly; static pool_cache_t ksiginfo_cache __read_mostly; static callout_t proc_stop_ch __cacheline_aligned; @@ -118,7 +119,7 @@ static void ksiginfo_exechook(struct pro static void proc_stop_callout(void *); static int sigchecktrace(void); static int sigpost(struct lwp *, sig_t, int, int); -static void sigput(sigpend_t *, struct proc *, ksiginfo_t *); +static int sigput(sigpend_t *, struct proc *, ksiginfo_t *); static int sigunwait(struct proc *, const ksiginfo_t *); static void sigswitch(bool, int, int); @@ -523,7 +524,7 @@ ksiginfo_queue_drain0(ksiginfoq_t *kq) } } -static bool +static int siggetinfo(sigpend_t *sp, ksiginfo_t *out, int signo) { ksiginfo_t *ksi; @@ -532,9 +533,12 @@ siggetinfo(sigpend_t *sp, ksiginfo_t *ou goto out; /* Find siginfo and copy it out. */ + int count = 0; TAILQ_FOREACH(ksi, &sp->sp_info, ksi_list) { if (ksi->ksi_signo != signo) continue; + if (count++ > 0) /* Only remove the first, count all of them */ + continue; TAILQ_REMOVE(&sp->sp_info, ksi, ksi_list); KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0); KASSERT((ksi->ksi_flags & KSI_QUEUED) != 0); @@ -543,9 +547,10 @@ siggetinfo(sigpend_t *sp, ksiginfo_t *ou memcpy(out, ksi, sizeof(*out)); out->ksi_flags &= ~(KSI_FROMPOOL | KSI_QUEUED); } - ksiginfo_free(ksi); /* XXXSMP */ - return true; + ksiginfo_free(ksi); } + if (count) + return count; out: /* If there is no siginfo, then manufacture it. */ @@ -554,7 +559,7 @@ out: out->ksi_info._signo = signo; out->ksi_info._code = SI_NOINFO; } - return false; + return 0; } /* @@ -568,6 +573,7 @@ int sigget(sigpend_t *sp, ksiginfo_t *out, int signo, const sigset_t *mask) { sigset_t tset; + int count; /* If there's no pending set, the signal is from the debugger. */ if (sp == NULL) @@ -590,7 +596,9 @@ sigget(sigpend_t *sp, ksiginfo_t *out, i sigdelset(&sp->sp_set, signo); out: - (void)siggetinfo(sp, out, signo); + count = siggetinfo(sp, out, signo); + if (count > 1) + sigaddset(&sp->sp_set, signo); return signo; } @@ -599,7 +607,7 @@ out: * * Append a new ksiginfo element to the list of pending ksiginfo's. */ -static void +static int sigput(sigpend_t *sp, struct proc *p, ksiginfo_t *ksi) { ksiginfo_t *kp; @@ -613,25 +621,33 @@ sigput(sigpend_t *sp, struct proc *p, ks * If there is no siginfo, we are done. */ if (KSI_EMPTY_P(ksi)) - return; + return 0; KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0); -#ifdef notyet /* XXX: QUEUING */ - if (ksi->ksi_signo < SIGRTMIN) -#endif - { - TAILQ_FOREACH(kp, &sp->sp_info, ksi_list) { - if (kp->ksi_signo == ksi->ksi_signo) { - KSI_COPY(ksi, kp); - kp->ksi_flags |= KSI_QUEUED; - return; - } + size_t count = 0; + TAILQ_FOREACH(kp, &sp->sp_info, ksi_list) { + count++; + if (ksi->ksi_signo >= SIGRTMIN && ksi->ksi_signo <= SIGRTMAX) + continue; + if (kp->ksi_signo == ksi->ksi_signo) { + KSI_COPY(ksi, kp); + kp->ksi_flags |= KSI_QUEUED; + return 0; } } - + + if (count >= SIGQUEUE_MAX) { +#ifdef DIAGNOSTIC + printf("%s(%d): Signal queue is full signal=%d\n", + p->p_comm, p->p_pid, ksi->ksi_signo); +#endif + return EAGAIN; + } ksi->ksi_flags |= KSI_QUEUED; TAILQ_INSERT_TAIL(&sp->sp_info, ksi, ksi_list); + + return 0; } /* @@ -1195,7 +1211,7 @@ sigunwait(struct proc *p, const ksiginfo * * Other ignored signals are discarded immediately. */ -void +int kpsignal2(struct proc *p, ksiginfo_t *ksi) { int prop, signo = ksi->ksi_signo; @@ -1205,6 +1221,7 @@ kpsignal2(struct proc *p, ksiginfo_t *ks lwpid_t lid; sig_t action; bool toall; + int error = 0; KASSERT(!cpu_intr_p()); KASSERT(mutex_owned(proc_lock)); @@ -1217,7 +1234,7 @@ kpsignal2(struct proc *p, ksiginfo_t *ks * exiting, then just drop the signal here and bail out. */ if (p->p_stat != SACTIVE && p->p_stat != SSTOP) - return; + return 0; /* * Notify any interested parties of the signal. @@ -1245,7 +1262,8 @@ kpsignal2(struct proc *p, ksiginfo_t *ks */ if ((kp = ksiginfo_alloc(p, ksi, PR_NOWAIT)) == NULL) goto discard; - sigput(&p->p_sigpend, p, kp); + if ((error = sigput(&p->p_sigpend, p, kp)) != 0) + goto out; } } else { /* @@ -1329,7 +1347,8 @@ kpsignal2(struct proc *p, ksiginfo_t *ks if (lid != 0) { l = lwp_find(p, lid); if (l != NULL) { - sigput(&l->l_sigpend, p, kp); + if ((error = sigput(&l->l_sigpend, p, kp)) != 0) + goto out; membar_producer(); (void)sigpost(l, action, prop, kp->ksi_signo); } @@ -1401,8 +1420,8 @@ kpsignal2(struct proc *p, ksiginfo_t *ks * Make signal pending. */ KASSERT((p->p_slflag & PSL_TRACED) == 0); - sigput(&p->p_sigpend, p, kp); - + if ((error = sigput(&p->p_sigpend, p, kp)) != 0) + goto out; deliver: /* * Before we set LW_PENDSIG on any LWP, ensure that the signal is @@ -1426,9 +1445,10 @@ out: */ ksiginfo_free(kp); if (signo == -1) - return; + return error; discard: SDT_PROBE(proc, kernel, , signal__discard, l, p, signo, 0, 0); + return error; } void Index: src/sys/kern/sys_sig.c diff -u src/sys/kern/sys_sig.c:1.45 src/sys/kern/sys_sig.c:1.46 --- src/sys/kern/sys_sig.c:1.45 Fri Oct 2 12:54:15 2015 +++ src/sys/kern/sys_sig.c Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_sig.c,v 1.45 2015/10/02 16:54:15 christos Exp $ */ +/* $NetBSD: sys_sig.c,v 1.46 2016/08/04 06:43:43 christos Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.45 2015/10/02 16:54:15 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.46 2016/08/04 06:43:43 christos Exp $"); #include "opt_dtrace.h" @@ -258,7 +258,7 @@ kill1(struct lwp *l, pid_t pid, ksiginfo KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(ksi->ksi_signo), NULL, NULL); if (!error && ksi->ksi_signo) { - kpsignal2(p, ksi); + error = kpsignal2(p, ksi); } mutex_exit(p->p_lock); mutex_exit(proc_lock); Index: src/sys/sys/signal.h diff -u src/sys/sys/signal.h:1.70 src/sys/sys/signal.h:1.71 --- src/sys/sys/signal.h:1.70 Wed Jun 15 08:10:18 2016 +++ src/sys/sys/signal.h Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: signal.h,v 1.70 2016/06/15 12:10:18 christos Exp $ */ +/* $NetBSD: signal.h,v 1.71 2016/08/04 06:43:43 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 @@ -82,10 +82,8 @@ #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ #define SIGPWR 32 /* power fail/restart (not reset when caught) */ -#ifdef _KERNEL -#define SIGRTMIN 33 /* Kernel only; not exposed to userland yet */ -#define SIGRTMAX 63 /* Kernel only; not exposed to userland yet */ -#endif +#define SIGRTMIN 33 +#define SIGRTMAX 63 #ifndef _KERNEL #include <sys/cdefs.h> Index: src/sys/sys/signalvar.h diff -u src/sys/sys/signalvar.h:1.86 src/sys/sys/signalvar.h:1.87 --- src/sys/sys/signalvar.h:1.86 Thu May 15 03:11:30 2014 +++ src/sys/sys/signalvar.h Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: signalvar.h,v 1.86 2014/05/15 07:11:30 uebayasi Exp $ */ +/* $NetBSD: signalvar.h,v 1.87 2016/08/04 06:43:43 christos Exp $ */ /* * Copyright (c) 1991, 1993 @@ -151,7 +151,7 @@ int sigget(sigpend_t *, ksiginfo_t *, in void sigclear(sigpend_t *, const sigset_t *, ksiginfoq_t *); void sigclearall(struct proc *, const sigset_t *, ksiginfoq_t *); -void kpsignal2(struct proc *, ksiginfo_t *); +int kpsignal2(struct proc *, ksiginfo_t *); void signal_init(void); Index: src/sys/sys/unistd.h diff -u src/sys/sys/unistd.h:1.60 src/sys/sys/unistd.h:1.61 --- src/sys/sys/unistd.h:1.60 Thu Jul 21 12:01:59 2016 +++ src/sys/sys/unistd.h Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: unistd.h,v 1.60 2016/07/21 16:01:59 njoly Exp $ */ +/* $NetBSD: unistd.h,v 1.61 2016/08/04 06:43:43 christos Exp $ */ /* * Copyright (c) 1989, 1993 @@ -318,6 +318,8 @@ #define _SC_CPUTIME 90 #define _SC_THREAD_CPUTIME 91 #define _SC_DELAYTIMER_MAX 92 +#define _SC_SIGQUEUE_MAX 93 +#define _SC_REALTIME_SIGNALS 94 /* Extensions found in Solaris and Linux. */ #define _SC_PHYS_PAGES 121 Index: src/tests/lib/libc/sys/t_sigqueue.c diff -u src/tests/lib/libc/sys/t_sigqueue.c:1.5 src/tests/lib/libc/sys/t_sigqueue.c:1.6 --- src/tests/lib/libc/sys/t_sigqueue.c:1.5 Sat Jun 6 09:14:06 2015 +++ src/tests/lib/libc/sys/t_sigqueue.c Thu Aug 4 02:43:43 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: t_sigqueue.c,v 1.5 2015/06/06 13:14:06 joerg Exp $ */ +/* $NetBSD: t_sigqueue.c,v 1.6 2016/08/04 06:43:43 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_sigqueue.c,v 1.5 2015/06/06 13:14:06 joerg Exp $"); +__RCSID("$NetBSD: t_sigqueue.c,v 1.6 2016/08/04 06:43:43 christos Exp $"); #include <atf-c.h> @@ -93,11 +93,115 @@ ATF_TC_BODY(sigqueue_err, tc) ATF_REQUIRE_ERRNO(EINVAL, sigqueue(getpid(), -1, sv) == -1); } +static int signals[] = { + SIGINT, SIGRTMIN + 1, SIGINT, SIGRTMIN + 0, SIGRTMIN + 2, + SIGQUIT, SIGRTMIN + 1 +}; +#ifdef __arraycount +#define CNT __arraycount(signals) +#else +#define CNT (sizeof(signals) / sizeof(signals[0])) +#endif + +static sig_atomic_t count = 0; +static int delivered[CNT]; + +static void +myhandler(int signo, siginfo_t *info, void *context) +{ + delivered[count++] = signo; +} + +static int +asc(const void *a, const void *b) +{ + const int *ia = a, *ib = b; + return *ib - *ia; +} + +/* + * given a array of signals to be delivered in tosend of size len + * place in ordered the signals to be delivered in delivery order + * and return the number of signals that should be delivered + */ +static size_t +sigorder(int *ordered, const int *tosend, size_t len) +{ + memcpy(ordered, tosend, len * sizeof(*tosend)); + qsort(ordered, len, sizeof(*ordered), asc); + if (len == 1) + return len; + + size_t i, j; + for (i = 0, j = 0; i < len - 1; i++) { + if (ordered[i] >= SIGRTMIN) + continue; + if (j == 0) + j = i + 1; + while (ordered[i] == ordered[j] && j < len) + j++; + if (j == len) + break; + ordered[i + 1] = ordered[j]; + } + return i + 1; +} + +ATF_TC(sigqueue_rt); +ATF_TC_HEAD(sigqueue_rt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test queuing of real-time signals"); +} + +ATF_TC_BODY(sigqueue_rt, tc) +{ + pid_t pid; + union sigval val; + struct sigaction act; + int ordered[CNT]; + struct sigaction oact[CNT]; + size_t ndelivered; + + ndelivered = sigorder(ordered, signals, CNT); + + act.sa_flags = SA_SIGINFO; + act.sa_sigaction = myhandler; + sigemptyset(&act.sa_mask); + for (size_t i = 0; i < ndelivered; i++) + ATF_REQUIRE(sigaction(ordered[i], &act, &oact[i]) != -1); + + val.sival_int = 0; + pid = getpid(); + + sigset_t mask, orig; + sigemptyset(&mask); + for (size_t i = 0; i < CNT; i++) + sigaddset(&mask, signals[i]); + + ATF_REQUIRE(sigprocmask(SIG_BLOCK, &mask, &orig) != -1); + + for (size_t i = 0; i < CNT; i++) + ATF_REQUIRE(sigqueue(pid, signals[i], val) != -1); + + ATF_REQUIRE(sigprocmask(SIG_UNBLOCK, &mask, &orig) != -1); + sleep(1); + ATF_REQUIRE_MSG((size_t)count == ndelivered, + "count %zu != ndelivered %zu", (size_t)count, ndelivered); + for (size_t i = 0; i < ndelivered; i++) + ATF_REQUIRE_MSG(ordered[i] == delivered[i], + "%zu: ordered %d != delivered %d", + i, ordered[i], delivered[i]); + + for (size_t i = 0; i < ndelivered; i++) + ATF_REQUIRE(sigaction(signals[i], &oact[i], NULL) != -1); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, sigqueue_basic); ATF_TP_ADD_TC(tp, sigqueue_err); + ATF_TP_ADD_TC(tp, sigqueue_rt); return atf_no_error(); }