ish/kernel/signal.h
2020-03-08 23:02:09 +00:00

285 lines
6.5 KiB
C

#ifndef SIGNAL_H
#define SIGNAL_H
#include "misc.h"
#include "util/list.h"
#include "util/sync.h"
struct task;
typedef qword_t sigset_t_;
#define SIG_ERR_ -1
#define SIG_DFL_ 0
#define SIG_IGN_ 1
#define SA_SIGINFO_ 4
#define SA_NODEFER_ 0x40000000
struct sigaction_ {
addr_t handler;
dword_t flags;
addr_t restorer;
sigset_t_ mask;
} __attribute__((packed));
#define NUM_SIGS 64
#define SIGHUP_ 1
#define SIGINT_ 2
#define SIGQUIT_ 3
#define SIGILL_ 4
#define SIGTRAP_ 5
#define SIGABRT_ 6
#define SIGIOT_ 6
#define SIGBUS_ 7
#define SIGFPE_ 8
#define SIGKILL_ 9
#define SIGUSR1_ 10
#define SIGSEGV_ 11
#define SIGUSR2_ 12
#define SIGPIPE_ 13
#define SIGALRM_ 14
#define SIGTERM_ 15
#define SIGSTKFLT_ 16
#define SIGCHLD_ 17
#define SIGCONT_ 18
#define SIGSTOP_ 19
#define SIGTSTP_ 20
#define SIGTTIN_ 21
#define SIGTTOU_ 22
#define SIGURG_ 23
#define SIGXCPU_ 24
#define SIGXFSZ_ 25
#define SIGVTALRM_ 26
#define SIGPROF_ 27
#define SIGWINCH_ 28
#define SIGIO_ 29
#define SIGPWR_ 30
#define SIGSYS_ 31
#define SI_USER_ 0
#define SI_TIMER_ -2
#define SI_TKILL_ -6
#define SI_KERNEL_ 128
#define SEGV_MAPERR_ 1
#define SEGV_ACCERR_ 2
union sigval_ {
int_t sv_int;
addr_t sv_ptr;
};
struct siginfo_ {
int_t sig;
int_t sig_errno;
int_t code;
union {
struct {
pid_t_ pid;
uid_t_ uid;
} kill;
struct {
pid_t_ pid;
uid_t_ uid;
int_t status;
clock_t_ utime;
clock_t_ stime;
} child;
struct {
addr_t addr;
} fault;
struct {
addr_t addr;
int_t syscall;
} sigsys;
};
};
// a reasonable default siginfo
static const struct siginfo_ SIGINFO_NIL = {
.code = SI_KERNEL_,
};
struct sigqueue {
struct list queue;
struct siginfo_ info;
};
// send a signal
// you better make sure the task isn't gonna get freed under me (pids_lock or current)
void send_signal(struct task *task, int sig, struct siginfo_ info);
// send a signal without regard for whether the signal is blocked or ignored
void deliver_signal(struct task *task, int sig, struct siginfo_ info);
// send a signal to current if it's not blocked or ignored, return whether that worked
// exists specifically for sending SIGTTIN/SIGTTOU
bool try_self_signal(int sig);
// send a signal to all processes in a group, could return ESRCH
int send_group_signal(dword_t pgid, int sig, struct siginfo_ info);
// check for and deliver pending signals on current
// must be called without pids_lock, current->group->lock, or current->sighand->lock
void receive_signals(void);
// set the signal mask, restore it to what it was before on the next receive_signals call
void sigmask_set_temp(sigset_t_ mask);
struct sighand {
atomic_uint refcount;
struct sigaction_ action[NUM_SIGS];
addr_t altstack;
dword_t altstack_size;
lock_t lock;
};
struct sighand *sighand_new(void);
struct sighand *sighand_copy(struct sighand *sighand);
void sighand_release(struct sighand *sighand);
dword_t sys_rt_sigaction(dword_t signum, addr_t action_addr, addr_t oldaction_addr, dword_t sigset_size);
dword_t sys_sigaction(dword_t signum, addr_t action_addr, addr_t oldaction_addr);
dword_t sys_rt_sigreturn(void);
dword_t sys_sigreturn(void);
#define SIG_BLOCK_ 0
#define SIG_UNBLOCK_ 1
#define SIG_SETMASK_ 2
typedef uint64_t sigset_t_;
dword_t sys_rt_sigprocmask(dword_t how, addr_t set, addr_t oldset, dword_t size);
int_t sys_rt_sigpending(addr_t set_addr);
static inline sigset_t_ sig_mask(int sig) {
assert(sig >= 1 && sig < NUM_SIGS);
return 1l << (sig - 1);
}
static inline bool sigset_has(sigset_t_ set, int sig) {
return !!(set & sig_mask(sig));
}
static inline void sigset_add(sigset_t_ *set, int sig) {
*set |= sig_mask(sig);
}
static inline void sigset_del(sigset_t_ *set, int sig) {
*set &= ~sig_mask(sig);
}
struct stack_t_ {
addr_t stack;
dword_t flags;
dword_t size;
};
#define SS_ONSTACK_ 1
#define SS_DISABLE_ 2
#define MINSIGSTKSZ_ 2048
dword_t sys_sigaltstack(addr_t ss, addr_t old_ss);
int_t sys_rt_sigsuspend(addr_t mask_addr, uint_t size);
int_t sys_pause(void);
int_t sys_rt_sigtimedwait(addr_t set_addr, addr_t info_addr, addr_t timeout_addr, uint_t set_size);
dword_t sys_kill(pid_t_ pid, dword_t sig);
dword_t sys_tkill(pid_t_ tid, dword_t sig);
dword_t sys_tgkill(pid_t_ tgid, pid_t_ tid, dword_t sig);
// signal frame structs. There's a good chance this should go in its own header file
// thanks kernel for giving me something to copy/paste
struct sigcontext_ {
word_t gs, __gsh;
word_t fs, __fsh;
word_t es, __esh;
word_t ds, __dsh;
dword_t di;
dword_t si;
dword_t bp;
dword_t sp;
dword_t bx;
dword_t dx;
dword_t cx;
dword_t ax;
dword_t trapno;
dword_t err;
dword_t ip;
word_t cs, __csh;
dword_t flags;
dword_t sp_at_signal;
word_t ss, __ssh;
dword_t fpstate;
dword_t oldmask;
dword_t cr2;
};
struct ucontext_ {
uint_t flags;
uint_t link;
struct stack_t_ stack;
struct sigcontext_ mcontext;
sigset_t_ sigmask;
} __attribute__((packed));
struct fpreg_ {
word_t significand[4];
word_t exponent;
};
struct fpxreg_ {
word_t significand[4];
word_t exponent;
word_t padding[3];
};
struct xmmreg_ {
uint32_t element[4];
};
struct fpstate_ {
/* Regular FPU environment. */
dword_t cw;
dword_t sw;
dword_t tag;
dword_t ipoff;
dword_t cssel;
dword_t dataoff;
dword_t datasel;
struct fpreg_ st[8];
word_t status;
word_t magic;
/* FXSR FPU environment. */
dword_t _fxsr_env[6];
dword_t mxcsr;
dword_t reserved;
struct fpxreg_ fxsr_st[8];
struct xmmreg_ xmm[8];
dword_t padding[56];
};
struct sigframe_ {
addr_t restorer;
dword_t sig;
struct sigcontext_ sc;
struct fpstate_ fpstate;
dword_t extramask;
char retcode[8];
};
struct rt_sigframe_ {
addr_t restorer;
int_t sig;
addr_t pinfo;
addr_t puc;
union {
struct siginfo_ info;
char __pad[128];
};
struct ucontext_ uc;
char retcode[8];
};
// On a 64-bit system with 32-bit emulation, the fpu state is stored in extra
// space at the end of the frame, not in the frame itself. We store the fpu
// state in the frame where it should be, and ptraceomatic will set this. If
// they are set we'll add some padding to the bottom to the frame to make
// everything align.
extern int xsave_extra;
extern int fxsave_extra;
#endif