Signals, 2nd pass: syscall restarting now only works on EINTR (removed other exotic retcodes like ERESTARTSYS); signal handlers now receive 3 args, and the vregs struct is used to save the signal context, making the system beos compatible.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1681 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
lillo
2002-10-26 13:31:22 +00:00
parent 702a9e2e58
commit 343b352fe1
6 changed files with 237 additions and 80 deletions
+1 -1
View File
@@ -157,7 +157,7 @@ FUNCTION(i386_stack_switch):
jmp *%edx
FUNCTION(i386_return_from_signal):
popl %eax // flush the only signal handler parameter
addl $12, %esp // Flushes the 3 arguments to sa_handler
movl $103, %eax // This syscall will restore the cpu context to the
movl $0, %ecx // one existing before calling the signal handler
lea 4(%esp), %edx
+54 -65
View File
@@ -202,63 +202,49 @@ void
arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig_mask)
{
struct iframe *frame = t->arch_info.current_iframe;
uint32 *stack = (uint32 *)frame->user_esp;
uint32 *code;
uint32 *fpu_state;
uint32 *stack_ptr = (uint32 *)frame->user_esp;
uint32 *code_ptr;
uint32 *regs_ptr;
struct vregs *regs;
if (frame->orig_eax >= 0) {
// we're coming from a syscall
switch (frame->eax) {
case ERESTARTNOHAND:
frame->eax = EINTR;
break;
case EINTR:
case ERESTARTSYS:
if (!(sa->sa_flags & SA_RESTART)) {
frame->eax = EINTR;
break;
}
/* fallthrough */
case ERESTARTNOINTR:
dprintf("### restarting syscall %d after signal %d\n", frame->orig_eax, sig);
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
break;
if ((frame->eax == EINTR) && (sa->sa_flags & SA_RESTART)) {
dprintf("### restarting syscall %d after signal %d\n", frame->orig_eax, sig);
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
}
}
stack -= 192;
code = stack + 25;
fpu_state = stack + 64;
stack_ptr -= 192;
code_ptr = stack_ptr + 32;
regs_ptr = stack_ptr + 64;
stack[0] = (uint32)code; // return address when sa_handler done
stack[1] = sig; // only argument to sa_handler
stack[2] = frame->gs;
stack[3] = frame->fs;
stack[4] = frame->es;
stack[5] = frame->ds;
stack[6] = frame->edi;
stack[7] = frame->esi;
stack[8] = frame->ebp;
stack[9] = frame->esp;
stack[10] = frame->ebx;
stack[11] = frame->edx;
stack[12] = frame->ecx;
stack[13] = frame->eax;
stack[18] = frame->eip;
stack[19] = frame->cs;
stack[20] = frame->flags;
stack[21] = frame->user_esp;
stack[22] = frame->user_ss;
stack[23] = sig_mask;
stack[24] = (uint32)fpu_state;
stack_ptr[0] = (uint32)code_ptr; // return address when sa_handler done
stack_ptr[1] = sig; // first argument to sa_handler
stack_ptr[2] = (uint32)sa->sa_userdata;// second argument to sa_handler
stack_ptr[3] = (uint32)regs_ptr; // third argument to sa_handler
stack_ptr[4] = sig_mask; // Old signal mask to restore
stack_ptr[5] = (uint32)regs_ptr; // Int frame + extra regs to restore
i386_fsave(fpu_state);
memcpy(code_ptr, i386_return_from_signal, (i386_end_return_from_signal - i386_return_from_signal));
memcpy(code, i386_return_from_signal, (i386_end_return_from_signal - i386_return_from_signal));
regs = (struct vregs *)regs_ptr;
regs->eip = frame->eip;
regs->eflags = frame->flags;
regs->eax = frame->eax;
regs->ecx = frame->ecx;
regs->edx = frame->edx;
regs->esp = frame->esp;
regs->_reserved_1 = frame->user_esp;
regs->_reserved_2[0] = frame->edi;
regs->_reserved_2[1] = frame->esi;
regs->_reserved_2[2] = frame->ebp;
i386_fsave((void *)(&regs->xregs));
frame->user_esp = (uint32)stack;
frame->user_esp = (uint32)stack_ptr;
frame->eip = (uint32)sa->sa_handler;
}
@@ -268,17 +254,29 @@ arch_restore_signal_frame(void)
{
struct thread *t = thread_get_current_thread();
struct iframe *frame;
uint32 fpu_state;
uint32 *stack;
struct vregs *regs;
dprintf("### arch_restore_signal_frame: entry\n");
frame = t->arch_info.current_iframe;
t->sig_block_mask = *((sigset_t *)((void *)frame->user_esp + sizeof(struct iframe))) & BLOCKABLE_SIGS;
fpu_state = *((uint32 *)((void *)frame->user_esp + sizeof(struct iframe) + sizeof(uint32)));
memcpy((void *)frame, (void *)frame->user_esp, sizeof(struct iframe));
stack = (uint32 *)frame->user_esp;
t->sig_block_mask = stack[0];
regs = (struct vregs *)stack[1];
frame->eip = regs->eip;
frame->flags = regs->eflags;
frame->eax = regs->eax;
frame->ecx = regs->ecx;
frame->edx = regs->edx;
frame->esp = regs->esp;
frame->user_esp = regs->_reserved_1;
frame->edi = regs->_reserved_2[0];
frame->esi = regs->_reserved_2[1];
frame->ebp = regs->_reserved_2[2];
i386_frstor((void *)fpu_state);
i386_frstor((void *)(&regs->xregs));
dprintf("### arch_restore_signal_frame: exit\n");
@@ -293,19 +291,10 @@ arch_check_syscall_restart(struct thread *t)
{
struct iframe *frame = t->arch_info.current_iframe;
dprintf("### arch_check_syscall_restart: entry\n");
if (frame->orig_eax >= 0) {
dprintf("### arch_check_syscall_restart: coming from a syscall\n");
if ((frame->eax == ERESTARTNOHAND) ||
(frame->eax == EINTR) ||
(frame->eax == ERESTARTSYS) ||
(frame->eax == ERESTARTNOINTR)) {
dprintf("### arch_check_syscall_restart: syscall restart needed\n");
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
}
if ((frame->orig_eax >= 0) && (frame->eax == EINTR)) {
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
}
dprintf("### arch_check_syscall_restart: exit\n");
}
-1
View File
@@ -201,7 +201,6 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
break;
case SYSCALL_EXIT_THREAD:
sys_exit_thread((status_t)arg0);
// thread_exit((int)arg0);
*call_ret = 0;
break;
case SYSCALL_CREATE_TEAM: