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();
}