tech-userlevel archive

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

Re: updates?



Yes, it works for me, each time I send you a new patch, I will compile my
kernel and userland,
and testing using the program we have written.

Here is a short video that I created from my environment which shows the
real time signal works for me
https://www.dropbox.com/s/amds3jmpfev8jz9/realtime_signal.mov?dl=0

Also, I looked at all files needed in the real time signal patches,
and attached all files of them, you can replace using these files and see
whether there are any
differences with the current settings.

/usr/src/sys/sys/signal.h

/usr/src/include/limits.h

/usr/src/lib/libc/gen/sysconf.c

/usr/src/sys/kern/kern_sig.c

/usr/src/sys/kern/sys_sig.c

/usr/src/sys/sys/signalvar.h

/usr/src/sys/sys/unistd.h

2016-07-30 9:36 GMT-07:00 Christos Zoulas <christos%zoulas.com@localhost>:

> On Jul 29,  4:28pm, charles.cui1984%gmail.com@localhost (Charles Cui) wrote:
> -- Subject: Re: updates?
>
> | Hi Christos,
> |
> |   This patch fix the memory leak that you found in the RT patch.
> |
> |
> https://github.com/ycui1984/posixtestsuite/blob/master/patches/REALTIME_SIGNAL/0008-bug-fix.patch
> |
>
> Thanks but how are you testing this stuff? I just applied all the patche
> and
> now I can't login to my vm via ssh. Signal delivery seems completely
> broken.
> If I ^C a kernel make, I get from the kernel "sendsig: bad version 0", and
> then Illegal Instruction. Does this work for you?
>
> christos
>
/*	$NetBSD: signal.h,v 1.67 2011/01/10 13:56:44 christos Exp $	*/

/*
 * Copyright (c) 1982, 1986, 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)signal.h	8.4 (Berkeley) 5/4/95
 */

#ifndef	_SYS_SIGNAL_H_
#define	_SYS_SIGNAL_H_

#include <sys/featuretest.h>
#include <sys/sigtypes.h>

#define _NSIG		64

#if defined(_NETBSD_SOURCE)
#define NSIG _NSIG

#endif /* _NETBSD_SOURCE */

#define	SIGHUP		1	/* hangup */
#define	SIGINT		2	/* interrupt */
#define	SIGQUIT		3	/* quit */
#define	SIGILL		4	/* illegal instruction (not reset when caught) */
#define	SIGTRAP		5	/* trace trap (not reset when caught) */
#define	SIGABRT		6	/* abort() */
#define	SIGIOT		SIGABRT	/* compatibility */
#define	SIGEMT		7	/* EMT instruction */
#define	SIGFPE		8	/* floating point exception */
#define	SIGKILL		9	/* kill (cannot be caught or ignored) */
#define	SIGBUS		10	/* bus error */
#define	SIGSEGV		11	/* segmentation violation */
#define	SIGSYS		12	/* bad argument to system call */
#define	SIGPIPE		13	/* write on a pipe with no one to read it */
#define	SIGALRM		14	/* alarm clock */
#define	SIGTERM		15	/* software termination signal from kill */
#define	SIGURG		16	/* urgent condition on IO channel */
#define	SIGSTOP		17	/* sendable stop signal not from tty */
#define	SIGTSTP		18	/* stop signal from tty */
#define	SIGCONT		19	/* continue a stopped process */
#define	SIGCHLD		20	/* to parent on child stop or exit */
#define	SIGTTIN		21	/* to readers pgrp upon background tty read */
#define	SIGTTOU		22	/* like TTIN for output if (tp->t_local&LTOSTOP) */
#define	SIGIO		23	/* input/output possible signal */
#define	SIGXCPU		24	/* exceeded CPU time limit */
#define	SIGXFSZ		25	/* exceeded file size limit */
#define	SIGVTALRM	26	/* virtual time alarm */
#define	SIGPROF		27	/* profiling time alarm */
#define	SIGWINCH	28	/* window size changes */
#define	SIGINFO		29	/* information request */
#define	SIGUSR1		30	/* user defined signal 1 */
#define	SIGUSR2		31	/* user defined signal 2 */
#define	SIGPWR		32	/* power fail/restart (not reset when caught) */
#define	SIGRTMIN	33
#define	SIGRTMAX	63
#define SIGPOLL		SIGIO

#ifndef _KERNEL
#include <sys/cdefs.h>
#endif

#define	SIG_DFL		((void (*)(int))  0)
#define	SIG_IGN		((void (*)(int))  1)
#define	SIG_ERR		((void (*)(int)) -1)
#define	SIG_HOLD	((void (*)(int))  3)

#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || \
    defined(_NETBSD_SOURCE)

#ifdef _KERNEL
#define	sigaddset(s, n)		__sigaddset(s, n)
#define	sigdelset(s, n)		__sigdelset(s, n)
#define	sigismember(s, n)	__sigismember(s, n)
#define	sigemptyset(s)		__sigemptyset(s)
#define	sigfillset(s)		__sigfillset(s)
#define sigplusset(s, t)	__sigplusset(s, t)
#define sigminusset(s, t)	__sigminusset(s, t)
#endif /* _KERNEL */

#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
    defined(_NETBSD_SOURCE)
#include <sys/siginfo.h>
#endif

#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
#include <sys/ucontext.h>
#endif /* _XOPEN_SOURCE_EXTENDED || _XOPEN_SOURCE >= 500 || _NETBSD_SOURCE */

/*
 * Signal vector "template" used in sigaction call.
 */
struct	sigaction {
	union {
		void (*_sa_handler)(int);
#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
    defined(_NETBSD_SOURCE)
		void (*_sa_sigaction)(int, siginfo_t *, void *);
#endif
	} _sa_u;	/* signal handler */
	sigset_t sa_mask;		/* signal mask to apply */
	int	sa_flags;		/* see signal options below */
};

#define sa_handler _sa_u._sa_handler
#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
    defined(_NETBSD_SOURCE)
#define sa_sigaction _sa_u._sa_sigaction
#endif

#include <machine/signal.h>	/* sigcontext; codes for SIGILL, SIGFPE */

#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
#define SA_ONSTACK	0x0001	/* take signal on signal stack */
#define SA_RESTART	0x0002	/* restart system call on signal return */
#define SA_RESETHAND	0x0004	/* reset to SIG_DFL when taking signal */
#define SA_NODEFER	0x0010	/* don't mask the signal we're delivering */
#endif /* _XOPEN_SOURCE_EXTENDED || XOPEN_SOURCE >= 500 || _NETBSD_SOURCE */
/* Only valid for SIGCHLD. */
#define SA_NOCLDSTOP	0x0008	/* do not generate SIGCHLD on child stop */
#define SA_NOCLDWAIT	0x0020	/* do not generate zombies on unwaited child */
#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
    defined(_NETBSD_SOURCE)
#define SA_SIGINFO	0x0040	/* take sa_sigaction handler */
#endif /* (_POSIX_C_SOURCE - 0) >= 199309L || ... */
#if defined(_NETBSD_SOURCE)
#define	SA_NOKERNINFO	0x0080	/* siginfo does not print kernel info on tty */
#endif /*_NETBSD_SOURCE */
#ifdef _KERNEL
#define	SA_ALLBITS	0x00ff
#endif

/*
 * Flags for sigprocmask():
 */
#define	SIG_BLOCK	1	/* block specified signal set */
#define	SIG_UNBLOCK	2	/* unblock specified signal set */
#define	SIG_SETMASK	3	/* set specified signal set */

#if defined(_NETBSD_SOURCE)
typedef	void (*sig_t)(int);	/* type of signal function */
#endif

#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
/*
 * Flags used with stack_t/struct sigaltstack.
 */
#define SS_ONSTACK	0x0001	/* take signals on alternate stack */
#define SS_DISABLE	0x0004	/* disable taking signals on alternate stack */
#ifdef _KERNEL
#define	SS_ALLBITS	0x0005
#endif
#define	MINSIGSTKSZ	8192			/* minimum allowable stack */
#define	SIGSTKSZ	(MINSIGSTKSZ + 32768)	/* recommended stack size */
#endif /* _XOPEN_SOURCE_EXTENDED || _XOPEN_SOURCE >= 500 || _NETBSD_SOURCE */

#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
/*
 * Structure used in sigstack call.
 */
struct	sigstack {
	void	*ss_sp;			/* signal stack pointer */
	int	ss_onstack;		/* current status */
};
#endif /* _XOPEN_SOURCE_EXTENDED || _XOPEN_SOURCE >= 500 || _NETBSD_SOURCE */

#if defined(_NETBSD_SOURCE) && !defined(_KERNEL)
/*
 * Macro for converting signal number to a mask suitable for
 * sigblock().
 */
#define sigmask(n)	__sigmask(n)

#define	BADSIG		SIG_ERR
#endif /* _NETBSD_SOURCE */

#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
    defined(_NETBSD_SOURCE)
struct	sigevent {
	int	sigev_notify;
	int	sigev_signo;
	union sigval	sigev_value;
	void	(*sigev_notify_function)(union sigval);
	void /* pthread_attr_t */	*sigev_notify_attributes;
};

#define SIGEV_NONE	0
#define SIGEV_SIGNAL	1
#define SIGEV_THREAD	2
#if defined(_NETBSD_SOURCE)
#define SIGEV_SA	3
#endif
#endif /* (_POSIX_C_SOURCE - 0) >= 199309L || ... */

#endif	/* _POSIX_C_SOURCE || _XOPEN_SOURCE || _NETBSD_SOURCE */

/*
 * For historical reasons; programs expect signal's return value to be
 * defined by <sys/signal.h>.
 */
__BEGIN_DECLS
void	(*signal(int, void (*)(int)))(int);
void	(*bsd_signal(int, void (*)(int)))(int);
#if (_POSIX_C_SOURCE - 0) >= 200112L || defined(_NETBSD_SOURCE)
int	sigqueue(pid_t, int, const union sigval);
#endif
#if defined(_NETBSD_SOURCE)
int	sigqueueinfo(pid_t, const siginfo_t *);
#endif
__END_DECLS
#endif	/* !_SYS_SIGNAL_H_ */
/*	$NetBSD: limits.h,v 1.36 2016/03/08 05:02:55 christos Exp $	*/

/*
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)limits.h	8.2 (Berkeley) 1/4/94
 */

#ifndef _LIMITS_H_
#define	_LIMITS_H_

#include <sys/featuretest.h>

#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || \
    defined(_NETBSD_SOURCE)
#define	_POSIX_AIO_LISTIO_MAX	2
#define	_POSIX_AIO_MAX		1
#define	_POSIX_ARG_MAX		4096
#define	_POSIX_CHILD_MAX	25
#define	_POSIX_HOST_NAME_MAX	255
#define	_POSIX_LINK_MAX		8
#define	_POSIX_LOGIN_NAME_MAX	9
#define	_POSIX_MAX_CANON	255
#define	_POSIX_MAX_INPUT	255
#define	_POSIX_MQ_OPEN_MAX	8
#define	_POSIX_MQ_PRIO_MAX	32
#define	_POSIX_NAME_MAX		14
#define	_POSIX_NGROUPS_MAX	8
#define	_POSIX_OPEN_MAX		20
#define	_POSIX_PATH_MAX		256
#define	_POSIX_PIPE_BUF		512
#define	_POSIX_RE_DUP_MAX	255
#define	_POSIX_SSIZE_MAX	32767
#define	_POSIX_STREAM_MAX	8
#define	_POSIX_SYMLINK_MAX	255
#define	_POSIX_SYMLOOP_MAX	8

/*
 * We have not implemented these yet
 *
 * _POSIX_THREAD_ATTR_STACKADDR
 * _POSIX_THREAD_ATTR_STACKSIZE
 * _POSIX_THREAD_CPUTIME
 * _POSIX_THREAD_PRIORITY_SCHEDULING
 * _POSIX_THREAD_PRIO_INHERIT
 * _POSIX_THREAD_PRIO_PROTECT
 * _POSIX_THREAD_PROCESS_SHARED
 * _POSIX_THREAD_SAFE_FUNCTIONS
 * _POSIX_THREAD_SPORADIC_SERVER
 */

/*
 * The following 3 are defined in 
 * Open Group Base Specifications Issue 7
 */
#define	_POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
#define	_POSIX_THREAD_KEYS_MAX			128
#define	_POSIX_THREAD_THREADS_MAX		64

/*
 * These are the correct names, defined in terms of the above
 * except for PTHREAD_KEYS_MAX which is bigger than standard 
 * mandated minimum value _POSIX_THREAD_KEYS_MAX.
 */
#define	PTHREAD_DESTRUCTOR_ITERATIONS 	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define	PTHREAD_KEYS_MAX		256
/* Not yet: PTHREAD_STACK_MIN */
#define	PTHREAD_THREADS_MAX		_POSIX_THREAD_THREADS_MAX

#define	_POSIX_TIMER_MAX	32
#define	_POSIX_SEM_NSEMS_MAX	256
#define	_POSIX_SIGQUEUE_MAX	32
#define	_POSIX_REALTIME_SIGNALS	200112L
#define	_POSIX_CPUTIME		200112L
#define	_POSIX_THREAD_CPUTIME	200112L
#define	_POSIX_DELAYTIMER_MAX	32
#define	_POSIX_TTY_NAME_MAX	9
#define	_POSIX_TZNAME_MAX	6

#define	_POSIX2_BC_BASE_MAX	99
#define	_POSIX2_BC_DIM_MAX	2048
#define	_POSIX2_BC_SCALE_MAX	99
#define	_POSIX2_BC_STRING_MAX	1000
#define	_POSIX2_CHARCLASS_NAME_MAX	14
#define	_POSIX2_COLL_WEIGHTS_MAX	2
#define	_POSIX2_EXPR_NEST_MAX	32
#define	_POSIX2_LINE_MAX	2048
#define	_POSIX2_RE_DUP_MAX	255

/*
 * X/Open CAE Specifications,
 * adopted in IEEE Std 1003.1-2001 XSI.
 */
#if (_POSIX_C_SOURCE - 0) >= 200112L || defined(_XOPEN_SOURCE) || \
    defined(_NETBSD_SOURCE)
#define	_XOPEN_IOV_MAX		16
#define	_XOPEN_NAME_MAX		256
#define	_XOPEN_PATH_MAX		1024

#define PASS_MAX		128		/* Legacy */

#define CHARCLASS_NAME_MAX	14
#define NL_ARGMAX		9
#define NL_LANGMAX		14
#define NL_MSGMAX		32767
#define NL_NMAX			1
#define NL_SETMAX		255
#define NL_TEXTMAX		2048

	/* IEEE Std 1003.1-2001 TSF */
#define	_GETGR_R_SIZE_MAX	1024
#define	_GETPW_R_SIZE_MAX	1024

/* Always ensure that this is consistent with <stdio.h> */
#ifndef TMP_MAX
#define TMP_MAX			308915776	/* Legacy */
#endif
#endif /* _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE || _NETBSD_SOURCE */

#endif /* _POSIX_C_SOURCE || _XOPEN_SOURCE || _NETBSD_SOURCE */

#define MB_LEN_MAX		32	/* Allow ISO/IEC 2022 */

/*
 * X/Open Extended API set 2 (a.k.a. C063)
 * This hides unimplemented functions from GNU configure until
 * we are done implementing them.
 */
#if !defined(_INCOMPLETE_XOPEN_C063)
#define __stub_fexecve
#endif

#include <machine/limits.h>

#ifdef __CHAR_UNSIGNED__
# define CHAR_MIN     0
# define CHAR_MAX     UCHAR_MAX
#else
# define CHAR_MIN     SCHAR_MIN
# define CHAR_MAX     SCHAR_MAX
#endif

#include <sys/syslimits.h>

#endif /* !_LIMITS_H_ */
/*	$NetBSD: sysconf.c,v 1.37 2016/02/26 17:13:01 christos Exp $	*/

/*-
 * Copyright (c) 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Sean Eric Fagan of Cygnus Support.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)sysconf.c	8.2 (Berkeley) 3/20/94";
#else
__RCSID("$NetBSD: sysconf.c,v 1.37 2016/02/26 17:13:01 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */

#include "namespace.h"
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/resource.h>

#include <errno.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include <paths.h>
#include <pwd.h>
#include <pthread.h>

#ifdef __weak_alias
__weak_alias(sysconf,__sysconf)
#endif

/*
 * sysconf --
 *	get configurable system variables.
 *
 * XXX
 * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
 * not change during the lifetime of the calling process.  This would seem
 * to require that any change to system limits kill all running processes.
 * A workaround might be to cache the values when they are first retrieved
 * and then simply return the cached value on subsequent calls.  This is
 * less useful than returning up-to-date values, however.
 */
long
sysconf(int name)
{
	struct rlimit rl;
	size_t len;
	uint64_t mem;
	int mib[CTL_MAXNAME], value;
	unsigned int mib_len;
	struct clockinfo tmpclock;
	static int clk_tck;

	len = sizeof(value);

	/* Default length of the MIB */
	mib_len = 2;

	switch (name) {

/* 1003.1 */
	case _SC_ARG_MAX:
		mib[0] = CTL_KERN;
		mib[1] = KERN_ARGMAX;
		break;
	case _SC_CHILD_MAX:
		return (getrlimit(RLIMIT_NPROC, &rl) ? -1 : (long)rl.rlim_cur);
	case _O_SC_CLK_TCK:
		/*
		 * For applications compiled when CLK_TCK was a compile-time
		 * constant.
		 */
		return 100;
	case _SC_CLK_TCK:
		/*
		 * Has to be handled specially because it returns a
		 * struct clockinfo instead of an integer. Also, since
		 * this might be called often by some things that
		 * don't grok CLK_TCK can be a macro expanding to a
		 * function, cache the value.
		 */
		if (clk_tck == 0) {
			mib[0] = CTL_KERN;
			mib[1] = KERN_CLOCKRATE;
			len = sizeof(struct clockinfo);
			clk_tck = sysctl(mib, 2, &tmpclock, &len, NULL, 0)
			    == -1 ? -1 : tmpclock.hz;
		}
		return(clk_tck);
	case _SC_JOB_CONTROL:
		mib[0] = CTL_KERN;
		mib[1] = KERN_JOB_CONTROL;
		goto yesno;
	case _SC_NGROUPS_MAX:
		mib[0] = CTL_KERN;
		mib[1] = KERN_NGROUPS;
		break;
	case _SC_OPEN_MAX:
		return (getrlimit(RLIMIT_NOFILE, &rl) ? -1 : (long)rl.rlim_cur);
	case _SC_STREAM_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_STREAM_MAX;
		break;
	case _SC_TZNAME_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_TZNAME_MAX;
		break;
	case _SC_SAVED_IDS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_SAVED_IDS;
		goto yesno;
	case _SC_VERSION:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX1;
		break;

/* 1003.1b */
	case _SC_PAGESIZE:
		return _getpagesize();
	case _SC_FSYNC:
		mib[0] = CTL_KERN;
		mib[1] = KERN_FSYNC;
		goto yesno;
	case _SC_SYNCHRONIZED_IO:
		mib[0] = CTL_KERN;
		mib[1] = KERN_SYNCHRONIZED_IO;
		goto yesno;
	case _SC_MAPPED_FILES:
		mib[0] = CTL_KERN;
		mib[1] = KERN_MAPPED_FILES;
		goto yesno;
	case _SC_MEMLOCK:
		mib[0] = CTL_KERN;
		mib[1] = KERN_MEMLOCK;
		goto yesno;
	case _SC_MEMLOCK_RANGE:
		mib[0] = CTL_KERN;
		mib[1] = KERN_MEMLOCK_RANGE;
		goto yesno;
	case _SC_MEMORY_PROTECTION:
		mib[0] = CTL_KERN;
		mib[1] = KERN_MEMORY_PROTECTION;
		goto yesno;
	case _SC_MONOTONIC_CLOCK:
		mib[0] = CTL_KERN;
		mib[1] = KERN_MONOTONIC_CLOCK;
		goto yesno;
	case _SC_SEMAPHORES:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_SEMAPHORES;
		goto yesno;
	case _SC_TIMERS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_TIMERS;
		goto yesno;

/* 1003.1c */
	case _SC_LOGIN_NAME_MAX:
		mib[0] = CTL_KERN;
		mib[1] = KERN_LOGIN_NAME_MAX;
		break;
	case _SC_THREADS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_THREADS;
		goto yesno;

/* 1003.1j */
	case _SC_BARRIERS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_BARRIERS;
		goto yesno;
	case _SC_SPIN_LOCKS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_SPIN_LOCKS;
		goto yesno;
	/* Historical; Threads option in 1003.1-2001 */
	case _SC_READER_WRITER_LOCKS:
		mib[0] = CTL_KERN;
		mib[1] = KERN_POSIX_READER_WRITER_LOCKS;
		goto yesno;

/* 1003.2 */
	case _SC_BC_BASE_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_BC_BASE_MAX;
		break;
	case _SC_BC_DIM_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_BC_DIM_MAX;
		break;
	case _SC_BC_SCALE_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_BC_SCALE_MAX;
		break;
	case _SC_BC_STRING_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_BC_STRING_MAX;
		break;
	case _SC_COLL_WEIGHTS_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_COLL_WEIGHTS_MAX;
		break;
	case _SC_EXPR_NEST_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_EXPR_NEST_MAX;
		break;
	case _SC_LINE_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_LINE_MAX;
		break;
	case _SC_RE_DUP_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_RE_DUP_MAX;
		break;
	case _SC_2_VERSION:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_VERSION;
		break;
	case _SC_2_C_BIND:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_C_BIND;
		goto yesno;
	case _SC_2_C_DEV:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_C_DEV;
		goto yesno;
	case _SC_2_CHAR_TERM:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_CHAR_TERM;
		goto yesno;
	case _SC_2_FORT_DEV:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_FORT_DEV;
		goto yesno;
	case _SC_2_FORT_RUN:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_FORT_RUN;
		goto yesno;
	case _SC_2_LOCALEDEF:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_LOCALEDEF;
		goto yesno;
	case _SC_2_SW_DEV:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_SW_DEV;
		goto yesno;
	case _SC_2_UPE:
		mib[0] = CTL_USER;
		mib[1] = USER_POSIX2_UPE;
		goto yesno;

/* XPG 4.2 */
	case _SC_IOV_MAX:
		mib[0] = CTL_KERN;
		mib[1] = KERN_IOV_MAX;
		break;
	case _SC_XOPEN_SHM:
		mib[0] = CTL_KERN;
		mib[1] = KERN_SYSVIPC;
		mib[2] = KERN_SYSVIPC_SHM;
		mib_len = 3;
		goto yesno;

/* 1003.1-2001, XSI Option Group */
	case _SC_AIO_LISTIO_MAX:
		if (sysctlgetmibinfo("kern.aio_listio_max", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break; 
	case _SC_AIO_MAX:
		if (sysctlgetmibinfo("kern.aio_max", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break; 
	case _SC_ASYNCHRONOUS_IO:
		if (sysctlgetmibinfo("kern.posix_aio", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		goto yesno;
	case _SC_MESSAGE_PASSING:
		if (sysctlgetmibinfo("kern.posix_msg", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		goto yesno;
	case _SC_MQ_OPEN_MAX:
		if (sysctlgetmibinfo("kern.mqueue.mq_open_max", &mib[0],
		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break; 
	case _SC_MQ_PRIO_MAX:
		if (sysctlgetmibinfo("kern.mqueue.mq_prio_max", &mib[0],
		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break; 
	case _SC_PRIORITY_SCHEDULING:
		if (sysctlgetmibinfo("kern.posix_sched", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		goto yesno;
	case _SC_ATEXIT_MAX:
		mib[0] = CTL_USER;
		mib[1] = USER_ATEXIT_MAX;
		break;

/* 1003.1-2001, TSF */
	case _SC_GETGR_R_SIZE_MAX:
		return _GETGR_R_SIZE_MAX;
	case _SC_GETPW_R_SIZE_MAX:
		return _GETPW_R_SIZE_MAX;

/* Unsorted */
	case _SC_HOST_NAME_MAX:
		return MAXHOSTNAMELEN;
	case _SC_PASS_MAX:
		return _PASSWORD_LEN;
	case _SC_REGEXP:
		return _POSIX_REGEXP;
	case _SC_SHARED_MEMORY_OBJECTS:
		return _POSIX_SHARED_MEMORY_OBJECTS;
	case _SC_SHELL:
		return _POSIX_SHELL;
	case _SC_SPAWN:
		return _POSIX_SPAWN;
	case _SC_SYMLOOP_MAX:
		return MAXSYMLINKS;

yesno:		if (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1)
			return (-1);
		if (value == 0)
			return (-1);
		return (value);

/* Extensions */
	case _SC_NPROCESSORS_CONF:
		mib[0] = CTL_HW;
		mib[1] = HW_NCPU;
		break;
	case _SC_NPROCESSORS_ONLN:
		mib[0] = CTL_HW;
		mib[1] = HW_NCPUONLINE;
		break;

/* Linux/Solaris */
	case _SC_PHYS_PAGES:
		len = sizeof(mem);
		mib[0] = CTL_HW;
		mib[1] = HW_PHYSMEM64;
		return sysctl(mib, 2, &mem, &len, NULL, 0) == -1 ? -1 : 
		    (long)(mem / _getpagesize()); 

/* Native */
	case _SC_SCHED_RT_TS:
		if (sysctlgetmibinfo("kern.sched.rtts", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))      
			return -1;              
		break;
	case _SC_SCHED_PRI_MIN:
		if (sysctlgetmibinfo("kern.sched.pri_min", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break;
	case _SC_SCHED_PRI_MAX:
		if (sysctlgetmibinfo("kern.sched.pri_max", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))
			return -1;
		break;
	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
		return _POSIX_THREAD_DESTRUCTOR_ITERATIONS;
	case _SC_THREAD_KEYS_MAX:
		return _POSIX_THREAD_KEYS_MAX;
	case _SC_THREAD_STACK_MIN:
		return PTHREAD_STACK_MIN;
	case _SC_THREAD_THREADS_MAX:
		if (sysctlgetmibinfo("kern.maxproc", &mib[0], &mib_len,
		    NULL, NULL, NULL, SYSCTL_VERSION))	/* XXX */
			return -1;
		goto yesno;
	case _SC_THREAD_ATTR_STACKADDR:
		return _POSIX_THREAD_ATTR_STACKADDR;
	case _SC_THREAD_ATTR_STACKSIZE:
		return _POSIX_THREAD_ATTR_STACKSIZE;
	case _SC_THREAD_SAFE_FUNCTIONS:
		return _POSIX_THREAD_SAFE_FUNCTIONS;
	case _SC_THREAD_PRIO_PROTECT:
		return _POSIX_THREAD_PRIO_PROTECT;
	case _SC_THREAD_PRIORITY_SCHEDULING:
	case _SC_THREAD_PRIO_INHERIT:
	case _SC_THREAD_PROCESS_SHARED:
		return -1;
	case _SC_TTY_NAME_MAX:
		return pathconf(_PATH_DEV, _PC_NAME_MAX);
	case _SC_TIMER_MAX:
		return _POSIX_TIMER_MAX;
	case _SC_SEM_NSEMS_MAX:
		return _POSIX_SEM_NSEMS_MAX;
	case _SC_CPUTIME:
		return _POSIX_CPUTIME;
	case _SC_THREAD_CPUTIME:
		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);
	}
	return (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1 ? -1 : value); 
}
/*	$NetBSD: kern_sig.c,v 1.327 2016/04/28 00:37:39 christos Exp $	*/

/*-
 * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Andrew Doran.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1982, 1986, 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)kern_sig.c	8.14 (Berkeley) 5/14/95
 */

/*
 * Signal subsystem.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.327 2016/04/28 00:37:39 christos Exp $");

#include "opt_ptrace.h"
#include "opt_dtrace.h"
#include "opt_compat_sunos.h"
#include "opt_compat_netbsd.h"
#include "opt_compat_netbsd32.h"
#include "opt_pax.h"

#define	SIGPROP		/* include signal properties table */
#include <sys/param.h>
#include <sys/signalvar.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/wait.h>
#include <sys/ktrace.h>
#include <sys/syslog.h>
#include <sys/filedesc.h>
#include <sys/file.h>
#include <sys/pool.h>
#include <sys/ucontext.h>
#include <sys/exec.h>
#include <sys/kauth.h>
#include <sys/acct.h>
#include <sys/callout.h>
#include <sys/atomic.h>
#include <sys/cpu.h>
#include <sys/module.h>
#include <sys/sdt.h>

#ifdef PAX_SEGVGUARD
#include <sys/pax.h>
#endif /* PAX_SEGVGUARD */

#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;

sigset_t		contsigmask	__cacheline_aligned;
static sigset_t		stopsigmask	__cacheline_aligned;
sigset_t		sigcantmask	__cacheline_aligned;

static void	ksiginfo_exechook(struct proc *, void *);
static void	proc_stop_callout(void *);
static int	sigchecktrace(void);
static int	sigpost(struct lwp *, sig_t, int, int);
static int	sigput(sigpend_t *, struct proc *, ksiginfo_t *);
static int	sigunwait(struct proc *, const ksiginfo_t *);
static void	sigswitch(bool, int, int);

static void	sigacts_poolpage_free(struct pool *, void *);
static void	*sigacts_poolpage_alloc(struct pool *, int);

void (*sendsig_sigcontext_vec)(const struct ksiginfo *, const sigset_t *);
int (*coredump_vec)(struct lwp *, const char *) =
    (int (*)(struct lwp *, const char *))enosys;

/*
 * DTrace SDT provider definitions
 */
SDT_PROVIDER_DECLARE(proc);
SDT_PROBE_DEFINE3(proc, kernel, , signal__send,
    "struct lwp *", 	/* target thread */
    "struct proc *", 	/* target process */
    "int");		/* signal */
SDT_PROBE_DEFINE3(proc, kernel, , signal__discard,
    "struct lwp *",	/* target thread */
    "struct proc *",	/* target process */
    "int");  		/* signal */
SDT_PROBE_DEFINE3(proc, kernel, , signal__handle,
    "int", 		/* signal */
    "ksiginfo_t *", 	/* signal info */
    "void (*)(void)");	/* handler address */


static struct pool_allocator sigactspool_allocator = {
	.pa_alloc = sigacts_poolpage_alloc,
	.pa_free = sigacts_poolpage_free
};

#ifdef DEBUG
int	kern_logsigexit = 1;
#else
int	kern_logsigexit = 0;
#endif

static const char logcoredump[] =
    "pid %d (%s), uid %d: exited on signal %d (core dumped)\n";
static const char lognocoredump[] =
    "pid %d (%s), uid %d: exited on signal %d (core not dumped, err = %d)\n";

static kauth_listener_t signal_listener;

static int
signal_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
    void *arg0, void *arg1, void *arg2, void *arg3)
{
	struct proc *p;
	int result, signum;

	result = KAUTH_RESULT_DEFER;
	p = arg0;
	signum = (int)(unsigned long)arg1;

	if (action != KAUTH_PROCESS_SIGNAL)
		return result;

	if (kauth_cred_uidmatch(cred, p->p_cred) ||
	    (signum == SIGCONT && (curproc->p_session == p->p_session)))
		result = KAUTH_RESULT_ALLOW;

	return result;
}

/*
 * signal_init:
 *
 *	Initialize global signal-related data structures.
 */
void
signal_init(void)
{

	sigactspool_allocator.pa_pagesz = (PAGE_SIZE)*2;

	sigacts_cache = pool_cache_init(sizeof(struct sigacts), 0, 0, 0,
	    "sigacts", sizeof(struct sigacts) > PAGE_SIZE ?
	    &sigactspool_allocator : NULL, IPL_NONE, NULL, NULL, NULL);
	ksiginfo_cache = pool_cache_init(sizeof(ksiginfo_t), 0, 0, 0,
	    "ksiginfo", NULL, IPL_VM, NULL, NULL, NULL);

	exechook_establish(ksiginfo_exechook, NULL);

	callout_init(&proc_stop_ch, CALLOUT_MPSAFE);
	callout_setfunc(&proc_stop_ch, proc_stop_callout, NULL);

	signal_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
	    signal_listener_cb, NULL);
}

/*
 * sigacts_poolpage_alloc:
 *
 *	Allocate a page for the sigacts memory pool.
 */
static void *
sigacts_poolpage_alloc(struct pool *pp, int flags)
{

	return (void *)uvm_km_alloc(kernel_map,
	    PAGE_SIZE * 2, PAGE_SIZE * 2,
	    ((flags & PR_WAITOK) ? 0 : UVM_KMF_NOWAIT | UVM_KMF_TRYLOCK)
	    | UVM_KMF_WIRED);
}

/*
 * sigacts_poolpage_free:
 *
 *	Free a page on behalf of the sigacts memory pool.
 */
static void
sigacts_poolpage_free(struct pool *pp, void *v)
{

	uvm_km_free(kernel_map, (vaddr_t)v, PAGE_SIZE * 2, UVM_KMF_WIRED);
}

/*
 * sigactsinit:
 *
 *	Create an initial sigacts structure, using the same signal state
 *	as of specified process.  If 'share' is set, share the sigacts by
 *	holding a reference, otherwise just copy it from parent.
 */
struct sigacts *
sigactsinit(struct proc *pp, int share)
{
	struct sigacts *ps = pp->p_sigacts, *ps2;

	if (__predict_false(share)) {
		atomic_inc_uint(&ps->sa_refcnt);
		return ps;
	}
	ps2 = pool_cache_get(sigacts_cache, PR_WAITOK);
	mutex_init(&ps2->sa_mutex, MUTEX_DEFAULT, IPL_SCHED);
	ps2->sa_refcnt = 1;

	mutex_enter(&ps->sa_mutex);
	memcpy(ps2->sa_sigdesc, ps->sa_sigdesc, sizeof(ps2->sa_sigdesc));
	mutex_exit(&ps->sa_mutex);
	return ps2;
}

/*
 * sigactsunshare:
 *
 *	Make this process not share its sigacts, maintaining all signal state.
 */
void
sigactsunshare(struct proc *p)
{
	struct sigacts *ps, *oldps = p->p_sigacts;

	if (__predict_true(oldps->sa_refcnt == 1))
		return;

	ps = pool_cache_get(sigacts_cache, PR_WAITOK);
	mutex_init(&ps->sa_mutex, MUTEX_DEFAULT, IPL_SCHED);
	memcpy(ps->sa_sigdesc, oldps->sa_sigdesc, sizeof(ps->sa_sigdesc));
	ps->sa_refcnt = 1;

	p->p_sigacts = ps;
	sigactsfree(oldps);
}

/*
 * sigactsfree;
 *
 *	Release a sigacts structure.
 */
void
sigactsfree(struct sigacts *ps)
{

	if (atomic_dec_uint_nv(&ps->sa_refcnt) == 0) {
		mutex_destroy(&ps->sa_mutex);
		pool_cache_put(sigacts_cache, ps);
	}
}

/*
 * siginit:
 *
 *	Initialize signal state for process 0; set to ignore signals that
 *	are ignored by default and disable the signal stack.  Locking not
 *	required as the system is still cold.
 */
void
siginit(struct proc *p)
{
	struct lwp *l;
	struct sigacts *ps;
	int signo, prop;

	ps = p->p_sigacts;
	sigemptyset(&contsigmask);
	sigemptyset(&stopsigmask);
	sigemptyset(&sigcantmask);
	for (signo = 1; signo < NSIG; signo++) {
		prop = sigprop[signo];
		if (prop & SA_CONT)
			sigaddset(&contsigmask, signo);
		if (prop & SA_STOP)
			sigaddset(&stopsigmask, signo);
		if (prop & SA_CANTMASK)
			sigaddset(&sigcantmask, signo);
		if (prop & SA_IGNORE && signo != SIGCONT)
			sigaddset(&p->p_sigctx.ps_sigignore, signo);
		sigemptyset(&SIGACTION_PS(ps, signo).sa_mask);
		SIGACTION_PS(ps, signo).sa_flags = SA_RESTART;
	}
	sigemptyset(&p->p_sigctx.ps_sigcatch);
	p->p_sflag &= ~PS_NOCLDSTOP;

	ksiginfo_queue_init(&p->p_sigpend.sp_info);
	sigemptyset(&p->p_sigpend.sp_set);

	/*
	 * Reset per LWP state.
	 */
	l = LIST_FIRST(&p->p_lwps);
	l->l_sigwaited = NULL;
	l->l_sigstk.ss_flags = SS_DISABLE;
	l->l_sigstk.ss_size = 0;
	l->l_sigstk.ss_sp = 0;
	ksiginfo_queue_init(&l->l_sigpend.sp_info);
	sigemptyset(&l->l_sigpend.sp_set);

	/* One reference. */
	ps->sa_refcnt = 1;
}

/*
 * execsigs:
 *
 *	Reset signals for an exec of the specified process.
 */
void
execsigs(struct proc *p)
{
	struct sigacts *ps;
	struct lwp *l;
	int signo, prop;
	sigset_t tset;
	ksiginfoq_t kq;

	KASSERT(p->p_nlwps == 1);

	sigactsunshare(p);
	ps = p->p_sigacts;

	/*
	 * Reset caught signals.  Held signals remain held through
	 * l->l_sigmask (unless they were caught, and are now ignored
	 * by default).
	 *
	 * No need to lock yet, the process has only one LWP and
	 * at this point the sigacts are private to the process.
	 */
	sigemptyset(&tset);
	for (signo = 1; signo < NSIG; signo++) {
		if (sigismember(&p->p_sigctx.ps_sigcatch, signo)) {
			prop = sigprop[signo];
			if (prop & SA_IGNORE) {
				if ((prop & SA_CONT) == 0)
					sigaddset(&p->p_sigctx.ps_sigignore,
					    signo);
				sigaddset(&tset, signo);
			}
			SIGACTION_PS(ps, signo).sa_handler = SIG_DFL;
		}
		sigemptyset(&SIGACTION_PS(ps, signo).sa_mask);
		SIGACTION_PS(ps, signo).sa_flags = SA_RESTART;
	}
	ksiginfo_queue_init(&kq);

	mutex_enter(p->p_lock);
	sigclearall(p, &tset, &kq);
	sigemptyset(&p->p_sigctx.ps_sigcatch);

	/*
	 * Reset no zombies if child dies flag as Solaris does.
	 */
	p->p_flag &= ~(PK_NOCLDWAIT | PK_CLDSIGIGN);
	if (SIGACTION_PS(ps, SIGCHLD).sa_handler == SIG_IGN)
		SIGACTION_PS(ps, SIGCHLD).sa_handler = SIG_DFL;

	/*
	 * Reset per-LWP state.
	 */
	l = LIST_FIRST(&p->p_lwps);
	l->l_sigwaited = NULL;
	l->l_sigstk.ss_flags = SS_DISABLE;
	l->l_sigstk.ss_size = 0;
	l->l_sigstk.ss_sp = 0;
	ksiginfo_queue_init(&l->l_sigpend.sp_info);
	sigemptyset(&l->l_sigpend.sp_set);
	mutex_exit(p->p_lock);

	ksiginfo_queue_drain(&kq);
}

/*
 * ksiginfo_exechook:
 *
 *	Free all pending ksiginfo entries from a process on exec.
 *	Additionally, drain any unused ksiginfo structures in the
 *	system back to the pool.
 *
 *	XXX This should not be a hook, every process has signals.
 */
static void
ksiginfo_exechook(struct proc *p, void *v)
{
	ksiginfoq_t kq;

	ksiginfo_queue_init(&kq);

	mutex_enter(p->p_lock);
	sigclearall(p, NULL, &kq);
	mutex_exit(p->p_lock);

	ksiginfo_queue_drain(&kq);
}

/*
 * ksiginfo_alloc:
 *
 *	Allocate a new ksiginfo structure from the pool, and optionally copy
 *	an existing one.  If the existing ksiginfo_t is from the pool, and
 *	has not been queued somewhere, then just return it.  Additionally,
 *	if the existing ksiginfo_t does not contain any information beyond
 *	the signal number, then just return it.
 */
ksiginfo_t *
ksiginfo_alloc(struct proc *p, ksiginfo_t *ok, int flags)
{
	ksiginfo_t *kp;

	if (ok != NULL) {
		if ((ok->ksi_flags & (KSI_QUEUED | KSI_FROMPOOL)) ==
		    KSI_FROMPOOL)
			return ok;
		if (KSI_EMPTY_P(ok))
			return ok;
	}

	kp = pool_cache_get(ksiginfo_cache, flags);
	if (kp == NULL) {
#ifdef DIAGNOSTIC
		printf("Out of memory allocating ksiginfo for pid %d\n",
		    p->p_pid);
#endif
		return NULL;
	}

	if (ok != NULL) {
		memcpy(kp, ok, sizeof(*kp));
		kp->ksi_flags &= ~KSI_QUEUED;
	} else
		KSI_INIT_EMPTY(kp);

	kp->ksi_flags |= KSI_FROMPOOL;

	return kp;
}

/*
 * ksiginfo_free:
 *
 *	If the given ksiginfo_t is from the pool and has not been queued,
 *	then free it.
 */
void
ksiginfo_free(ksiginfo_t *kp)
{

	if ((kp->ksi_flags & (KSI_QUEUED | KSI_FROMPOOL)) != KSI_FROMPOOL)
		return;
	pool_cache_put(ksiginfo_cache, kp);
}

/*
 * ksiginfo_queue_drain:
 *
 *	Drain a non-empty ksiginfo_t queue.
 */
void
ksiginfo_queue_drain0(ksiginfoq_t *kq)
{
	ksiginfo_t *ksi;

	KASSERT(!TAILQ_EMPTY(kq));

	while (!TAILQ_EMPTY(kq)) {
		ksi = TAILQ_FIRST(kq);
		TAILQ_REMOVE(kq, ksi, ksi_list);
		pool_cache_put(ksiginfo_cache, ksi);
	}
}

static int
siggetinfo(sigpend_t *sp, ksiginfo_t *out, int signo)
{
	ksiginfo_t *ksi;

	if (sp == NULL)
		goto out;

	/* Find siginfo and copy it out. */
	int ret = 0;
	TAILQ_FOREACH(ksi, &sp->sp_info, ksi_list) {
		if (ksi->ksi_signo != signo)
			continue;
		ret += 1;
		if (ret >= 2) continue; 
		TAILQ_REMOVE(&sp->sp_info, ksi, ksi_list);
		KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0);
		KASSERT((ksi->ksi_flags & KSI_QUEUED) != 0);
		ksi->ksi_flags &= ~KSI_QUEUED;
		if (out != NULL) {
			memcpy(out, ksi, sizeof(*out));
			out->ksi_flags &= ~(KSI_FROMPOOL | KSI_QUEUED);
		}
		ksiginfo_free(ksi);
	}
	return ret;

out:
	/* If there is no siginfo, then manufacture it. */
	if (out != NULL) {
		KSI_INIT(out);
		out->ksi_info._signo = signo;
		out->ksi_info._code = SI_NOINFO;
	}
	return 0;
}

/*
 * sigget:
 *
 *	Fetch the first pending signal from a set.  Optionally, also fetch
 *	or manufacture a ksiginfo element.  Returns the number of the first
 *	pending signal, or zero.
 */ 
int
sigget(sigpend_t *sp, ksiginfo_t *out, int signo, const sigset_t *mask)
{
	sigset_t tset;
	int ret = 0;

	/* If there's no pending set, the signal is from the debugger. */
	if (sp == NULL)
		goto out;

	/* Construct mask from signo, and 'mask'. */
	if (signo == 0) {
		if (mask != NULL) {
			tset = *mask;
			__sigandset(&sp->sp_set, &tset);
		} else
			tset = sp->sp_set;

		/* If there are no signals pending - return. */
		if ((signo = firstsig(&tset)) == 0)
			goto out;
	} else {
		KASSERT(sigismember(&sp->sp_set, signo));
	}

out:
	ret = siggetinfo(sp, out, signo);
	if (ret == 1) sigdelset(&sp->sp_set, signo);
	return signo;
}

/*
 * sigput:
 *
 *	Append a new ksiginfo element to the list of pending ksiginfo's.
 */
static int
sigput(sigpend_t *sp, struct proc *p, ksiginfo_t *ksi)
{
	ksiginfo_t *kp;

	KASSERT(mutex_owned(p->p_lock));
	KASSERT((ksi->ksi_flags & KSI_QUEUED) == 0);

	sigaddset(&sp->sp_set, ksi->ksi_signo);

	/*
	 * If there is no siginfo, we are done.
	 */
	if (KSI_EMPTY_P(ksi))
		return 0;

	KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0);

	int cnt = 0;
#ifdef notyet	/* XXX: QUEUING */
	if (ksi->ksi_signo < SIGRTMIN)
#endif
	{
		TAILQ_FOREACH(kp, &sp->sp_info, ksi_list) {
			cnt += 1;
			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 (cnt >= SIGQUEUE_MAX) {
		printf("no resource to enqueue\n");
		return EAGAIN;
	}
	ksi->ksi_flags |= KSI_QUEUED;
	TAILQ_INSERT_TAIL(&sp->sp_info, ksi, ksi_list);
	
	return 0;
}

/*
 * sigclear:
 *
 *	Clear all pending signals in the specified set.
 */
void
sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq)
{
	ksiginfo_t *ksi, *next;

	if (mask == NULL)
		sigemptyset(&sp->sp_set);
	else
		sigminusset(mask, &sp->sp_set);

	TAILQ_FOREACH_SAFE(ksi, &sp->sp_info, ksi_list, next) {
		if (mask == NULL || sigismember(mask, ksi->ksi_signo)) {
			TAILQ_REMOVE(&sp->sp_info, ksi, ksi_list);
			KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0);
			KASSERT((ksi->ksi_flags & KSI_QUEUED) != 0);
			TAILQ_INSERT_TAIL(kq, ksi, ksi_list);
		}
	}
}

/*
 * sigclearall:
 *
 *	Clear all pending signals in the specified set from a process and
 *	its LWPs.
 */
void
sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq)
{
	struct lwp *l;

	KASSERT(mutex_owned(p->p_lock));

	sigclear(&p->p_sigpend, mask, kq);

	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
		sigclear(&l->l_sigpend, mask, kq);
	}
}

/*
 * sigispending:
 *
 *	Return the first signal number if there are pending signals for the
 *	current LWP.  May be called unlocked provided that LW_PENDSIG is set,
 *	and that the signal has been posted to the appopriate queue before
 *	LW_PENDSIG is set.
 */ 
int
sigispending(struct lwp *l, int signo)
{
	struct proc *p = l->l_proc;
	sigset_t tset;

	membar_consumer();

	tset = l->l_sigpend.sp_set;
	sigplusset(&p->p_sigpend.sp_set, &tset);
	sigminusset(&p->p_sigctx.ps_sigignore, &tset);
	sigminusset(&l->l_sigmask, &tset);

	if (signo == 0) {
		return firstsig(&tset);
	}
	return sigismember(&tset, signo) ? signo : 0;
}

void
getucontext(struct lwp *l, ucontext_t *ucp)
{
	struct proc *p = l->l_proc;

	KASSERT(mutex_owned(p->p_lock));

	ucp->uc_flags = 0;
	ucp->uc_link = l->l_ctxlink;
	ucp->uc_sigmask = l->l_sigmask;
	ucp->uc_flags |= _UC_SIGMASK;

	/*
	 * The (unsupplied) definition of the `current execution stack'
	 * in the System V Interface Definition appears to allow returning
	 * the main context stack.
	 */
	if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) {
		ucp->uc_stack.ss_sp = (void *)l->l_proc->p_stackbase;
		ucp->uc_stack.ss_size = ctob(l->l_proc->p_vmspace->vm_ssize);
		ucp->uc_stack.ss_flags = 0;	/* XXX, def. is Very Fishy */
	} else {
		/* Simply copy alternate signal execution stack. */
		ucp->uc_stack = l->l_sigstk;
	}
	ucp->uc_flags |= _UC_STACK;
	mutex_exit(p->p_lock);
	cpu_getmcontext(l, &ucp->uc_mcontext, &ucp->uc_flags);
	mutex_enter(p->p_lock);
}

int
setucontext(struct lwp *l, const ucontext_t *ucp)
{
	struct proc *p = l->l_proc;
	int error;

	KASSERT(mutex_owned(p->p_lock));

	if ((ucp->uc_flags & _UC_SIGMASK) != 0) {
		error = sigprocmask1(l, SIG_SETMASK, &ucp->uc_sigmask, NULL);
		if (error != 0)
			return error;
	}

	mutex_exit(p->p_lock);
	error = cpu_setmcontext(l, &ucp->uc_mcontext, ucp->uc_flags);
	mutex_enter(p->p_lock);
	if (error != 0)
		return (error);

	l->l_ctxlink = ucp->uc_link;

	/*
	 * If there was stack information, update whether or not we are
	 * still running on an alternate signal stack.
	 */
	if ((ucp->uc_flags & _UC_STACK) != 0) {
		if (ucp->uc_stack.ss_flags & SS_ONSTACK)
			l->l_sigstk.ss_flags |= SS_ONSTACK;
		else
			l->l_sigstk.ss_flags &= ~SS_ONSTACK;
	}

	return 0;
}

/*
 * killpg1: common code for kill process group/broadcast kill.
 */
int
killpg1(struct lwp *l, ksiginfo_t *ksi, int pgid, int all)
{
	struct proc	*p, *cp;
	kauth_cred_t	pc;
	struct pgrp	*pgrp;
	int		nfound;
	int		signo = ksi->ksi_signo;

	cp = l->l_proc;
	pc = l->l_cred;
	nfound = 0;

	mutex_enter(proc_lock);
	if (all) {
		/*
		 * Broadcast.
		 */
		PROCLIST_FOREACH(p, &allproc) {
			if (p->p_pid <= 1 || p == cp ||
			    (p->p_flag & PK_SYSTEM) != 0)
				continue;
			mutex_enter(p->p_lock);
			if (kauth_authorize_process(pc,
			    KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signo), NULL,
			    NULL) == 0) {
				nfound++;
				if (signo)
					kpsignal2(p, ksi);
			}
			mutex_exit(p->p_lock);
		}
	} else {
		if (pgid == 0)
			/* Zero pgid means send to my process group. */
			pgrp = cp->p_pgrp;
		else {
			pgrp = pgrp_find(pgid);
			if (pgrp == NULL)
				goto out;
		}
		LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
			if (p->p_pid <= 1 || p->p_flag & PK_SYSTEM)
				continue;
			mutex_enter(p->p_lock);
			if (kauth_authorize_process(pc, KAUTH_PROCESS_SIGNAL,
			    p, KAUTH_ARG(signo), NULL, NULL) == 0) {
				nfound++;
				if (signo && P_ZOMBIE(p) == 0)
					kpsignal2(p, ksi);
			}
			mutex_exit(p->p_lock);
		}
	}
out:
	mutex_exit(proc_lock);
	return nfound ? 0 : ESRCH;
}

/*
 * Send a signal to a process group.  If checktty is set, limit to members
 * which have a controlling terminal.
 */
void
pgsignal(struct pgrp *pgrp, int sig, int checkctty)
{
	ksiginfo_t ksi;

	KASSERT(!cpu_intr_p());
	KASSERT(mutex_owned(proc_lock));

	KSI_INIT_EMPTY(&ksi);
	ksi.ksi_signo = sig;
	kpgsignal(pgrp, &ksi, NULL, checkctty);
}

void
kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
{
	struct proc *p;

	KASSERT(!cpu_intr_p());
	KASSERT(mutex_owned(proc_lock));
	KASSERT(pgrp != NULL);

	LIST_FOREACH(p, &pgrp->pg_members, p_pglist)
		if (checkctty == 0 || p->p_lflag & PL_CONTROLT)
			kpsignal(p, ksi, data);
}

/*
 * Send a signal caused by a trap to the current LWP.  If it will be caught
 * immediately, deliver it with correct code.  Otherwise, post it normally.
 */
void
trapsignal(struct lwp *l, ksiginfo_t *ksi)
{
	struct proc	*p;
	struct sigacts	*ps;
	int signo = ksi->ksi_signo;
	sigset_t *mask;

	KASSERT(KSI_TRAP_P(ksi));

	ksi->ksi_lid = l->l_lid;
	p = l->l_proc;

	KASSERT(!cpu_intr_p());
	mutex_enter(proc_lock);
	mutex_enter(p->p_lock);
	mask = &l->l_sigmask;
	ps = p->p_sigacts;

	if ((p->p_slflag & PSL_TRACED) == 0 &&
	    sigismember(&p->p_sigctx.ps_sigcatch, signo) &&
	    !sigismember(mask, signo)) {
		mutex_exit(proc_lock);
		l->l_ru.ru_nsignals++;
		kpsendsig(l, ksi, mask);
		mutex_exit(p->p_lock);
		if (ktrpoint(KTR_PSIG)) {
			ktrpsig(signo, SIGACTION_PS(ps, signo).sa_handler,
			    mask, ksi);
		}
	} else {
		/* XXX for core dump/debugger */
		p->p_sigctx.ps_lwp = l->l_lid;
		p->p_sigctx.ps_signo = ksi->ksi_signo;
		p->p_sigctx.ps_code = ksi->ksi_trap;
		kpsignal2(p, ksi);
		mutex_exit(p->p_lock);
		mutex_exit(proc_lock);
	}
}

/*
 * Fill in signal information and signal the parent for a child status change.
 */
void
child_psignal(struct proc *p, int mask)
{
	ksiginfo_t ksi;
	struct proc *q;
	int xsig;

	KASSERT(mutex_owned(proc_lock));
	KASSERT(mutex_owned(p->p_lock));

	xsig = p->p_xsig;

	KSI_INIT(&ksi);
	ksi.ksi_signo = SIGCHLD;
	ksi.ksi_code = (xsig == SIGCONT ? CLD_CONTINUED : CLD_STOPPED);
	ksi.ksi_pid = p->p_pid;
	ksi.ksi_uid = kauth_cred_geteuid(p->p_cred);
	ksi.ksi_status = xsig;
	ksi.ksi_utime = p->p_stats->p_ru.ru_utime.tv_sec;
	ksi.ksi_stime = p->p_stats->p_ru.ru_stime.tv_sec;

	q = p->p_pptr;

	mutex_exit(p->p_lock);
	mutex_enter(q->p_lock);

	if ((q->p_sflag & mask) == 0)
		kpsignal2(q, &ksi);

	mutex_exit(q->p_lock);
	mutex_enter(p->p_lock);
}

void
psignal(struct proc *p, int signo)
{
	ksiginfo_t ksi;

	KASSERT(!cpu_intr_p());
	KASSERT(mutex_owned(proc_lock));

	KSI_INIT_EMPTY(&ksi);
	ksi.ksi_signo = signo;
	mutex_enter(p->p_lock);
	kpsignal2(p, &ksi);
	mutex_exit(p->p_lock);
}

void
kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
{
	fdfile_t *ff;
	file_t *fp;
	fdtab_t *dt;

	KASSERT(!cpu_intr_p());
	KASSERT(mutex_owned(proc_lock));

	if ((p->p_sflag & PS_WEXIT) == 0 && data) {
		size_t fd;
		filedesc_t *fdp = p->p_fd;

		/* XXXSMP locking */
		ksi->ksi_fd = -1;
		dt = fdp->fd_dt;
		for (fd = 0; fd < dt->dt_nfiles; fd++) {
			if ((ff = dt->dt_ff[fd]) == NULL)
				continue;
			if ((fp = ff->ff_file) == NULL)
				continue;
			if (fp->f_data == data) {
				ksi->ksi_fd = fd;
				break;
			}
		}
	}
	mutex_enter(p->p_lock);
	kpsignal2(p, ksi);
	mutex_exit(p->p_lock);
}

/*
 * sigismasked:
 *
 *	Returns true if signal is ignored or masked for the specified LWP.
 */
int
sigismasked(struct lwp *l, int sig)
{
	struct proc *p = l->l_proc;

	return sigismember(&p->p_sigctx.ps_sigignore, sig) ||
	    sigismember(&l->l_sigmask, sig);
}

/*
 * sigpost:
 *
 *	Post a pending signal to an LWP.  Returns non-zero if the LWP may
 *	be able to take the signal.
 */
static int
sigpost(struct lwp *l, sig_t action, int prop, int sig)
{
	int rv, masked;
	struct proc *p = l->l_proc;

	KASSERT(mutex_owned(p->p_lock));

	/*
	 * If the LWP is on the way out, sigclear() will be busy draining all
	 * pending signals.  Don't give it more.
	 */
	if (l->l_refcnt == 0)
		return 0;

	SDT_PROBE(proc, kernel, , signal__send, l, p, sig, 0, 0);

	/*
	 * Have the LWP check for signals.  This ensures that even if no LWP
	 * is found to take the signal immediately, it should be taken soon.
	 */
	lwp_lock(l);
	l->l_flag |= LW_PENDSIG;

	/*
	 * SIGCONT can be masked, but if LWP is stopped, it needs restart.
	 * Note: SIGKILL and SIGSTOP cannot be masked.
	 */
	masked = sigismember(&l->l_sigmask, sig);
	if (masked && ((prop & SA_CONT) == 0 || l->l_stat != LSSTOP)) {
		lwp_unlock(l);
		return 0;
	}

	/*
	 * If killing the process, make it run fast.
	 */
	if (__predict_false((prop & SA_KILL) != 0) &&
	    action == SIG_DFL && l->l_priority < MAXPRI_USER) {
		KASSERT(l->l_class == SCHED_OTHER);
		lwp_changepri(l, MAXPRI_USER);
	}

	/*
	 * If the LWP is running or on a run queue, then we win.  If it's
	 * sleeping interruptably, wake it and make it take the signal.  If
	 * the sleep isn't interruptable, then the chances are it will get
	 * to see the signal soon anyhow.  If suspended, it can't take the
	 * signal right now.  If it's LWP private or for all LWPs, save it
	 * for later; otherwise punt.
	 */
	rv = 0;

	switch (l->l_stat) {
	case LSRUN:
	case LSONPROC:
		lwp_need_userret(l);
		rv = 1;
		break;

	case LSSLEEP:
		if ((l->l_flag & LW_SINTR) != 0) {
			/* setrunnable() will release the lock. */
			setrunnable(l);
			return 1;
		}
		break;

	case LSSUSPENDED:
		if ((prop & SA_KILL) != 0 && (l->l_flag & LW_WCORE) != 0) {
			/* lwp_continue() will release the lock. */
			lwp_continue(l);
			return 1;
		}
		break;

	case LSSTOP:
		if ((prop & SA_STOP) != 0)
			break;

		/*
		 * If the LWP is stopped and we are sending a continue
		 * signal, then start it again.
		 */
		if ((prop & SA_CONT) != 0) {
			if (l->l_wchan != NULL) {
				l->l_stat = LSSLEEP;
				p->p_nrlwps++;
				rv = 1;
				break;
			}
			/* setrunnable() will release the lock. */
			setrunnable(l);
			return 1;
		} else if (l->l_wchan == NULL || (l->l_flag & LW_SINTR) != 0) {
			/* setrunnable() will release the lock. */
			setrunnable(l);
			return 1;
		}
		break;

	default:
		break;
	}

	lwp_unlock(l);
	return rv;
}

/*
 * Notify an LWP that it has a pending signal.
 */
void
signotify(struct lwp *l)
{
	KASSERT(lwp_locked(l, NULL));

	l->l_flag |= LW_PENDSIG;
	lwp_need_userret(l);
}

/*
 * Find an LWP within process p that is waiting on signal ksi, and hand
 * it on.
 */
static int
sigunwait(struct proc *p, const ksiginfo_t *ksi)
{
	struct lwp *l;
	int signo;

	KASSERT(mutex_owned(p->p_lock));

	signo = ksi->ksi_signo;

	if (ksi->ksi_lid != 0) {
		/*
		 * Signal came via _lwp_kill().  Find the LWP and see if
		 * it's interested.
		 */
		if ((l = lwp_find(p, ksi->ksi_lid)) == NULL)
			return 0;
		if (l->l_sigwaited == NULL ||
		    !sigismember(&l->l_sigwaitset, signo))
			return 0;
	} else {
		/*
		 * Look for any LWP that may be interested.
		 */
		LIST_FOREACH(l, &p->p_sigwaiters, l_sigwaiter) {
			KASSERT(l->l_sigwaited != NULL);
			if (sigismember(&l->l_sigwaitset, signo))
				break;
		}
	}

	if (l != NULL) {
		l->l_sigwaited->ksi_info = ksi->ksi_info;
		l->l_sigwaited = NULL;
		LIST_REMOVE(l, l_sigwaiter);
		cv_signal(&l->l_sigcv);
		return 1;
	}

	return 0;
}

/*
 * Send the signal to the process.  If the signal has an action, the action
 * is usually performed by the target process rather than the caller; we add
 * the signal to the set of pending signals for the process.
 *
 * Exceptions:
 *   o When a stop signal is sent to a sleeping process that takes the
 *     default action, the process is stopped without awakening it.
 *   o SIGCONT restarts stopped processes (or puts them back to sleep)
 *     regardless of the signal action (eg, blocked or ignored).
 *
 * Other ignored signals are discarded immediately.
 */
int
kpsignal2(struct proc *p, ksiginfo_t *ksi)
{
	int prop, signo = ksi->ksi_signo;
	struct sigacts *sa;
	struct lwp *l = NULL;
	ksiginfo_t *kp;
	lwpid_t lid;
	sig_t action;
	bool toall;
	int error = 0;

	KASSERT(!cpu_intr_p());
	KASSERT(mutex_owned(proc_lock));
	KASSERT(mutex_owned(p->p_lock));
	KASSERT((ksi->ksi_flags & KSI_QUEUED) == 0);
	KASSERT(signo > 0 && signo < NSIG);

	/*
	 * If the process is being created by fork, is a zombie or is
	 * exiting, then just drop the signal here and bail out.
	 */
	if (p->p_stat != SACTIVE && p->p_stat != SSTOP)
		return error;

	/*
	 * Notify any interested parties of the signal.
	 */
	KNOTE(&p->p_klist, NOTE_SIGNAL | signo);

	/*
	 * Some signals including SIGKILL must act on the entire process.
	 */
	kp = NULL;
	prop = sigprop[signo];
	toall = ((prop & SA_TOALL) != 0);
	lid = toall ? 0 : ksi->ksi_lid;

	/*
	 * If proc is traced, always give parent a chance.
	 */
	if (p->p_slflag & PSL_TRACED) {
		action = SIG_DFL;

		if (lid == 0) {
			/*
			 * If the process is being traced and the signal
			 * is being caught, make sure to save any ksiginfo.
			 */
			if ((kp = ksiginfo_alloc(p, ksi, PR_NOWAIT)) == NULL)
				goto discard;
			error = sigput(&p->p_sigpend, p, kp);
			if (error != 0) goto out;
		}
	} else {
		/*
		 * If the signal was the result of a trap and is not being
		 * caught, then reset it to default action so that the
		 * process dumps core immediately.
		 */
		if (KSI_TRAP_P(ksi)) {
			sa = p->p_sigacts;
			mutex_enter(&sa->sa_mutex);
			if (!sigismember(&p->p_sigctx.ps_sigcatch, signo)) {
				sigdelset(&p->p_sigctx.ps_sigignore, signo);
				SIGACTION(p, signo).sa_handler = SIG_DFL;
			}
			mutex_exit(&sa->sa_mutex);
		}

		/*
		 * If the signal is being ignored, then drop it.  Note: we
		 * don't set SIGCONT in ps_sigignore, and if it is set to
		 * SIG_IGN, action will be SIG_DFL here.
		 */
		if (sigismember(&p->p_sigctx.ps_sigignore, signo))
			goto discard;

		else if (sigismember(&p->p_sigctx.ps_sigcatch, signo))
			action = SIG_CATCH;
		else {
			action = SIG_DFL;

			/*
			 * If sending a tty stop signal to a member of an
			 * orphaned process group, discard the signal here if
			 * the action is default; don't stop the process below
			 * if sleeping, and don't clear any pending SIGCONT.
			 */
			if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0)
				goto discard;

			if (prop & SA_KILL && p->p_nice > NZERO)
				p->p_nice = NZERO;
		}
	}

	/*
	 * If stopping or continuing a process, discard any pending
	 * signals that would do the inverse.
	 */
	if ((prop & (SA_CONT | SA_STOP)) != 0) {
		ksiginfoq_t kq;

		ksiginfo_queue_init(&kq);
		if ((prop & SA_CONT) != 0)
			sigclear(&p->p_sigpend, &stopsigmask, &kq);
		if ((prop & SA_STOP) != 0)
			sigclear(&p->p_sigpend, &contsigmask, &kq);
		ksiginfo_queue_drain(&kq);	/* XXXSMP */
	}

	/*
	 * If the signal doesn't have SA_CANTMASK (no override for SIGKILL,
	 * please!), check if any LWPs are waiting on it.  If yes, pass on
	 * the signal info.  The signal won't be processed further here.
	 */
	if ((prop & SA_CANTMASK) == 0 && !LIST_EMPTY(&p->p_sigwaiters) &&
	    p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0 &&
	    sigunwait(p, ksi))
		goto discard;

	/*
	 * XXXSMP Should be allocated by the caller, we're holding locks
	 * here.
	 */
	if (kp == NULL && (kp = ksiginfo_alloc(p, ksi, PR_NOWAIT)) == NULL)
		goto discard;

	/*
	 * LWP private signals are easy - just find the LWP and post
	 * the signal to it.
	 */
	if (lid != 0) {
		l = lwp_find(p, lid);
		if (l != NULL) {
			error = sigput(&l->l_sigpend, p, kp);
			if (error != 0) goto out;
			membar_producer();
			(void)sigpost(l, action, prop, kp->ksi_signo);
		}
		goto out;
	}

	/*
	 * Some signals go to all LWPs, even if posted with _lwp_kill()
	 * or for an SA process.
	 */
	if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) {
		if ((p->p_slflag & PSL_TRACED) != 0)
			goto deliver;

		/*
		 * If SIGCONT is default (or ignored) and process is
		 * asleep, we are finished; the process should not
		 * be awakened.
		 */
		if ((prop & SA_CONT) != 0 && action == SIG_DFL)
			goto out;
	} else {
		/*
		 * Process is stopped or stopping.
		 * - If traced, then no action is needed, unless killing.
		 * - Run the process only if sending SIGCONT or SIGKILL.
		 */
		if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) {
			goto out;
		}
		if ((prop & SA_CONT) != 0 || signo == SIGKILL) {
			/*
			 * Re-adjust p_nstopchild if the process was
			 * stopped but not yet collected by its parent.
			 */
			if (p->p_stat == SSTOP && !p->p_waited)
				p->p_pptr->p_nstopchild--;
			p->p_stat = SACTIVE;
			p->p_sflag &= ~PS_STOPPING;
			if (p->p_slflag & PSL_TRACED) {
				KASSERT(signo == SIGKILL);
				goto deliver;
			}
			/*
			 * Do not make signal pending if SIGCONT is default.
			 *
			 * If the process catches SIGCONT, let it handle the
			 * signal itself (if waiting on event - process runs,
			 * otherwise continues sleeping).
			 */
			if ((prop & SA_CONT) != 0) {
				p->p_xsig = SIGCONT;
				p->p_sflag |= PS_CONTINUED;
				child_psignal(p, 0);
				if (action == SIG_DFL) {
					KASSERT(signo != SIGKILL);
					goto deliver;
				}
			}
		} else if ((prop & SA_STOP) != 0) {
			/*
			 * Already stopped, don't need to stop again.
			 * (If we did the shell could get confused.)
			 */
			goto out;
		}
	}
	/*
	 * Make signal pending.
	 */
	KASSERT((p->p_slflag & PSL_TRACED) == 0);
	error = sigput(&p->p_sigpend, p, kp);
	if (error != 0) goto out;
deliver:
	/*
	 * Before we set LW_PENDSIG on any LWP, ensure that the signal is
	 * visible on the per process list (for sigispending()).  This
	 * is unlikely to be needed in practice, but...
	 */
	membar_producer();

	/*
	 * Try to find an LWP that can take the signal.
	 */
	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
		if (sigpost(l, action, prop, kp->ksi_signo) && !toall)
			break;
	}
	signo = -1;
out:
	/*
	 * If the ksiginfo wasn't used, then bin it.  XXXSMP freeing memory
	 * with locks held.  The caller should take care of this.
	 */
	ksiginfo_free(kp);
	if (signo == -1)
		return error;
discard:
	SDT_PROBE(proc, kernel, , signal__discard, l, p, signo, 0, 0);
	return error;
}

void
kpsendsig(struct lwp *l, const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct proc *p = l->l_proc;

	KASSERT(mutex_owned(p->p_lock));
	(*p->p_emul->e_sendsig)(ksi, mask);
}

/*
 * Stop any LWPs sleeping interruptably.
 */
static void
proc_stop_lwps(struct proc *p)
{
	struct lwp *l;

	KASSERT(mutex_owned(p->p_lock));
	KASSERT((p->p_sflag & PS_STOPPING) != 0);

	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
		lwp_lock(l);
		if (l->l_stat == LSSLEEP && (l->l_flag & LW_SINTR) != 0) {
			l->l_stat = LSSTOP;
			p->p_nrlwps--;
		}
		lwp_unlock(l);
	}
}

/*
 * Finish stopping of a process.  Mark it stopped and notify the parent.
 *
 * Drop p_lock briefly if PS_NOTIFYSTOP is set and ppsig is true.
 */
static void
proc_stop_done(struct proc *p, bool ppsig, int ppmask)
{

	KASSERT(mutex_owned(proc_lock));
	KASSERT(mutex_owned(p->p_lock));
	KASSERT((p->p_sflag & PS_STOPPING) != 0);
	KASSERT(p->p_nrlwps == 0 || (p->p_nrlwps == 1 && p == curproc));

	p->p_sflag &= ~PS_STOPPING;
	p->p_stat = SSTOP;
	p->p_waited = 0;
	p->p_pptr->p_nstopchild++;
	if ((p->p_sflag & PS_NOTIFYSTOP) != 0) {
		if (ppsig) {
			/* child_psignal drops p_lock briefly. */
			child_psignal(p, ppmask);
		}
		cv_broadcast(&p->p_pptr->p_waitcv);
	}
}

/*
 * Stop the current process and switch away when being stopped or traced.
 */
static void
sigswitch(bool ppsig, int ppmask, int signo)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	int biglocks;

	KASSERT(mutex_owned(p->p_lock));
	KASSERT(l->l_stat == LSONPROC);
	KASSERT(p->p_nrlwps > 0);

	/*
	 * On entry we know that the process needs to stop.  If it's
	 * the result of a 'sideways' stop signal that has been sourced
	 * through issignal(), then stop other LWPs in the process too.
	 */
	if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) {
		KASSERT(signo != 0);
		proc_stop(p, 1, signo);
		KASSERT(p->p_nrlwps > 0);
	}

	/*
	 * If we are the last live LWP, and the stop was a result of
	 * a new signal, then signal the parent.
	 */
	if ((p->p_sflag & PS_STOPPING) != 0) {
		if (!mutex_tryenter(proc_lock)) {
			mutex_exit(p->p_lock);
			mutex_enter(proc_lock);
			mutex_enter(p->p_lock);
		}

		if (p->p_nrlwps == 1 && (p->p_sflag & PS_STOPPING) != 0) {
			/*
			 * Note that proc_stop_done() can drop
			 * p->p_lock briefly.
			 */
			proc_stop_done(p, ppsig, ppmask);
		}

		mutex_exit(proc_lock);
	}

	/*
	 * Unlock and switch away.
	 */
	KERNEL_UNLOCK_ALL(l, &biglocks);
	if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) {
		p->p_nrlwps--;
		lwp_lock(l);
		KASSERT(l->l_stat == LSONPROC || l->l_stat == LSSLEEP);
		l->l_stat = LSSTOP;
		lwp_unlock(l);
	}

	mutex_exit(p->p_lock);
	lwp_lock(l);
	mi_switch(l);
	KERNEL_LOCK(biglocks, l);
	mutex_enter(p->p_lock);
}

/*
 * Check for a signal from the debugger.
 */
static int
sigchecktrace(void)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	int signo;

	KASSERT(mutex_owned(p->p_lock));

	/* If there's a pending SIGKILL, process it immediately. */
	if (sigismember(&p->p_sigpend.sp_set, SIGKILL))
		return 0;

	/*
	 * If we are no longer being traced, or the parent didn't
	 * give us a signal, or we're stopping, look for more signals.
	 */
	if ((p->p_slflag & PSL_TRACED) == 0 || p->p_xsig == 0 ||
	    (p->p_sflag & PS_STOPPING) != 0)
		return 0;

	/*
	 * If the new signal is being masked, look for other signals.
	 * `p->p_sigctx.ps_siglist |= mask' is done in setrunnable().
	 */
	signo = p->p_xsig;
	p->p_xsig = 0;
	if (sigismember(&l->l_sigmask, signo)) {
		signo = 0;
	}
	return signo;
}

/*
 * If the current process has received a signal (should be caught or cause
 * termination, should interrupt current syscall), return the signal number.
 *
 * Stop signals with default action are processed immediately, then cleared;
 * they aren't returned.  This is checked after each entry to the system for
 * a syscall or trap.
 *
 * We will also return -1 if the process is exiting and the current LWP must
 * follow suit.
 */
int
issignal(struct lwp *l)
{
	struct proc *p;
	int signo, prop;
	sigpend_t *sp;
	sigset_t ss;

	p = l->l_proc;
	sp = NULL;
	signo = 0;

	KASSERT(p == curproc);
	KASSERT(mutex_owned(p->p_lock));

	for (;;) {
		/* Discard any signals that we have decided not to take. */
		if (signo != 0) {
			(void)sigget(sp, NULL, signo, NULL);
		}

		/*
		 * If the process is stopped/stopping, then stop ourselves
		 * now that we're on the kernel/userspace boundary.  When
		 * we awaken, check for a signal from the debugger.
		 */
		if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) {
			sigswitch(true, PS_NOCLDSTOP, 0);
			signo = sigchecktrace();
		} else
			signo = 0;

		/* Signals from the debugger are "out of band". */
		sp = NULL;

		/*
		 * If the debugger didn't provide a signal, find a pending
		 * signal from our set.  Check per-LWP signals first, and
		 * then per-process.
		 */
		if (signo == 0) {
			sp = &l->l_sigpend;
			ss = sp->sp_set;
			if ((p->p_lflag & PL_PPWAIT) != 0)
				sigminusset(&stopsigmask, &ss);
			sigminusset(&l->l_sigmask, &ss);

			if ((signo = firstsig(&ss)) == 0) {
				sp = &p->p_sigpend;
				ss = sp->sp_set;
				if ((p->p_lflag & PL_PPWAIT) != 0)
					sigminusset(&stopsigmask, &ss);
				sigminusset(&l->l_sigmask, &ss);

				if ((signo = firstsig(&ss)) == 0) {
					/*
					 * No signal pending - clear the
					 * indicator and bail out.
					 */
					lwp_lock(l);
					l->l_flag &= ~LW_PENDSIG;
					lwp_unlock(l);
					sp = NULL;
					break;
				}
			}
		}

		/*
		 * We should see pending but ignored signals only if
		 * we are being traced.
		 */
		if (sigismember(&p->p_sigctx.ps_sigignore, signo) &&
		    (p->p_slflag & PSL_TRACED) == 0) {
			/* Discard the signal. */
			continue;
		}

		/*
		 * If traced, always stop, and stay stopped until released
		 * by the debugger.  If the our parent process is waiting
		 * for us, don't hang as we could deadlock.
		 */
		if ((p->p_slflag & PSL_TRACED) != 0 &&
		    (p->p_lflag & PL_PPWAIT) == 0 && signo != SIGKILL) {
			/*
			 * Take the signal, but don't remove it from the
			 * siginfo queue, because the debugger can send
			 * it later.
			 */
			if (sp)
				sigdelset(&sp->sp_set, signo);
			p->p_xsig = signo;

			/* Emulation-specific handling of signal trace */
			if (p->p_emul->e_tracesig == NULL ||
			    (*p->p_emul->e_tracesig)(p, signo) == 0)
				sigswitch(!(p->p_slflag & PSL_FSTRACE), 0,
				    signo);

			/* Check for a signal from the debugger. */
			if ((signo = sigchecktrace()) == 0)
				continue;

			/* Signals from the debugger are "out of band". */
			sp = NULL;
		}

		prop = sigprop[signo];

		/*
		 * Decide whether the signal should be returned.
		 */
		switch ((long)SIGACTION(p, signo).sa_handler) {
		case (long)SIG_DFL:
			/*
			 * Don't take default actions on system processes.
			 */
			if (p->p_pid <= 1) {
#ifdef DIAGNOSTIC
				/*
				 * Are you sure you want to ignore SIGSEGV
				 * in init? XXX
				 */
				printf_nolog("Process (pid %d) got sig %d\n",
				    p->p_pid, signo);
#endif
				continue;
			}

			/*
			 * If there is a pending stop signal to process with
			 * default action, stop here, then clear the signal. 
			 * However, if process is member of an orphaned
			 * process group, ignore tty stop signals.
			 */
			if (prop & SA_STOP) {
				/*
				 * XXX Don't hold proc_lock for p_lflag,
				 * but it's not a big deal.
				 */
				if (p->p_slflag & PSL_TRACED ||
				    ((p->p_lflag & PL_ORPHANPG) != 0 &&
				    prop & SA_TTYSTOP)) {
					/* Ignore the signal. */
					continue;
				}
				/* Take the signal. */
				(void)sigget(sp, NULL, signo, NULL);
				p->p_xsig = signo;
				p->p_sflag &= ~PS_CONTINUED;
				signo = 0;
				sigswitch(true, PS_NOCLDSTOP, p->p_xsig);
			} else if (prop & SA_IGNORE) {
				/*
				 * Except for SIGCONT, shouldn't get here.
				 * Default action is to ignore; drop it.
				 */
				continue;
			}
			break;

		case (long)SIG_IGN:
#ifdef DEBUG_ISSIGNAL
			/*
			 * Masking above should prevent us ever trying
			 * to take action on an ignored signal other
			 * than SIGCONT, unless process is traced.
			 */
			if ((prop & SA_CONT) == 0 &&
			    (p->p_slflag & PSL_TRACED) == 0)
				printf_nolog("issignal\n");
#endif
			continue;

		default:
			/*
			 * This signal has an action, let postsig() process
			 * it.
			 */
			break;
		}

		break;
	}

	l->l_sigpendset = sp;
	return signo;
}

/*
 * Take the action for the specified signal
 * from the current set of pending signals.
 */
void
postsig(int signo)
{
	struct lwp	*l;
	struct proc	*p;
	struct sigacts	*ps;
	sig_t		action;
	sigset_t	*returnmask;
	ksiginfo_t	ksi;

	l = curlwp;
	p = l->l_proc;
	ps = p->p_sigacts;

	KASSERT(mutex_owned(p->p_lock));
	KASSERT(signo > 0);

	/*
	 * Set the new mask value and also defer further occurrences of this
	 * signal.
	 *
	 * Special case: user has done a sigsuspend.  Here the current mask is
	 * not of interest, but rather the mask from before the sigsuspend is
	 * what we want restored after the signal processing is completed.
	 */
	if (l->l_sigrestore) {
		returnmask = &l->l_sigoldmask;
		l->l_sigrestore = 0;
	} else
		returnmask = &l->l_sigmask;

	/*
	 * Commit to taking the signal before releasing the mutex.
	 */
	action = SIGACTION_PS(ps, signo).sa_handler;
	l->l_ru.ru_nsignals++;
	if (l->l_sigpendset == NULL) {
		/* From the debugger */
		if (!siggetinfo(&l->l_sigpend, &ksi, signo))
			(void)siggetinfo(&p->p_sigpend, &ksi, signo);
	} else
		sigget(l->l_sigpendset, &ksi, signo, NULL);

	if (ktrpoint(KTR_PSIG)) {
		mutex_exit(p->p_lock);
		ktrpsig(signo, action, returnmask, &ksi);
		mutex_enter(p->p_lock);
	}

	SDT_PROBE(proc, kernel, , signal__handle, signo, &ksi, action, 0, 0);

	if (action == SIG_DFL) {
		/*
		 * Default action, where the default is to kill
		 * the process.  (Other cases were ignored above.)
		 */
		sigexit(l, signo);
		return;
	}

	/*
	 * If we get here, the signal must be caught.
	 */
#ifdef DIAGNOSTIC
	if (action == SIG_IGN || sigismember(&l->l_sigmask, signo))
		panic("postsig action");
#endif

	kpsendsig(l, &ksi, returnmask);
}

/*
 * sendsig:
 *
 *	Default signal delivery method for NetBSD.
 */
void
sendsig(const struct ksiginfo *ksi, const sigset_t *mask)
{
	struct sigacts *sa;
	int sig;

	sig = ksi->ksi_signo;
	sa = curproc->p_sigacts;

	switch (sa->sa_sigdesc[sig].sd_vers)  {
	case 0:
	case 1:
		/* Compat for 1.6 and earlier. */
		if (sendsig_sigcontext_vec == NULL) {
			break;
		}
		(*sendsig_sigcontext_vec)(ksi, mask);
		return;
	case 2:
	case 3:
		sendsig_siginfo(ksi, mask);
		return;
	default:
		break;
	}

	printf("sendsig: bad version %d\n", sa->sa_sigdesc[sig].sd_vers);
	sigexit(curlwp, SIGILL);
}

/*
 * sendsig_reset:
 *
 *	Reset the signal action.  Called from emulation specific sendsig()
 *	before unlocking to deliver the signal.
 */
void
sendsig_reset(struct lwp *l, int signo)
{
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;

	KASSERT(mutex_owned(p->p_lock));

	p->p_sigctx.ps_lwp = 0;
	p->p_sigctx.ps_code = 0;
	p->p_sigctx.ps_signo = 0;

	mutex_enter(&ps->sa_mutex);
	sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask);
	if (SIGACTION_PS(ps, signo).sa_flags & SA_RESETHAND) {
		sigdelset(&p->p_sigctx.ps_sigcatch, signo);
		if (signo != SIGCONT && sigprop[signo] & SA_IGNORE)
			sigaddset(&p->p_sigctx.ps_sigignore, signo);
		SIGACTION_PS(ps, signo).sa_handler = SIG_DFL;
	}
	mutex_exit(&ps->sa_mutex);
}

/*
 * Kill the current process for stated reason.
 */
void
killproc(struct proc *p, const char *why)
{

	KASSERT(mutex_owned(proc_lock));

	log(LOG_ERR, "pid %d was killed: %s\n", p->p_pid, why);
	uprintf_locked("sorry, pid %d was killed: %s\n", p->p_pid, why);
	psignal(p, SIGKILL);
}

/*
 * Force the current process to exit with the specified signal, dumping core
 * if appropriate.  We bypass the normal tests for masked and caught
 * signals, allowing unrecoverable failures to terminate the process without
 * changing signal state.  Mark the accounting record with the signal
 * termination.  If dumping core, save the signal number for the debugger. 
 * Calls exit and does not return.
 */
void
sigexit(struct lwp *l, int signo)
{
	int exitsig, error, docore;
	struct proc *p;
	struct lwp *t;

	p = l->l_proc;

	KASSERT(mutex_owned(p->p_lock));
	KERNEL_UNLOCK_ALL(l, NULL);

	/*
	 * Don't permit coredump() multiple times in the same process.
	 * Call back into sigexit, where we will be suspended until
	 * the deed is done.  Note that this is a recursive call, but
	 * LW_WCORE will prevent us from coming back this way.
	 */
	if ((p->p_sflag & PS_WCORE) != 0) {
		lwp_lock(l);
		l->l_flag |= (LW_WCORE | LW_WEXIT | LW_WSUSPEND);
		lwp_unlock(l);
		mutex_exit(p->p_lock);
		lwp_userret(l);
		panic("sigexit 1");
		/* NOTREACHED */
	}

	/* If process is already on the way out, then bail now. */
	if ((p->p_sflag & PS_WEXIT) != 0) {
		mutex_exit(p->p_lock);
		lwp_exit(l);
		panic("sigexit 2");
		/* NOTREACHED */
	}

	/*
	 * Prepare all other LWPs for exit.  If dumping core, suspend them
	 * so that their registers are available long enough to be dumped.
 	 */
	if ((docore = (sigprop[signo] & SA_CORE)) != 0) {
		p->p_sflag |= PS_WCORE;
		for (;;) {
			LIST_FOREACH(t, &p->p_lwps, l_sibling) {
				lwp_lock(t);
				if (t == l) {
					t->l_flag &= ~LW_WSUSPEND;
					lwp_unlock(t);
					continue;
				}
				t->l_flag |= (LW_WCORE | LW_WEXIT);
				lwp_suspend(l, t);
			}

			if (p->p_nrlwps == 1)
				break;

			/*
			 * Kick any LWPs sitting in lwp_wait1(), and wait
			 * for everyone else to stop before proceeding.
			 */
			p->p_nlwpwait++;
			cv_broadcast(&p->p_lwpcv);
			cv_wait(&p->p_lwpcv, p->p_lock);
			p->p_nlwpwait--;
		}
	}

	exitsig = signo;
	p->p_acflag |= AXSIG;
	p->p_sigctx.ps_signo = signo;

	if (docore) {
		mutex_exit(p->p_lock);
		error = (*coredump_vec)(l, NULL);

		if (kern_logsigexit) {
			int uid = l->l_cred ?
			    (int)kauth_cred_geteuid(l->l_cred) : -1;

			if (error)
				log(LOG_INFO, lognocoredump, p->p_pid,
				    p->p_comm, uid, signo, error);
			else
				log(LOG_INFO, logcoredump, p->p_pid,
				    p->p_comm, uid, signo);
		}

#ifdef PAX_SEGVGUARD
		pax_segvguard(l, p->p_textvp, p->p_comm, true);
#endif /* PAX_SEGVGUARD */
		/* Acquire the sched state mutex.  exit1() will release it. */
		mutex_enter(p->p_lock);
		if (error == 0)
			p->p_sflag |= PS_COREDUMP;
	}

	/* No longer dumping core. */
	p->p_sflag &= ~PS_WCORE;

	exit1(l, 0, exitsig);
	/* NOTREACHED */
}

/*
 * Put process 'p' into the stopped state and optionally, notify the parent.
 */
void
proc_stop(struct proc *p, int notify, int signo)
{
	struct lwp *l;

	KASSERT(mutex_owned(p->p_lock));

	/*
	 * First off, set the stopping indicator and bring all sleeping
	 * LWPs to a halt so they are included in p->p_nrlwps.  We musn't
	 * unlock between here and the p->p_nrlwps check below.
	 */
	p->p_sflag |= PS_STOPPING;
	if (notify)
		p->p_sflag |= PS_NOTIFYSTOP;
	else
		p->p_sflag &= ~PS_NOTIFYSTOP;
	membar_producer();

	proc_stop_lwps(p);

	/*
	 * If there are no LWPs available to take the signal, then we
	 * signal the parent process immediately.  Otherwise, the last
	 * LWP to stop will take care of it.
	 */

	if (p->p_nrlwps == 0) {
		proc_stop_done(p, true, PS_NOCLDSTOP);
	} else {
		/*
		 * Have the remaining LWPs come to a halt, and trigger
		 * proc_stop_callout() to ensure that they do.
		 */
		LIST_FOREACH(l, &p->p_lwps, l_sibling) {
			sigpost(l, SIG_DFL, SA_STOP, signo);
		}
		callout_schedule(&proc_stop_ch, 1);
	}
}

/*
 * When stopping a process, we do not immediatly set sleeping LWPs stopped,
 * but wait for them to come to a halt at the kernel-user boundary.  This is
 * to allow LWPs to release any locks that they may hold before stopping.
 *
 * Non-interruptable sleeps can be long, and there is the potential for an
 * LWP to begin sleeping interruptably soon after the process has been set
 * stopping (PS_STOPPING).  These LWPs will not notice that the process is
 * stopping, and so complete halt of the process and the return of status
 * information to the parent could be delayed indefinitely.
 *
 * To handle this race, proc_stop_callout() runs once per tick while there
 * are stopping processes in the system.  It sets LWPs that are sleeping
 * interruptably into the LSSTOP state.
 *
 * Note that we are not concerned about keeping all LWPs stopped while the
 * process is stopped: stopped LWPs can awaken briefly to handle signals. 
 * What we do need to ensure is that all LWPs in a stopping process have
 * stopped at least once, so that notification can be sent to the parent
 * process.
 */
static void
proc_stop_callout(void *cookie)
{
	bool more, restart;
	struct proc *p;

	(void)cookie;

	do {
		restart = false;
		more = false;

		mutex_enter(proc_lock);
		PROCLIST_FOREACH(p, &allproc) {
			mutex_enter(p->p_lock);

			if ((p->p_sflag & PS_STOPPING) == 0) {
				mutex_exit(p->p_lock);
				continue;
			}

			/* Stop any LWPs sleeping interruptably. */
			proc_stop_lwps(p);
			if (p->p_nrlwps == 0) {
				/*
				 * We brought the process to a halt.
				 * Mark it as stopped and notify the
				 * parent.
				 */
				if ((p->p_sflag & PS_NOTIFYSTOP) != 0) {
					/*
					 * Note that proc_stop_done() will
					 * drop p->p_lock briefly.
					 * Arrange to restart and check
					 * all processes again.
					 */
					restart = true;
				}
				proc_stop_done(p, true, PS_NOCLDSTOP);
			} else
				more = true;

			mutex_exit(p->p_lock);
			if (restart)
				break;
		}
		mutex_exit(proc_lock);
	} while (restart);

	/*
	 * If we noted processes that are stopping but still have
	 * running LWPs, then arrange to check again in 1 tick.
	 */
	if (more)
		callout_schedule(&proc_stop_ch, 1);
}

/*
 * Given a process in state SSTOP, set the state back to SACTIVE and
 * move LSSTOP'd LWPs to LSSLEEP or make them runnable.
 */
void
proc_unstop(struct proc *p)
{
	struct lwp *l;
	int sig;

	KASSERT(mutex_owned(proc_lock));
	KASSERT(mutex_owned(p->p_lock));

	p->p_stat = SACTIVE;
	p->p_sflag &= ~PS_STOPPING;
	sig = p->p_xsig;

	if (!p->p_waited)
		p->p_pptr->p_nstopchild--;

	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
		lwp_lock(l);
		if (l->l_stat != LSSTOP) {
			lwp_unlock(l);
			continue;
		}
		if (l->l_wchan == NULL) {
			setrunnable(l);
			continue;
		}
		if (sig && (l->l_flag & LW_SINTR) != 0) {
			setrunnable(l);
			sig = 0;
		} else {
			l->l_stat = LSSLEEP;
			p->p_nrlwps++;
			lwp_unlock(l);
		}
	}
}

static int
filt_sigattach(struct knote *kn)
{
	struct proc *p = curproc;

	kn->kn_obj = p;
	kn->kn_flags |= EV_CLEAR;	/* automatically set */

	mutex_enter(p->p_lock);
	SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
	mutex_exit(p->p_lock);

	return 0;
}

static void
filt_sigdetach(struct knote *kn)
{
	struct proc *p = kn->kn_obj;

	mutex_enter(p->p_lock);
	SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
	mutex_exit(p->p_lock);
}

/*
 * Signal knotes are shared with proc knotes, so we apply a mask to
 * the hint in order to differentiate them from process hints.  This
 * could be avoided by using a signal-specific knote list, but probably
 * isn't worth the trouble.
 */
static int
filt_signal(struct knote *kn, long hint)
{

	if (hint & NOTE_SIGNAL) {
		hint &= ~NOTE_SIGNAL;

		if (kn->kn_id == hint)
			kn->kn_data++;
	}
	return (kn->kn_data != 0);
}

const struct filterops sig_filtops = {
	0, filt_sigattach, filt_sigdetach, filt_signal
};
/*	$NetBSD: sys_sig.c,v 1.45 2015/10/02 16:54:15 christos Exp $	*/

/*-
 * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Andrew Doran.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1982, 1986, 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)kern_sig.c	8.14 (Berkeley) 5/14/95
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.45 2015/10/02 16:54:15 christos Exp $");

#include "opt_dtrace.h"

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
#include <sys/proc.h>
#include <sys/pool.h>
#include <sys/syscallargs.h>
#include <sys/kauth.h>
#include <sys/wait.h>
#include <sys/kmem.h>
#include <sys/module.h>
#include <sys/sdt.h>

SDT_PROVIDER_DECLARE(proc);
SDT_PROBE_DEFINE2(proc, kernel, , signal__clear,
    "int", 		/* signal */
    "ksiginfo_t *");	/* signal-info */

int
sys___sigaction_sigtramp(struct lwp *l,
    const struct sys___sigaction_sigtramp_args *uap, register_t *retval)
{
	/* {
		syscallarg(int)				signum;
		syscallarg(const struct sigaction *)	nsa;
		syscallarg(struct sigaction *)		osa;
		syscallarg(void *)			tramp;
		syscallarg(int)				vers;
	} */
	struct sigaction nsa, osa;
	int error;

	if (SCARG(uap, nsa)) {
		error = copyin(SCARG(uap, nsa), &nsa, sizeof(nsa));
		if (error)
			return (error);
	}
	error = sigaction1(l, SCARG(uap, signum),
	    SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
	    SCARG(uap, tramp), SCARG(uap, vers));
	if (error)
		return (error);
	if (SCARG(uap, osa)) {
		error = copyout(&osa, SCARG(uap, osa), sizeof(osa));
		if (error)
			return (error);
	}
	return 0;
}

/*
 * Manipulate signal mask.  Note that we receive new mask, not pointer, and
 * return old mask as return value; the library stub does the rest.
 */
int
sys___sigprocmask14(struct lwp *l, const struct sys___sigprocmask14_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)			how;
		syscallarg(const sigset_t *)	set;
		syscallarg(sigset_t *)		oset;
	} */
	struct proc	*p = l->l_proc;
	sigset_t	nss, oss;
	int		error;

	if (SCARG(uap, set)) {
		error = copyin(SCARG(uap, set), &nss, sizeof(nss));
		if (error)
			return error;
	}
	mutex_enter(p->p_lock);
	error = sigprocmask1(l, SCARG(uap, how),
	    SCARG(uap, set) ? &nss : 0, SCARG(uap, oset) ? &oss : 0);
	mutex_exit(p->p_lock);
	if (error)
		return error;
	if (SCARG(uap, oset)) {
		error = copyout(&oss, SCARG(uap, oset), sizeof(oss));
		if (error)
			return error;
	}
	return 0;
}

int
sys___sigpending14(struct lwp *l, const struct sys___sigpending14_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(sigset_t *)	set;
	} */
	sigset_t ss;

	sigpending1(l, &ss);
	return copyout(&ss, SCARG(uap, set), sizeof(ss));
}

/*
 * Suspend process until signal, providing mask to be set in the meantime. 
 * Note nonstandard calling convention: libc stub passes mask, not pointer,
 * to save a copyin.
 */
int
sys___sigsuspend14(struct lwp *l, const struct sys___sigsuspend14_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(const sigset_t *)	set;
	} */
	sigset_t	ss;
	int		error;

	if (SCARG(uap, set)) {
		error = copyin(SCARG(uap, set), &ss, sizeof(ss));
		if (error)
			return error;
	}
	return sigsuspend1(l, SCARG(uap, set) ? &ss : 0);
}

int
sys___sigaltstack14(struct lwp *l, const struct sys___sigaltstack14_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(const struct sigaltstack *)	nss;
		syscallarg(struct sigaltstack *)	oss;
	} */
	struct sigaltstack	nss, oss;
	int			error;

	if (SCARG(uap, nss)) {
		error = copyin(SCARG(uap, nss), &nss, sizeof(nss));
		if (error)
			return error;
	}
	error = sigaltstack1(l,
	    SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0);
	if (error)
		return error;
	if (SCARG(uap, oss)) {
		error = copyout(&oss, SCARG(uap, oss), sizeof(oss));
		if (error)
			return error;
	}
	return 0;
}

int
kill1(struct lwp *l, pid_t pid, ksiginfo_t *ksi, register_t *retval)
{
	int error;
	struct proc *p;

	if ((u_int)ksi->ksi_signo >= NSIG)
		return EINVAL;

	if (pid != l->l_proc->p_pid) {
		if (ksi->ksi_pid != l->l_proc->p_pid)
			return EPERM;

		if (ksi->ksi_uid != kauth_cred_geteuid(l->l_cred))
			return EPERM;

		switch (ksi->ksi_code) {
		case SI_USER:
		case SI_QUEUE:
			break;
		default:
			return EPERM;
		}
	}

	if (pid > 0) {
		/* kill single process */
		mutex_enter(proc_lock);
		p = proc_find_raw(pid);
		if (p == NULL || (p->p_stat != SACTIVE && p->p_stat != SSTOP)) {
			mutex_exit(proc_lock);
			/* IEEE Std 1003.1-2001: return success for zombies */
			return p ? 0 : ESRCH;
		}
		mutex_enter(p->p_lock);
		error = kauth_authorize_process(l->l_cred,
		    KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(ksi->ksi_signo),
		    NULL, NULL);
		if (!error && ksi->ksi_signo) {
			error = kpsignal2(p, ksi);
		}
		mutex_exit(p->p_lock);
		mutex_exit(proc_lock);
		return error;
	}

	switch (pid) {
	case -1:		/* broadcast signal */
		return killpg1(l, ksi, 0, 1);
	case 0:			/* signal own process group */
		return killpg1(l, ksi, 0, 0);
	default:		/* negative explicit process group */
		return killpg1(l, ksi, -pid, 0);
	}
	/* NOTREACHED */
}

int
sys_sigqueueinfo(struct lwp *l, const struct sys_sigqueueinfo_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(pid_t int)	pid;
		syscallarg(const siginfo_t *)	info;
	} */
	ksiginfo_t	ksi;
	int error;

	KSI_INIT(&ksi);

	if ((error = copyin(&SCARG(uap, info)->_info, &ksi.ksi_info,
	    sizeof(ksi.ksi_info))) != 0)
		return error;

	return kill1(l, SCARG(uap, pid), &ksi, retval);
}

int
sys_kill(struct lwp *l, const struct sys_kill_args *uap, register_t *retval)
{
	/* {
		syscallarg(pid_t)	pid;
		syscallarg(int)	signum;
	} */
	ksiginfo_t	ksi;

	KSI_INIT(&ksi);

	ksi.ksi_signo = SCARG(uap, signum);
	ksi.ksi_code = SI_USER;
	ksi.ksi_pid = l->l_proc->p_pid;
	ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);

	return kill1(l, SCARG(uap, pid), &ksi, retval);
}

int
sys_getcontext(struct lwp *l, const struct sys_getcontext_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(struct __ucontext *) ucp;
	} */
	struct proc *p = l->l_proc;
	ucontext_t uc;

	memset(&uc, 0, sizeof(uc));

	mutex_enter(p->p_lock);
	getucontext(l, &uc);
	mutex_exit(p->p_lock);

	return copyout(&uc, SCARG(uap, ucp), sizeof (*SCARG(uap, ucp)));
}

int
sys_setcontext(struct lwp *l, const struct sys_setcontext_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(const ucontext_t *) ucp;
	} */
	struct proc *p = l->l_proc;
	ucontext_t uc;
	int error;

	error = copyin(SCARG(uap, ucp), &uc, sizeof (uc));
	if (error)
		return error;
	if ((uc.uc_flags & _UC_CPU) == 0)
		return EINVAL;
	mutex_enter(p->p_lock);
	error = setucontext(l, &uc);
	mutex_exit(p->p_lock);
	if (error)
 		return error;

	return EJUSTRETURN;
}

/*
 * sigtimedwait(2) system call, used also for implementation
 * of sigwaitinfo() and sigwait().
 *
 * This only handles single LWP in signal wait. libpthread provides
 * its own sigtimedwait() wrapper to DTRT WRT individual threads.
 */
int
sys_____sigtimedwait50(struct lwp *l,
    const struct sys_____sigtimedwait50_args *uap, register_t *retval)
{

	return sigtimedwait1(l, uap, retval, copyin, copyout, copyin, copyout);
}

int
sigaction1(struct lwp *l, int signum, const struct sigaction *nsa,
	struct sigaction *osa, const void *tramp, int vers)
{
	struct proc *p;
	struct sigacts *ps;
	sigset_t tset;
	int prop, error;
	ksiginfoq_t kq;
	static bool v0v1valid;

	if (signum <= 0 || signum >= NSIG)
		return EINVAL;

	p = l->l_proc;
	error = 0;
	ksiginfo_queue_init(&kq);

	/*
	 * Trampoline ABI version 0 is reserved for the legacy kernel
	 * provided on-stack trampoline.  Conversely, if we are using a
	 * non-0 ABI version, we must have a trampoline.  Only validate the
	 * vers if a new sigaction was supplied and there was an actual
	 * handler specified (not SIG_IGN or SIG_DFL), which don't require
	 * a trampoline. Emulations use legacy kernel trampolines with
	 * version 0, alternatively check for that too.
	 *
	 * If version < 2, we try to autoload the compat module.  Note
	 * that we interlock with the unload check in compat_modcmd()
	 * using kernconfig_lock.  If the autoload fails, we don't try it
	 * again for this process.
	 */
	if (nsa != NULL && nsa->sa_handler != SIG_IGN
	    && nsa->sa_handler != SIG_DFL) {
		if (__predict_false(vers < 2)) {
			if (p->p_flag & PK_32)
				v0v1valid = true;
			else if ((p->p_lflag & PL_SIGCOMPAT) == 0) {
				kernconfig_lock();
				if (sendsig_sigcontext_vec == NULL) {
					(void)module_autoload("compat",
					    MODULE_CLASS_ANY);
				}
				if (sendsig_sigcontext_vec != NULL) {
					/*
					 * We need to remember if the
					 * sigcontext method may be useable,
					 * because libc may use it even
					 * if siginfo is available.
					 */
					v0v1valid = true;
				}
				mutex_enter(proc_lock);
				/*
				 * Prevent unload of compat module while
				 * this process remains.
				 */
				p->p_lflag |= PL_SIGCOMPAT;
				mutex_exit(proc_lock);
				kernconfig_unlock();
			}
		}

		switch (vers) {
		case 0:
			/* sigcontext, kernel supplied trampoline. */
			if (tramp != NULL || !v0v1valid) {
				return EINVAL;
			}
			break;
		case 1:
			/* sigcontext, user supplied trampoline. */
			if (tramp == NULL || !v0v1valid) {
				return EINVAL;
			}
			break;
		case 2:
		case 3:
			/* siginfo, user supplied trampoline. */
			if (tramp == NULL) {
				return EINVAL;
			}
			break;
		default:
			return EINVAL;
		}
	}

	mutex_enter(p->p_lock);

	ps = p->p_sigacts;
	if (osa)
		*osa = SIGACTION_PS(ps, signum);
	if (!nsa)
		goto out;

	prop = sigprop[signum];
	if ((nsa->sa_flags & ~SA_ALLBITS) || (prop & SA_CANTMASK)) {
		error = EINVAL;
		goto out;
	}

	SIGACTION_PS(ps, signum) = *nsa;
	ps->sa_sigdesc[signum].sd_tramp = tramp;
	ps->sa_sigdesc[signum].sd_vers = vers;
	sigminusset(&sigcantmask, &SIGACTION_PS(ps, signum).sa_mask);

	if ((prop & SA_NORESET) != 0)
		SIGACTION_PS(ps, signum).sa_flags &= ~SA_RESETHAND;

	if (signum == SIGCHLD) {
		if (nsa->sa_flags & SA_NOCLDSTOP)
			p->p_sflag |= PS_NOCLDSTOP;
		else
			p->p_sflag &= ~PS_NOCLDSTOP;
		if (nsa->sa_flags & SA_NOCLDWAIT) {
			/*
			 * Paranoia: since SA_NOCLDWAIT is implemented by
			 * reparenting the dying child to PID 1 (and trust
			 * it to reap the zombie), PID 1 itself is forbidden
			 * to set SA_NOCLDWAIT.
			 */
			if (p->p_pid == 1)
				p->p_flag &= ~PK_NOCLDWAIT;
			else
				p->p_flag |= PK_NOCLDWAIT;
		} else
			p->p_flag &= ~PK_NOCLDWAIT;

		if (nsa->sa_handler == SIG_IGN) {
			/*
			 * Paranoia: same as above.
			 */
			if (p->p_pid == 1)
				p->p_flag &= ~PK_CLDSIGIGN;
			else
				p->p_flag |= PK_CLDSIGIGN;
		} else
			p->p_flag &= ~PK_CLDSIGIGN;
	}

	if ((nsa->sa_flags & SA_NODEFER) == 0)
		sigaddset(&SIGACTION_PS(ps, signum).sa_mask, signum);
	else
		sigdelset(&SIGACTION_PS(ps, signum).sa_mask, signum);

	/*
	 * Set bit in p_sigctx.ps_sigignore for signals that are set to
	 * SIG_IGN, and for signals set to SIG_DFL where the default is to
	 * ignore. However, don't put SIGCONT in p_sigctx.ps_sigignore, as
	 * we have to restart the process.
	 */
	if (nsa->sa_handler == SIG_IGN ||
	    (nsa->sa_handler == SIG_DFL && (prop & SA_IGNORE) != 0)) {
		/* Never to be seen again. */
		sigemptyset(&tset);
		sigaddset(&tset, signum);
		sigclearall(p, &tset, &kq);
		if (signum != SIGCONT) {
			/* Easier in psignal */
			sigaddset(&p->p_sigctx.ps_sigignore, signum);
		}
		sigdelset(&p->p_sigctx.ps_sigcatch, signum);
	} else {
		sigdelset(&p->p_sigctx.ps_sigignore, signum);
		if (nsa->sa_handler == SIG_DFL)
			sigdelset(&p->p_sigctx.ps_sigcatch, signum);
		else
			sigaddset(&p->p_sigctx.ps_sigcatch, signum);
	}

	/*
	 * Previously held signals may now have become visible.  Ensure that
	 * we check for them before returning to userspace.
	 */
	if (sigispending(l, 0)) {
		lwp_lock(l);
		l->l_flag |= LW_PENDSIG;
		lwp_unlock(l);
	}
out:
	mutex_exit(p->p_lock);
	ksiginfo_queue_drain(&kq);

	return error;
}

int
sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
{
	sigset_t *mask = &l->l_sigmask;
	bool more;

	KASSERT(mutex_owned(l->l_proc->p_lock));

	if (oss) {
		*oss = *mask;
	}

	if (nss == NULL) {
		return 0;
	}

	switch (how) {
	case SIG_BLOCK:
		sigplusset(nss, mask);
		more = false;
		break;
	case SIG_UNBLOCK:
		sigminusset(nss, mask);
		more = true;
		break;
	case SIG_SETMASK:
		*mask = *nss;
		more = true;
		break;
	default:
		return EINVAL;
	}
	sigminusset(&sigcantmask, mask);
	if (more && sigispending(l, 0)) {
		/*
		 * Check for pending signals on return to user.
		 */
		lwp_lock(l);
		l->l_flag |= LW_PENDSIG;
		lwp_unlock(l);
	}
	return 0;
}

void
sigpending1(struct lwp *l, sigset_t *ss)
{
	struct proc *p = l->l_proc;

	mutex_enter(p->p_lock);
	*ss = l->l_sigpend.sp_set;
	sigplusset(&p->p_sigpend.sp_set, ss);
	mutex_exit(p->p_lock);
}

void
sigsuspendsetup(struct lwp *l, const sigset_t *ss)
{
	struct proc *p = l->l_proc;

	/*
	 * When returning from sigsuspend/pselect/pollts, we want
	 * the old mask to be restored after the
	 * signal handler has finished.  Thus, we
	 * save it here and mark the sigctx structure
	 * to indicate this.
	 */
	mutex_enter(p->p_lock);
	l->l_sigrestore = 1;
	l->l_sigoldmask = l->l_sigmask;
	l->l_sigmask = *ss;
	sigminusset(&sigcantmask, &l->l_sigmask);

	/* Check for pending signals when sleeping. */
	if (sigispending(l, 0)) {
		lwp_lock(l);
		l->l_flag |= LW_PENDSIG;
		lwp_unlock(l);
	}
	mutex_exit(p->p_lock);
}

void
sigsuspendteardown(struct lwp *l)
{
	struct proc *p = l->l_proc;

	mutex_enter(p->p_lock);
	/* Check for pending signals when sleeping. */
	if (l->l_sigrestore) {
		if (sigispending(l, 0)) {
			lwp_lock(l);
			l->l_flag |= LW_PENDSIG;
			lwp_unlock(l);
		} else {
			l->l_sigrestore = 0;
			l->l_sigmask = l->l_sigoldmask;
		}
	}
	mutex_exit(p->p_lock);
}

int
sigsuspend1(struct lwp *l, const sigset_t *ss)
{

	if (ss)
		sigsuspendsetup(l, ss);

	while (kpause("pause", true, 0, NULL) == 0)
		;

	/* always return EINTR rather than ERESTART... */
	return EINTR;
}

int
sigaltstack1(struct lwp *l, const struct sigaltstack *nss,
    struct sigaltstack *oss)
{
	struct proc *p = l->l_proc;
	int error = 0;

	mutex_enter(p->p_lock);

	if (oss)
		*oss = l->l_sigstk;

	if (nss) {
		if (nss->ss_flags & ~SS_ALLBITS)
			error = EINVAL;
		else if (nss->ss_flags & SS_DISABLE) {
			if (l->l_sigstk.ss_flags & SS_ONSTACK)
				error = EINVAL;
		} else if (nss->ss_size < MINSIGSTKSZ)
			error = ENOMEM;

		if (!error)
			l->l_sigstk = *nss;
	}

	mutex_exit(p->p_lock);

	return error;
}

int
sigtimedwait1(struct lwp *l, const struct sys_____sigtimedwait50_args *uap,
    register_t *retval, copyin_t fetchss, copyout_t storeinf, copyin_t fetchts,
    copyout_t storets)
{
	/* {
		syscallarg(const sigset_t *) set;
		syscallarg(siginfo_t *) info;
		syscallarg(struct timespec *) timeout;
	} */
	struct proc *p = l->l_proc;
	int error, signum, timo;
	struct timespec ts, tsstart, tsnow;
	ksiginfo_t ksi;

	/*
	 * Calculate timeout, if it was specified.
	 *
	 * NULL pointer means an infinite timeout.
	 * {.tv_sec = 0, .tv_nsec = 0} means do not block.
	 */
	if (SCARG(uap, timeout)) {
		error = (*fetchts)(SCARG(uap, timeout), &ts, sizeof(ts));
		if (error)
			return error;

		if ((error = itimespecfix(&ts)) != 0)
			return error;

		timo = tstohz(&ts);
		if (timo == 0) {
			if (ts.tv_sec == 0 && ts.tv_nsec == 0)
				timo = -1; /* do not block */
			else
				timo = 1; /* the shortest possible timeout */
		}

		/*
		 * Remember current uptime, it would be used in
		 * ECANCELED/ERESTART case.
		 */
		getnanouptime(&tsstart);
	} else {
		memset(&tsstart, 0, sizeof(tsstart)); /* XXXgcc */
		timo = 0; /* infinite timeout */
	}

	error = (*fetchss)(SCARG(uap, set), &l->l_sigwaitset,
	    sizeof(l->l_sigwaitset));
	if (error)
		return error;

	/*
	 * Silently ignore SA_CANTMASK signals. psignal1() would ignore
	 * SA_CANTMASK signals in waitset, we do this only for the below
	 * siglist check.
	 */
	sigminusset(&sigcantmask, &l->l_sigwaitset);

	mutex_enter(p->p_lock);

	/* Check for pending signals in the process, if no - then in LWP. */
	if ((signum = sigget(&p->p_sigpend, &ksi, 0, &l->l_sigwaitset)) == 0)
		signum = sigget(&l->l_sigpend, &ksi, 0, &l->l_sigwaitset);

	if (signum != 0) {
		/* If found a pending signal, just copy it out to the user. */
		mutex_exit(p->p_lock);
		goto out;
	}

	if (timo < 0) {
		/* If not allowed to block, return an error */
		mutex_exit(p->p_lock);
		return EAGAIN;
	}

	/*
	 * Set up the sigwait list and wait for signal to arrive.
	 * We can either be woken up or time out.
	 */
	l->l_sigwaited = &ksi;
	LIST_INSERT_HEAD(&p->p_sigwaiters, l, l_sigwaiter);
	error = cv_timedwait_sig(&l->l_sigcv, p->p_lock, timo);

	/*
	 * Need to find out if we woke as a result of _lwp_wakeup() or a
	 * signal outside our wait set.
	 */
	if (l->l_sigwaited != NULL) {
		if (error == EINTR) {
			/* Wakeup via _lwp_wakeup(). */
			error = ECANCELED;
		} else if (!error) {
			/* Spurious wakeup - arrange for syscall restart. */
			error = ERESTART;
		}
		l->l_sigwaited = NULL;
		LIST_REMOVE(l, l_sigwaiter);
	}
	mutex_exit(p->p_lock);

	/*
	 * If the sleep was interrupted (either by signal or wakeup), update
	 * the timeout and copyout new value back.  It would be used when
	 * the syscall would be restarted or called again.
	 */
	if (timo && (error == ERESTART || error == ECANCELED)) {
		getnanouptime(&tsnow);

		/* Compute how much time has passed since start. */
		timespecsub(&tsnow, &tsstart, &tsnow);

		/* Substract passed time from timeout. */
		timespecsub(&ts, &tsnow, &ts);

		if (ts.tv_sec < 0)
			error = EAGAIN;
		else {
			/* Copy updated timeout to userland. */
			error = (*storets)(&ts, SCARG(uap, timeout),
			    sizeof(ts));
		}
	}
out:
	/*
	 * If a signal from the wait set arrived, copy it to userland.
	 * Copy only the used part of siginfo, the padding part is
	 * left unchanged (userland is not supposed to touch it anyway).
	 */
	if (error == 0 && SCARG(uap, info)) {
		error = (*storeinf)(&ksi.ksi_info, SCARG(uap, info),
		    sizeof(ksi.ksi_info));
	}
	if (error == 0) {
		*retval = ksi.ksi_info._signo;
		SDT_PROBE(proc, kernel, , signal__clear, *retval,
		    &ksi, 0, 0, 0);
	}
	return error;
}
/*	$NetBSD: signalvar.h,v 1.86 2014/05/15 07:11:30 uebayasi Exp $	*/

/*
 * Copyright (c) 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)signalvar.h	8.6 (Berkeley) 2/19/95
 */

#ifndef	_SYS_SIGNALVAR_H_
#define	_SYS_SIGNALVAR_H_

#include <sys/siginfo.h>
#include <sys/queue.h>
#include <sys/mutex.h>

/*
 * Kernel signal definitions and data structures,
 * not exported to user programs.
 */

/*
 * Queue of signals.
 */
typedef TAILQ_HEAD(ksiginfoq, ksiginfo) ksiginfoq_t;

/*
 * Process signal actions, possibly shared between processes.
 */
struct sigacts {
	struct sigact_sigdesc {
		struct sigaction sd_sigact;
		const void	*sd_tramp;
		int		sd_vers;
	} sa_sigdesc[NSIG];		/* disposition of signals */

	int		sa_refcnt;	/* reference count */
	kmutex_t	sa_mutex;	/* lock on sa_refcnt */
};

/*
 * Pending signals, per LWP and per process.
 */
typedef struct sigpend {
	ksiginfoq_t	sp_info;
	sigset_t	sp_set;
} sigpend_t;

/*
 * Process signal state.
 */
struct sigctx {
	int		ps_signo;	/* for core dump/debugger XXX */
	int		ps_code;	/* for core dump/debugger XXX */
	int		ps_lwp;		/* for core dump/debugger XXX */
	void		*ps_sigcode;	/* address of signal trampoline */
	sigset_t	ps_sigignore;	/* Signals being ignored. */
	sigset_t	ps_sigcatch;	/* Signals being caught by user. */
};

/* additional signal action values, used only temporarily/internally */
#define	SIG_CATCH	(void (*)(int))2

/*
 * get signal action for process and signal; currently only for current process
 */
#define SIGACTION(p, sig)	(p->p_sigacts->sa_sigdesc[(sig)].sd_sigact)
#define	SIGACTION_PS(ps, sig)	(ps->sa_sigdesc[(sig)].sd_sigact)

/*
 * Signal properties and actions.
 * The array below categorizes the signals and their default actions
 * according to the following properties:
 */
#define	SA_KILL		0x0001		/* terminates process by default */
#define	SA_CORE		0x0002		/* ditto and coredumps */
#define	SA_STOP		0x0004		/* suspend process */
#define	SA_TTYSTOP	0x0008		/* ditto, from tty */
#define	SA_IGNORE	0x0010		/* ignore by default */
#define	SA_CONT		0x0020		/* continue if suspended */
#define	SA_CANTMASK	0x0040		/* non-maskable, catchable */
#define	SA_NORESET	0x0080		/* not reset when caught */
#define	SA_TOLWP	0x0100		/* to LWP that generated, if local */
#define	SA_TOALL	0x0200		/* always to all LWPs */

#ifdef _KERNEL

#include <sys/systm.h>			/* for copyin_t/copyout_t */

extern sigset_t contsigmask, sigcantmask;

struct vnode;
struct coredump_iostate;

/*
 * Machine-independent functions:
 */
int	coredump_netbsd(struct lwp *, struct coredump_iostate *);
void	execsigs(struct proc *);
int	issignal(struct lwp *);
void	pgsignal(struct pgrp *, int, int);
void	kpgsignal(struct pgrp *, struct ksiginfo *, void *, int);
void	postsig(int);
void	psignal(struct proc *, int);
void	kpsignal(struct proc *, struct ksiginfo *, void *);
void	child_psignal(struct proc *, int);
void	siginit(struct proc *);
void	trapsignal(struct lwp *, struct ksiginfo *);
void	sigexit(struct lwp *, int) __dead;
void	killproc(struct proc *, const char *);
void	setsigvec(struct proc *, int, struct sigaction *);
int	killpg1(struct lwp *, struct ksiginfo *, int, int);
void	proc_unstop(struct proc *p);

int	sigaction1(struct lwp *, int, const struct sigaction *,
	    struct sigaction *, const void *, int);
int	sigprocmask1(struct lwp *, int, const sigset_t *, sigset_t *);
void	sigpending1(struct lwp *, sigset_t *);
void	sigsuspendsetup(struct lwp *, const sigset_t *);
void	sigsuspendteardown(struct lwp *);
int	sigsuspend1(struct lwp *, const sigset_t *);
int	sigaltstack1(struct lwp *, const struct sigaltstack *,
	    struct sigaltstack *);
int	sigismasked(struct lwp *, int);

int	sigget(sigpend_t *, ksiginfo_t *, int, const sigset_t *);
void	sigclear(sigpend_t *, const sigset_t *, ksiginfoq_t *);
void	sigclearall(struct proc *, const sigset_t *, ksiginfoq_t *);

int	kpsignal2(struct proc *, ksiginfo_t *);

void	signal_init(void);

struct sigacts	*sigactsinit(struct proc *, int);
void	sigactsunshare(struct proc *);
void	sigactsfree(struct sigacts *);

void	kpsendsig(struct lwp *, const struct ksiginfo *, const sigset_t *);
void	sendsig_reset(struct lwp *, int);
void	sendsig(const struct ksiginfo *, const sigset_t *);

ksiginfo_t	*ksiginfo_alloc(struct proc *, ksiginfo_t *, int);
void	ksiginfo_free(ksiginfo_t *);
void	ksiginfo_queue_drain0(ksiginfoq_t *);

struct sys_____sigtimedwait50_args;
int	sigtimedwait1(struct lwp *, const struct sys_____sigtimedwait50_args *,
    register_t *, copyin_t, copyout_t, copyin_t, copyout_t);

void	signotify(struct lwp *);
int	sigispending(struct lwp *, int);

/*
 * Machine-dependent functions:
 */
void	sendsig_sigcontext(const struct ksiginfo *, const sigset_t *);
void	sendsig_siginfo(const struct ksiginfo *, const sigset_t *);

extern	struct pool ksiginfo_pool;

/*
 * Modularity / compatibility.
 */
extern void	(*sendsig_sigcontext_vec)(const struct ksiginfo *,
					  const sigset_t *);
extern int	(*coredump_vec)(struct lwp *, const char *);

/*
 * firstsig:
 *
 * 	Return the first signal in a signal set.
 */
static inline int
firstsig(const sigset_t *ss)
{
	int sig;

	sig = ffs(ss->__bits[0]);
	if (sig != 0)
		return (sig);
#if NSIG > 33
	sig = ffs(ss->__bits[1]);
	if (sig != 0)
		return (sig + 32);
#endif
#if NSIG > 65
	sig = ffs(ss->__bits[2]);
	if (sig != 0)
		return (sig + 64);
#endif
#if NSIG > 97
	sig = ffs(ss->__bits[3]);
	if (sig != 0)
		return (sig + 96);
#endif
	return (0);
}

static inline void
ksiginfo_queue_init(ksiginfoq_t *kq)
{
	TAILQ_INIT(kq);
}

static inline void
ksiginfo_queue_drain(ksiginfoq_t *kq)
{
	if (!TAILQ_EMPTY(kq))
		ksiginfo_queue_drain0(kq);
}

#endif	/* _KERNEL */

#ifdef	_KERNEL
#ifdef	SIGPROP
const int sigprop[NSIG] = {
	0,					/* 0 unused */
	SA_KILL,				/* 1 SIGHUP */
	SA_KILL,				/* 2 SIGINT */
	SA_KILL|SA_CORE,			/* 3 SIGQUIT */
	SA_KILL|SA_CORE|SA_NORESET|SA_TOLWP,	/* 4 SIGILL */
	SA_KILL|SA_CORE|SA_NORESET|SA_TOLWP,	/* 5 SIGTRAP */
	SA_KILL|SA_CORE,			/* 6 SIGABRT */
	SA_KILL|SA_CORE|SA_TOLWP,		/* 7 SIGEMT */
	SA_KILL|SA_CORE|SA_TOLWP,		/* 8 SIGFPE */
	SA_KILL|SA_CANTMASK|SA_TOALL,		/* 9 SIGKILL */
	SA_KILL|SA_CORE|SA_TOLWP,		/* 10 SIGBUS */
	SA_KILL|SA_CORE|SA_TOLWP,		/* 11 SIGSEGV */
	SA_KILL|SA_CORE|SA_TOLWP,		/* 12 SIGSYS */
	SA_KILL,				/* 13 SIGPIPE */
	SA_KILL,				/* 14 SIGALRM */
	SA_KILL,				/* 15 SIGTERM */
	SA_IGNORE,				/* 16 SIGURG */
	SA_STOP|SA_CANTMASK|SA_TOALL,		/* 17 SIGSTOP */
	SA_STOP|SA_TTYSTOP|SA_TOALL,		/* 18 SIGTSTP */
	SA_IGNORE|SA_CONT|SA_TOALL,		/* 19 SIGCONT */
	SA_IGNORE,				/* 20 SIGCHLD */
	SA_STOP|SA_TTYSTOP|SA_TOALL,		/* 21 SIGTTIN */
	SA_STOP|SA_TTYSTOP|SA_TOALL,		/* 22 SIGTTOU */
	SA_IGNORE,				/* 23 SIGIO */
	SA_KILL,				/* 24 SIGXCPU */
	SA_KILL,				/* 25 SIGXFSZ */
	SA_KILL,				/* 26 SIGVTALRM */
	SA_KILL,				/* 27 SIGPROF */
	SA_IGNORE,				/* 28 SIGWINCH  */
	SA_IGNORE,				/* 29 SIGINFO */
	SA_KILL,				/* 30 SIGUSR1 */
	SA_KILL,				/* 31 SIGUSR2 */
	SA_IGNORE|SA_NORESET,			/* 32 SIGPWR */
	SA_KILL,				/* 33 SIGRTMIN + 0 */
	SA_KILL,				/* 34 SIGRTMIN + 1 */
	SA_KILL,				/* 35 SIGRTMIN + 2 */
	SA_KILL,				/* 36 SIGRTMIN + 3 */
	SA_KILL,				/* 37 SIGRTMIN + 4 */
	SA_KILL,				/* 38 SIGRTMIN + 5 */
	SA_KILL,				/* 39 SIGRTMIN + 6 */
	SA_KILL,				/* 40 SIGRTMIN + 7 */
	SA_KILL,				/* 41 SIGRTMIN + 8 */
	SA_KILL,				/* 42 SIGRTMIN + 9 */
	SA_KILL,				/* 43 SIGRTMIN + 10 */
	SA_KILL,				/* 44 SIGRTMIN + 11 */
	SA_KILL,				/* 45 SIGRTMIN + 12 */
	SA_KILL,				/* 46 SIGRTMIN + 13 */
	SA_KILL,				/* 47 SIGRTMIN + 14 */
	SA_KILL,				/* 48 SIGRTMIN + 15 */
	SA_KILL,				/* 49 SIGRTMIN + 16 */
	SA_KILL,				/* 50 SIGRTMIN + 17 */
	SA_KILL,				/* 51 SIGRTMIN + 18 */
	SA_KILL,				/* 52 SIGRTMIN + 19 */
	SA_KILL,				/* 53 SIGRTMIN + 20 */
	SA_KILL,				/* 54 SIGRTMIN + 21 */
	SA_KILL,				/* 55 SIGRTMIN + 22 */
	SA_KILL,				/* 56 SIGRTMIN + 23 */
	SA_KILL,				/* 57 SIGRTMIN + 24 */
	SA_KILL,				/* 58 SIGRTMIN + 25 */
	SA_KILL,				/* 59 SIGRTMIN + 26 */
	SA_KILL,				/* 60 SIGRTMIN + 27 */
	SA_KILL,				/* 61 SIGRTMIN + 28 */
	SA_KILL,				/* 62 SIGRTMIN + 29 */
	SA_KILL,				/* 63 SIGRTMIN + 30 */
};
#undef	SIGPROP
#else
extern const int sigprop[NSIG];
#endif	/* SIGPROP */
#endif	/* _KERNEL */
#endif	/* !_SYS_SIGNALVAR_H_ */
/*	$NetBSD: unistd.h,v 1.56 2016/02/26 17:10:41 christos Exp $	*/

/*
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)unistd.h	8.2 (Berkeley) 1/7/94
 */

#ifndef _SYS_UNISTD_H_
#define	_SYS_UNISTD_H_

#include <sys/featuretest.h>

/* compile-time symbolic constants */
#define	_POSIX_JOB_CONTROL	1
				/* implementation supports job control */

/*
 * According to POSIX 1003.1:
 * "The saved set-user-ID capability allows a program to regain the
 * effective user ID established at the last exec call."
 * However, the setuid/setgid function as specified by POSIX 1003.1 does
 * not allow changing the effective ID from the super-user without also
 * changed the saved ID, so it is impossible to get super-user privileges
 * back later.  Instead we provide this feature independent of the current
 * effective ID through the seteuid/setegid function.  In addition, we do
 * not use the saved ID as specified by POSIX 1003.1 in setuid/setgid,
 * because this would make it impossible for a set-user-ID executable
 * owned by a user other than the super-user to permanently revoke its
 * extra privileges.
 */
#ifdef	_NOT_AVAILABLE
#define	_POSIX_SAVED_IDS	1
				/* saved set-user-ID and set-group-ID */
#endif

#define	_POSIX_VERSION			200112L
#define	_POSIX2_VERSION			200112L

/*
 * We support the posix_spawn() family of functions (unconditionally).
 */
#define	_POSIX_SPAWN			200809L

/* execution-time symbolic constants */

/*
 * POSIX options and option groups we unconditionally do or don't
 * implement.  Those options which are implemented (or not) entirely
 * in user mode are defined in <unistd.h>.  Please keep this list in
 * alphabetical order.
 *
 * Anything which is defined as zero below **must** have an
 * implementation for the corresponding sysconf() which is able to
 * determine conclusively whether or not the feature is supported.
 * Anything which is defined as other than -1 below **must** have
 * complete headers, types, and function declarations as specified by
 * the POSIX standard; however, if the relevant sysconf() function
 * returns -1, the functions may be stubbed out.
 */
					/* Advisory information */
#undef	_POSIX_ADVISORY_INFO
					/* asynchronous I/O is available */
#define	_POSIX_ASYNCHRONOUS_IO		200112L
					/* barriers */
#define	_POSIX_BARRIERS			200112L
					/* chown requires correct privileges */
#define	_POSIX_CHOWN_RESTRICTED		1
					/* clock selection */
#define	_POSIX_CLOCK_SELECTION		-1
					/* CPU type */
#undef	_POSIX_CPUTYPE
					/* file synchronization is available */
#define	_POSIX_FSYNC			1
					/* support IPv6 */
#define	_POSIX_IPV6			0
					/* job control is available */
#define	_POSIX_JOB_CONTROL		1
					/* memory mapped files */
#define	_POSIX_MAPPED_FILES		1
					/* memory locking whole address space */
#define	_POSIX_MEMLOCK			1
					/* memory locking address ranges */
#define	_POSIX_MEMLOCK_RANGE		1
					/* memory access protections */
#define	_POSIX_MEMORY_PROTECTION	1
					/* message passing is available */
#define	_POSIX_MESSAGE_PASSING		200112L
					/* monotonic clock */
#define	_POSIX_MONOTONIC_CLOCK		200112L
					/* too-long path comp generate errors */
#define	_POSIX_NO_TRUNC			1
					/* prioritized I/O */
#define	_POSIX_PRIORITIZED_IO		-1
					/* priority scheduling */
#define	_POSIX_PRIORITY_SCHEDULING	200112L
					/* raw sockets */
#define	_POSIX_RAW_SOCKETS		200112L
					/* read/write locks */
#define	_POSIX_READER_WRITER_LOCKS	200112L
					/* realtime signals */
#undef	_POSIX_REALTIME_SIGNALS
					/* regular expressions */
#define	_POSIX_REGEXP			1
					/* semaphores */
#define	_POSIX_SEMAPHORES		0
					/* shared memory objects */
#define	_POSIX_SHARED_MEMORY_OBJECTS	0
					/* shell */
#define	_POSIX_SHELL			1
					/* spin locks */
#define	_POSIX_SPIN_LOCKS		200112L
					/* sporadic server */
#undef	_POSIX_SPORADIC_SERVER
					/* synchronized I/O is available */
#define	_POSIX_SYNCHRONIZED_IO		1
					/* threads */
#define	_POSIX_THREADS			200112L
					/* pthread_attr for stack size */
#define	_POSIX_THREAD_ATTR_STACKSIZE	200112L
					/* pthread_attr for stack address */
#define	_POSIX_THREAD_ATTR_STACKADDR	200112L
					/* _r functions */
#define	_POSIX_THREAD_PRIO_PROTECT	200112L
					/* PTHREAD_PRIO_PROTECT */
#define	_POSIX_THREAD_SAFE_FUNCTIONS	200112L
					/* timeouts */
#undef	_POSIX_TIMEOUTS
					/* timers */
#define	_POSIX_TIMERS			200112L
					/* typed memory objects */
#undef	_POSIX_TYPED_MEMORY_OBJECTS
					/* may disable terminal spec chars */
#define	_POSIX_VDISABLE			__CAST(unsigned char, '\377')

					/* C binding */
#define	_POSIX2_C_BIND			200112L

					/* XPG4.2 shared memory */
#define	_XOPEN_SHM			0

/* access function */
#define	F_OK		0	/* test for existence of file */
#define	X_OK		0x01	/* test for execute or search permission */
#define	W_OK		0x02	/* test for write permission */
#define	R_OK		0x04	/* test for read permission */

/* whence values for lseek(2) */
#define	SEEK_SET	0	/* set file offset to offset */
#define	SEEK_CUR	1	/* set file offset to current plus offset */
#define	SEEK_END	2	/* set file offset to EOF plus offset */

#if defined(_NETBSD_SOURCE)
/* whence values for lseek(2); renamed by POSIX 1003.1 */
#define	L_SET		SEEK_SET
#define	L_INCR		SEEK_CUR
#define	L_XTND		SEEK_END

/*
 * fsync_range values.
 *
 * Note the following flag values were chosen to not overlap
 * values for SEEK_XXX flags.  While not currently implemented,
 * it is possible to extend this call to respect SEEK_CUR and
 * SEEK_END offset addressing modes.
 */
#define	FDATASYNC	0x0010	/* sync data and minimal metadata */
#define	FFILESYNC	0x0020	/* sync data and metadata */
#define	FDISKSYNC	0x0040	/* flush disk caches after sync */
#endif

/* configurable pathname variables; use as argument to pathconf(3) */
#define	_PC_LINK_MAX		 1
#define	_PC_MAX_CANON		 2
#define	_PC_MAX_INPUT		 3
#define	_PC_NAME_MAX		 4
#define	_PC_PATH_MAX		 5
#define	_PC_PIPE_BUF		 6
#define	_PC_CHOWN_RESTRICTED	 7
#define	_PC_NO_TRUNC		 8
#define	_PC_VDISABLE		 9
#define	_PC_SYNC_IO		10
#define	_PC_FILESIZEBITS	11
#define	_PC_SYMLINK_MAX		12
#define	_PC_2_SYMLINKS		13
#define	_PC_ACL_EXTENDED	14

/* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */
#define	_PC_MIN_HOLE_SIZE	15

/* configurable system variables; use as argument to sysconf(3) */
/*
 * XXX The value of _SC_CLK_TCK is embedded in <time.h>.
 * XXX The value of _SC_PAGESIZE is embedded in <sys/shm.h>.
 */
#define	_SC_ARG_MAX		 1
#define	_SC_CHILD_MAX		 2
#define	_O_SC_CLK_TCK		 3 /* Old version, always 100 */
#define	_SC_NGROUPS_MAX		 4
#define	_SC_OPEN_MAX		 5
#define	_SC_JOB_CONTROL		 6
#define	_SC_SAVED_IDS		 7
#define	_SC_VERSION		 8
#define	_SC_BC_BASE_MAX		 9
#define	_SC_BC_DIM_MAX		10
#define	_SC_BC_SCALE_MAX	11
#define	_SC_BC_STRING_MAX	12
#define	_SC_COLL_WEIGHTS_MAX	13
#define	_SC_EXPR_NEST_MAX	14
#define	_SC_LINE_MAX		15
#define	_SC_RE_DUP_MAX		16
#define	_SC_2_VERSION		17
#define	_SC_2_C_BIND		18
#define	_SC_2_C_DEV		19
#define	_SC_2_CHAR_TERM		20
#define	_SC_2_FORT_DEV		21
#define	_SC_2_FORT_RUN		22
#define	_SC_2_LOCALEDEF		23
#define	_SC_2_SW_DEV		24
#define	_SC_2_UPE		25
#define	_SC_STREAM_MAX		26
#define	_SC_TZNAME_MAX		27
#define	_SC_PAGESIZE		28
#define	_SC_PAGE_SIZE		_SC_PAGESIZE	/* 1170 compatibility */
#define	_SC_FSYNC		29
#define	_SC_XOPEN_SHM		30
#define	_SC_SYNCHRONIZED_IO	31
#define	_SC_IOV_MAX		32
#define	_SC_MAPPED_FILES	33
#define	_SC_MEMLOCK		34
#define	_SC_MEMLOCK_RANGE	35
#define	_SC_MEMORY_PROTECTION	36
#define	_SC_LOGIN_NAME_MAX	37
#define	_SC_MONOTONIC_CLOCK	38
#define	_SC_CLK_TCK		39 /* New, variable version */
#define	_SC_ATEXIT_MAX		40
#define	_SC_THREADS		41
#define	_SC_SEMAPHORES		42
#define	_SC_BARRIERS		43
#define	_SC_TIMERS		44
#define	_SC_SPIN_LOCKS		45
#define	_SC_READER_WRITER_LOCKS	46
#define	_SC_GETGR_R_SIZE_MAX	47
#define	_SC_GETPW_R_SIZE_MAX	48
#define	_SC_CLOCK_SELECTION	49
#define	_SC_ASYNCHRONOUS_IO	50
#define	_SC_AIO_LISTIO_MAX	51
#define	_SC_AIO_MAX		52
#define	_SC_MESSAGE_PASSING	53
#define	_SC_MQ_OPEN_MAX		54
#define	_SC_MQ_PRIO_MAX		55
#define	_SC_PRIORITY_SCHEDULING	56
#define	_SC_THREAD_DESTRUCTOR_ITERATIONS 57
#define	_SC_THREAD_KEYS_MAX		58
#define	_SC_THREAD_STACK_MIN		59
#define	_SC_THREAD_THREADS_MAX		60
#define	_SC_THREAD_ATTR_STACKADDR	61
#define	_SC_THREAD_ATTR_STACKSIZE 	62
#define	_SC_THREAD_PRIORITY_SCHEDULING	63
#define	_SC_THREAD_PRIO_INHERIT 	64
#define	_SC_THREAD_PRIO_PROTECT		65
#define	_SC_THREAD_PROCESS_SHARED	66
#define	_SC_THREAD_SAFE_FUNCTIONS	67
#define	_SC_TTY_NAME_MAX		68
#define	_SC_HOST_NAME_MAX		69
#define	_SC_PASS_MAX			70
#define	_SC_REGEXP			71
#define	_SC_SHELL			72
#define	_SC_SYMLOOP_MAX			73

/* Actually, they are not supported or implemented yet */
#define	_SC_V6_ILP32_OFF32		74
#define	_SC_V6_ILP32_OFFBIG		75
#define	_SC_V6_LP64_OFF64		76
#define	_SC_V6_LPBIG_OFFBIG		77
#define	_SC_2_PBS			80
#define	_SC_2_PBS_ACCOUNTING		81
#define	_SC_2_PBS_CHECKPOINT		82
#define	_SC_2_PBS_LOCATE		83
#define	_SC_2_PBS_MESSAGE		84
#define	_SC_2_PBS_TRACK			85

/* These are implemented */
#define	_SC_SPAWN			86
#define	_SC_SHARED_MEMORY_OBJECTS	87

#define	_SC_TIMER_MAX			88
#define	_SC_SEM_NSEMS_MAX		89
#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

#ifdef _NETBSD_SOURCE
/* Commonly provided sysconf() extensions */
#define	_SC_NPROCESSORS_CONF	1001
#define	_SC_NPROCESSORS_ONLN	1002
/* Native variables */
#define	_SC_SCHED_RT_TS		2001
#define	_SC_SCHED_PRI_MIN	2002
#define	_SC_SCHED_PRI_MAX	2003
#endif	/* _NETBSD_SOURCE */

/* configurable system strings */
#define	_CS_PATH		 1

#endif /* !_SYS_UNISTD_H_ */


Home | Main Index | Thread Index | Old Index