diff --git a/headers/os/support/Errors.h b/headers/os/support/Errors.h index 2b0d86dacd..ebcb9787ab 100644 --- a/headers/os/support/Errors.h +++ b/headers/os/support/Errors.h @@ -178,10 +178,6 @@ enum { #define EOPNOTSUPP (B_POSIX_ERROR_BASE + 43) #define ENOTSOCK (B_POSIX_ERROR_BASE + 44) -#define ERESTARTSYS (B_POSIX_ERROR_BASE + 45) -#define ERESTARTNOINTR (B_POSIX_ERROR_BASE + 46) -#define ERESTARTNOHAND (B_POSIX_ERROR_BASE + 47) - #define ENOMEM B_NO_MEMORY #define EACCES B_PERMISSION_DENIED #define EINTR B_INTERRUPTED diff --git a/headers/posix/signal.h b/headers/posix/signal.h index 1477d82f80..28bc04aada 100644 --- a/headers/posix/signal.h +++ b/headers/posix/signal.h @@ -120,6 +120,9 @@ typedef struct stack_t { #define SA_RESTART 0x08 #define SA_STACK 0x10 +#ifdef __cplusplus +extern "C" { +#endif int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); int sigemptyset(sigset_t *set); @@ -162,5 +165,167 @@ int sigsuspend(const sigset_t *mask); int kill(pid_t pid, int sig); int send_signal(pid_t tid, uint sig); +#ifdef __cplusplus +} +#endif + +/* signal handlers get this as the last argument */ +typedef struct vregs vregs; + +#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_ */ diff --git a/src/kernel/apps/sig_test.c b/src/kernel/apps/sig_test.c index 30770001c0..161fd1d26b 100644 --- a/src/kernel/apps/sig_test.c +++ b/src/kernel/apps/sig_test.c @@ -10,19 +10,26 @@ #include -void sig_handler(int); -void alarm_handler(int); -void install_handler(int, __signal_func_ptr); +typedef void (*beos_signal_func_ptr)(int, void *, struct vregs *); + + +void sig_handler(int, void *data, struct vregs *regs); +void alarm_handler(int, void *data, struct vregs *regs); +void install_handler(int, beos_signal_func_ptr); int32 thread(void *); void usage(void); void -sig_handler(int sig) +sig_handler(int sig, void *data, struct vregs *regs) { int i; + char buffer[10]; + memcpy(buffer, data, 10); + buffer[9] = '\0'; printf("sig_test (sig_handler): Received signal #%d...\n", sig); + printf("User data at %p (contents: \"%s\"), vregs at %p\n", data, buffer, regs); printf("Counting for fun: "); for (i=0; i<10; i++) printf("%d ", i); @@ -31,22 +38,23 @@ sig_handler(int sig) void -alarm_handler(int sig) +alarm_handler(int sig, void *data, struct vregs *regs) { printf("Alarm!\n"); } void -install_handler(int sig, __signal_func_ptr handler) +install_handler(int sig, beos_signal_func_ptr handler) { struct sigaction newa; struct sigaction olda; memset(&newa, 0, sizeof(newa)); - newa.sa_handler = handler; + newa.sa_handler = (__signal_func_ptr)handler; newa.sa_flags = SA_NOMASK | SA_RESTART; + newa.sa_userdata = "test!"; if (sys_sigaction(sig, &newa, &olda) < 0) { printf("Failed installing handler for sig #%d!\n", sig); @@ -71,8 +79,8 @@ usage() { printf("usage: sig_test \n" "where `mode' is one of:\n" - "\t1\tInstalls one handler for all signals\n" - "\t2\tSame as 1 but also spawns 5 threads with no active handlers\n" + "\t1\tInstalls one handler for all signals and spawns 5 threads\n" + "\t2\tSame as 1 but does not spawn additional threads\n" "\t3\tSets an alarm via set_alarm\n" "\n"); exit(1); diff --git a/src/kernel/core/arch/x86/arch_interrupts.S b/src/kernel/core/arch/x86/arch_interrupts.S index 639a3ea4ca..de6cd0c778 100755 --- a/src/kernel/core/arch/x86/arch_interrupts.S +++ b/src/kernel/core/arch/x86/arch_interrupts.S @@ -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 diff --git a/src/kernel/core/arch/x86/arch_thread.c b/src/kernel/core/arch/x86/arch_thread.c index c10748a91e..1f20a5ff3a 100755 --- a/src/kernel/core/arch/x86/arch_thread.c +++ b/src/kernel/core/arch/x86/arch_thread.c @@ -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 *)(®s->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 *)(®s->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"); } diff --git a/src/kernel/core/syscalls.c b/src/kernel/core/syscalls.c index 66bb1372c4..31712710a2 100644 --- a/src/kernel/core/syscalls.c +++ b/src/kernel/core/syscalls.c @@ -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: