haiku/headers/posix/signal.h
Axel Dörfler a728651f04 Some more work on the signal code:
* get_signal_stack() checked the wrong sig_action field (index is signal-1), also,
  it had an off-by-one error in the stack range check.
* factored out a restart_syscall() function to avoid code duplication
* arch_setup_signal_frame() relied on the fact that vregs and the signal stack code
  is a multiple of 4 bytes in size.
* Fixed sigaction(): it did return the error code directly instead of setting errno.
* signal() actually had a work-around for the broken sigaction()...
* Replaced the sig_func_t typedef with a sighandler_t typedef - this is non-standard
  anyway, but now we're at least compatible with the GNU world instead of introducing
  our own solution (BSD seems to use sig_t here, BTW).
* Removed now unused sigval structure from the header; it should be added again as
  soon as we start supporting it.
* SA_RESETHAND and SA_ONESHOT are the same thing; the former did not work before.
* Made the non-standard SA_* flags refer to the standard ones instead of the other
  way around.
* Added a test application for various signal features - works fine under Haiku,
  tested also under Linux and BeOS (the latter fails as it does not support SA_RESTART).
  More tests should be added, though.
* Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21999 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-08-17 11:01:09 +00:00

420 lines
12 KiB
C

/*
* Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
#include <sys/types.h>
typedef int sig_atomic_t;
typedef long sigset_t;
typedef void (*sighandler_t)(int);
/* GNU-like signal handler typedef */
typedef void (*__signal_func_ptr)(int);
/* deprecated, for compatibility with BeOS only */
/* macros defining the standard signal handling behavior */
#define SIG_DFL ((sighandler_t)0) /* "default" signal behaviour */
#define SIG_IGN ((sighandler_t)1) /* ignore signal */
#define SIG_ERR ((sighandler_t)-1) /* an error occurred during signal processing */
#define SIG_HOLD ((sighandler_t)3) /* the signal was hold */
// TODO: support this structure!
typedef struct {
int si_signo; /* signal number */
int si_code; /* signal code */
int si_errno; /* if non zero, an error number associated with this signal */
pid_t si_pid; /* sending process ID */
uid_t si_uid; /* real user ID of sending process */
void *si_addr; /* address of faulting instruction */
int si_status; /* exit value or signal */
long si_band; /* band event for SIGPOLL */
} siginfo_t;
/*
* structure used by sigaction()
*
* Note: the 'sa_userdata' field is a non-POSIX extension.
* See the documentation for more info on this.
*/
struct sigaction {
sighandler_t sa_handler;
sigset_t sa_mask;
int sa_flags;
void *sa_userdata; /* will be passed to the signal handler */
};
/* values for sa_flags */
#define SA_NOCLDSTOP 0x01
#define SA_NOCLDWAIT 0x02
#define SA_RESETHAND 0x04
#define SA_NODEFER 0x08
#define SA_RESTART 0x10
#define SA_ONSTACK 0x20
#define SA_SIGINFO 0x40
#define SA_NOMASK SA_NODEFER
#define SA_STACK SA_ONSTACK
#define SA_ONESHOT SA_RESETHAND
/* values for ss_flags */
#define SS_ONSTACK 0x1
#define SS_DISABLE 0x2
#define MINSIGSTKSZ 4096
#define SIGSTKSZ 16384
/*
* for signals using an alternate stack
*/
typedef struct stack_t {
void *ss_sp;
size_t ss_size;
int ss_flags;
} stack_t;
typedef struct sigstack {
int ss_onstack;
void *ss_sp;
} sigstack;
/* for the 'how' arg of sigprocmask() */
#define SIG_BLOCK 1
#define SIG_UNBLOCK 2
#define SIG_SETMASK 3
/*
* The list of all defined signals:
*
* The numbering of signals for Haiku attempts to maintain
* some consistency with UN*X conventions so that things
* like "kill -9" do what you expect.
*/
#define SIGHUP 1 /* hangup -- tty is gone! */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* `quit' special character typed in tty */
#define SIGILL 4 /* illegal instruction */
#define SIGCHLD 5 /* child process exited */
#define SIGABRT 6 /* abort() called, dont' catch */
#define SIGPIPE 7 /* write to a pipe w/no readers */
#define SIGFPE 8 /* floating point exception */
#define SIGKILL 9 /* kill a team (not catchable) */
#define SIGSTOP 10 /* suspend a thread (not catchable) */
#define SIGSEGV 11 /* segmentation violation (read: invalid pointer) */
#define SIGCONT 12 /* continue execution if suspended */
#define SIGTSTP 13 /* `stop' special character typed in tty */
#define SIGALRM 14 /* an alarm has gone off (see alarm()) */
#define SIGTERM 15 /* termination requested */
#define SIGTTIN 16 /* read of tty from bg process */
#define SIGTTOU 17 /* write to tty from bg process */
#define SIGUSR1 18 /* app defined signal 1 */
#define SIGUSR2 19 /* app defined signal 2 */
#define SIGWINCH 20 /* tty window size changed */
#define SIGKILLTHR 21 /* be specific: kill just the thread, not team */
#define SIGTRAP 22 /* Trace/breakpoint trap */
#define SIGPOLL 23 /* Pollable event */
#define SIGPROF 24 /* Profiling timer expired */
#define SIGSYS 25 /* Bad system call */
#define SIGURG 26 /* High bandwidth data is available at socket */
#define SIGVTALRM 27 /* Virtual timer expired */
#define SIGXCPU 28 /* CPU time limit exceeded */
#define SIGXFSZ 29 /* File size limit exceeded */
#define SIGBUS SIGSEGV /* for old style code */
/*
* Signal numbers 30-32 are currently free but may be used in future
* releases. Use them at your own peril (if you do use them, at least
* be smart and use them backwards from signal 32).
*/
#define MAX_SIGNO 32 /* the most signals that a single thread can reference */
#define __signal_max 29 /* the largest signal number that is actually defined */
#define NSIG (__signal_max+1)
/* the number of defined signals */
/* the global table of text strings containing descriptions for each signal */
extern const char * const sys_siglist[NSIG];
#ifdef __cplusplus
extern "C" {
#endif
sighandler_t signal(int sig, sighandler_t signalHandler);
int raise(int sig);
int kill(pid_t pid, int sig);
int send_signal(pid_t tid, unsigned int sig);
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
int sigpending(sigset_t *set);
int sigsuspend(const sigset_t *mask);
int sigwait(const sigset_t *set, int *sig);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
const char *strsignal(int sig);
void set_signal_stack(void *ptr, size_t size);
int sigaltstack(const stack_t *ss, stack_t *oss);
/* pthread extension : equivalent of sigprocmask() */
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
extern inline int
sigismember(const sigset_t *set, int sig)
{
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
return (*set & mask) ? 1 : 0 ;
}
extern inline int
sigaddset(sigset_t *set, int sig)
{
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
return ((*set |= mask), 0) ;
}
extern inline int
sigdelset(sigset_t *set, int sig)
{
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
return ((*set &= ~mask), 0) ;
}
#ifdef __cplusplus
}
#endif
/* TODO: move this into the documentation!
* ==================================================
* !!! SPECIAL NOTES CONCERNING NON-POSIX EXTENSIONS:
* ==================================================
*
* The standard Posix interface for signal handlers is not as useful
* as it could be. The handler can define only one single argument
* (the signal number). For example:
* void
* my_signal_handler(int sig)
* {
* . . .
* }
*
* // install the handler
* signal(SIGINT, &my_signal_handler);
*
* The sigaction() function allows finer grained control of the signal
* handling. It also allows an opportunity, via the 'sigaction' struct, to
* enable additional data to be passed to the handler. For example:
* void
* my_signal_handler(int sig, char *userData, vregs regs)
* {
* . . .
* }
*
* struct sigaction sa;
* char data_buffer[32];
*
* sa.sa_handler = (sighandler_t)my_signal_handler;
* sigemptyset(&sa.sa_mask);
* sa.sa_userdata = userData;
*
* // install the handler
* sigaction(SIGINT, &sa, NULL);
*
* The two additional arguments available to the signal handler are extensions
* to the Posix standard. This feature was introduced by the BeOS and retained
* by Haiku. However, to remain compatible with Posix and ANSI C, the type
* of the sa_handler field is defined as 'sighandler_t'. This requires the handler
* to be cast when assigned to the sa_handler field, as in the example above.
*
* The 3 arguments that Haiku provides to signal handlers are as follows:
* 1) The first argument is the (usual) signal number.
*
* 2) The second argument is whatever value is put in the sa_userdata field
* of the sigaction struct.
*
* 3) The third argument is a pointer to a vregs struct (defined below).
* The vregs struct contains the contents of the volatile registers at
* the time the signal was delivered to your thread. You can change the fields
* of the structure. After your signal handler completes, the OS uses this struct
* to reload the registers for your thread (privileged registers are not loaded
* of course). The vregs struct is of course terribly machine dependent.
*/
/*
* the vregs struct:
*
* signal handlers get this as the last argument
*/
typedef struct vregs vregs;
// TODO: move those into an architecture specific header
#if __POWERPC__
struct vregs
{
ulong pc, /* program counter */
r0, /* scratch */
r1, /* stack ptr */
r2, /* TOC */
r3,r4,r5,r6,r7,r8,r9,r10, /* volatile regs */
r11,r12; /* scratch regs */
double f0, /* fp scratch */
f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13; /* fp volatile regs */
ulong filler1, /* place holder */
fpscr, /* fp condition codes */
ctr, xer, cr, msr, lr; /* misc. status */
};
#endif /* __POWERPC__ */
#if __INTEL__
typedef struct packed_fp_stack {
unsigned char st0[10];
unsigned char st1[10];
unsigned char st2[10];
unsigned char st3[10];
unsigned char st4[10];
unsigned char st5[10];
unsigned char st6[10];
unsigned char st7[10];
} packed_fp_stack;
typedef struct packed_mmx_regs {
unsigned char mm0[10];
unsigned char mm1[10];
unsigned char mm2[10];
unsigned char mm3[10];
unsigned char mm4[10];
unsigned char mm5[10];
unsigned char mm6[10];
unsigned char mm7[10];
} packed_mmx_regs;
typedef struct old_extended_regs {
unsigned short fp_control;
unsigned short _reserved1;
unsigned short fp_status;
unsigned short _reserved2;
unsigned short fp_tag;
unsigned short _reserved3;
unsigned long fp_eip;
unsigned short fp_cs;
unsigned short fp_opcode;
unsigned long fp_datap;
unsigned short fp_ds;
unsigned short _reserved4;
union {
packed_fp_stack fp;
packed_mmx_regs mmx;
} fp_mmx;
} old_extended_regs;
typedef struct fp_stack {
unsigned char st0[10];
unsigned char _reserved_42_47[6];
unsigned char st1[10];
unsigned char _reserved_58_63[6];
unsigned char st2[10];
unsigned char _reserved_74_79[6];
unsigned char st3[10];
unsigned char _reserved_90_95[6];
unsigned char st4[10];
unsigned char _reserved_106_111[6];
unsigned char st5[10];
unsigned char _reserved_122_127[6];
unsigned char st6[10];
unsigned char _reserved_138_143[6];
unsigned char st7[10];
unsigned char _reserved_154_159[6];
} fp_stack;
typedef struct mmx_regs {
unsigned char mm0[10];
unsigned char _reserved_42_47[6];
unsigned char mm1[10];
unsigned char _reserved_58_63[6];
unsigned char mm2[10];
unsigned char _reserved_74_79[6];
unsigned char mm3[10];
unsigned char _reserved_90_95[6];
unsigned char mm4[10];
unsigned char _reserved_106_111[6];
unsigned char mm5[10];
unsigned char _reserved_122_127[6];
unsigned char mm6[10];
unsigned char _reserved_138_143[6];
unsigned char mm7[10];
unsigned char _reserved_154_159[6];
} mmx_regs;
typedef struct xmmx_regs {
unsigned char xmm0[16];
unsigned char xmm1[16];
unsigned char xmm2[16];
unsigned char xmm3[16];
unsigned char xmm4[16];
unsigned char xmm5[16];
unsigned char xmm6[16];
unsigned char xmm7[16];
} xmmx_regs;
typedef struct new_extended_regs {
unsigned short fp_control;
unsigned short fp_status;
unsigned short fp_tag;
unsigned short fp_opcode;
unsigned long fp_eip;
unsigned short fp_cs;
unsigned short res_14_15;
unsigned long fp_datap;
unsigned short fp_ds;
unsigned short _reserved_22_23;
unsigned long mxcsr;
unsigned long _reserved_28_31;
union {
fp_stack fp;
mmx_regs mmx;
} fp_mmx;
xmmx_regs xmmx;
unsigned char _reserved_288_511[224];
} new_extended_regs;
typedef struct extended_regs {
union {
old_extended_regs old_format;
new_extended_regs new_format;
} state;
unsigned long format;
} extended_regs;
struct vregs {
unsigned long eip;
unsigned long eflags;
unsigned long eax;
unsigned long ecx;
unsigned long edx;
unsigned long esp;
unsigned long ebp;
unsigned long _reserved_1;
extended_regs xregs;
unsigned long _reserved_2[3];
};
#endif /* __INTEL__ */
#endif /* _SIGNAL_H_ */