/*	$NetBSD: signalvar.h,v 1.82 2011/11/18 03:34:13 christos 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 CIRCLEQ_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. */
};

/*
 * Storage for items that may be either per-LWP (1:1 threads) or
 * per-process (SA threads).
 */
typedef struct sigstore {
	stack_t		ss_stk;		/* p: sp & on stack state variable */
	sigset_t	ss_mask;	/* p: signal mask */
} sigstore_t;

/* 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;

/*
 * Machine-independent functions:
 */
int	coredump_netbsd(struct lwp *, void *);
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);
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 *);

void	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 *);

siginfo_t *siginfo_alloc(int);
void	siginfo_free(void *);

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

static inline void
ksiginfo_queue_drain(ksiginfoq_t *kq)
{
	if (!CIRCLEQ_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_ */
