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

Reply via email to