support sigaltstack

This commit is contained in:
Tomoki Shirasawa
2014-06-25 13:45:33 +09:00
parent bbb7f77706
commit 770eae0186
5 changed files with 59 additions and 25 deletions

View File

@ -33,31 +33,28 @@ struct sigaction {
sigset_t sa_mask;
};
//// work in progress
struct sigbackup {
unsigned long rc; // return code of rt_sigreturn (rax)
void *uctx;
sigset_t mask;
double fpregs[16];
};
////
#define SA_NOCLDSTOP 0x00000001u
#define SA_NOCLDWAIT 0x00000002u
#define SA_NODEFER 0x40000000u
#define SA_ONSTACK 0x08000000u
#define SA_RESETHAND 0x80000000u
#define SA_RESTART 0x10000000u
#define SA_SIGINFO 0x00000004u
struct k_sigaction {
struct sigaction sa;
};
struct sigstack {
void *ss_sp;
int ss_onstack;
};
typedef struct sigaltstack {
void *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
#define MINSIGSTKSZ 2048
#define SS_ONSTACK 1
#define SS_DISABLE 2
typedef union sigval {
int sival_int;
void *sival_ptr;

View File

@ -121,6 +121,8 @@ fault:
struct sigsp {
struct x86_regs regs;
unsigned long sigrc;
unsigned long sigmask;
int ssflags;
};
SYSCALL_DECLARE(rt_sigreturn)
@ -133,8 +135,9 @@ SYSCALL_DECLARE(rt_sigreturn)
asm("movq %%gs:132, %0" : "=r" (regs));
--regs;
proc->sigmask.__val[0] = proc->supmask.__val[0];
sigsp = (struct sigsp *)regs->rsp;
proc->sigmask.__val[0] = sigsp->sigmask;
proc->sigstack.ss_flags = sigsp->ssflags;
if(copy_from_user(proc, regs, &sigsp->regs, sizeof(struct x86_regs)))
return rc;
copy_from_user(proc, &rc, &sigsp->sigrc, sizeof(long));
@ -178,8 +181,20 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
else if(k->sa.sa_handler){
unsigned long *usp; /* user stack */
struct sigsp *sigsp;
int ssflags = proc->sigstack.ss_flags;
unsigned long mask = (unsigned long)proc->sigmask.__val[0];
usp = (unsigned long *)regs->rsp;
if((k->sa.sa_flags & SA_ONSTACK) &&
!(proc->sigstack.ss_flags & SS_DISABLE) &&
!(proc->sigstack.ss_flags & SS_ONSTACK)){
unsigned long lsp;
lsp = ((unsigned long)(((char *)proc->sigstack.ss_sp) + proc->sigstack.ss_size)) & 0xfffffffffffffff8UL;
usp = (unsigned long *)lsp;
proc->sigstack.ss_flags |= SS_ONSTACK;
}
else{
usp = (unsigned long *)regs->rsp;
}
sigsp = ((struct sigsp *)usp) - 1;
if(copy_to_user(proc, &sigsp->regs, regs, sizeof(struct x86_regs)) ||
copy_to_user(proc, &sigsp->sigrc, &rc, sizeof(long))){
@ -188,6 +203,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp);
return;
}
sigsp->sigmask = mask;
sigsp->ssflags = ssflags;
usp = (unsigned long *)sigsp;
usp--;
@ -197,8 +214,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
regs->rip = (unsigned long)k->sa.sa_handler;
regs->rsp = (unsigned long)usp;
kfree(pending);
proc->sigmask.__val[0] |= pending->sigmask.__val[0];
kfree(pending);
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
}
else{
@ -342,7 +359,7 @@ do_kill(int pid, int tid, int sig)
mask = __sigmask(sig);
pending = NULL;
rc = 0;
if(sig < 34){
if(sig < 33){ // SIGRTMIN - SIGRTMAX
list_for_each_entry(pending, head, list){
if(pending->sigmask.__val[0] == mask)
break;