From: Nathan F. <nf...@us...> - 2005-08-19 22:21:19
|
Update of /cvsroot/sbcl/sbcl/src/runtime In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21308/src/runtime Modified Files: cheneygc.c interrupt.c mips-arch.c mips-linux-os.c thread.c linux-nm mips-assem.S mips-lispregs.h Log Message: 0.9.3.69: THS patch-mania (from sbcl-devel, title and date as noted): * "Fix race condition for initial thread startup", 16 August 2005; * "Make internal startup functions in thread.c static", 16 August 2005; * "Minor MIPS code improvements", 16 August 2005; * "MIPS C runtime fixes", 19 August 2005 * "Support stack-allocated closures on MIPS", 19 August 2005; * "Assorted minor (non-)changes", 19 August 2005. Index: cheneygc.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/cheneygc.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- cheneygc.c 14 Jul 2005 15:41:11 -0000 1.16 +++ cheneygc.c 19 Aug 2005 22:21:02 -0000 1.17 @@ -48,7 +48,6 @@ static void scavenge_newspace(void); static void scavenge_interrupt_contexts(void); -extern struct interrupt_data * global_interrupt_data; extern unsigned long bytes_consed_between_gcs; @@ -125,8 +124,7 @@ unsigned long control_stack_size, binding_stack_size; sigset_t tmp, old; struct thread *th=arch_os_get_current_thread(); - struct interrupt_data *data= - th ? th->interrupt_data : global_interrupt_data; + struct interrupt_data *data=th->interrupt_data; #ifdef PRINTNOISE Index: interrupt.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v retrieving revision 1.86 retrieving revision 1.87 diff -u -d -r1.86 -r1.87 --- interrupt.c 19 Aug 2005 14:25:29 -0000 1.86 +++ interrupt.c 19 Aug 2005 22:21:02 -0000 1.87 @@ -630,13 +630,15 @@ { os_context_t *context = (os_context_t*)void_context; struct thread *thread=arch_os_get_current_thread(); + struct interrupt_data *data= + thread ? thread->interrupt_data : global_interrupt_data; #ifdef LISP_FEATURE_LINUX os_restore_fp_control(context); #endif check_blockables_blocked_or_lose(); check_interrupts_enabled_or_lose(context); - (*thread->interrupt_data->interrupt_low_level_handlers[signal]) + (*data->interrupt_low_level_handlers[signal]) (signal, info, void_context); #ifdef LISP_FEATURE_DARWIN /* Work around G5 bug */ @@ -649,7 +651,8 @@ { os_context_t *context = arch_os_get_context(&void_context); struct thread *thread=arch_os_get_current_thread(); - struct interrupt_data *data=thread->interrupt_data; + struct interrupt_data *data= + thread ? thread->interrupt_data : global_interrupt_data; #ifdef LISP_FEATURE_LINUX os_restore_fp_control(context); #endif Index: mips-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/mips-arch.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- mips-arch.c 14 Jul 2005 15:41:20 -0000 1.11 +++ mips-arch.c 19 Aug 2005 22:21:02 -0000 1.12 @@ -35,9 +35,30 @@ /* Classic CMUCL comment: Finding the bad address on the mips is easy. */ - return (os_vm_address_t) siginfo->si_addr; + return (os_vm_address_t)siginfo->si_addr; +} + +static inline unsigned int +os_context_register(os_context_t *context, int offset) +{ + return (unsigned int)(*os_context_register_addr(context, offset)); +} + +static inline unsigned int +os_context_pc(os_context_t *context) +{ + return (unsigned int)(*os_context_pc_addr(context)); +} + +static inline unsigned int +os_context_insn(os_context_t *context) +{ + return *(unsigned int *)(os_context_pc(context)); } +/* This function is somewhat misnamed, it actually just jumps to the + correct target address without attempting to execute the delay slot. + For other instructions it just increments the returned PC value. */ static unsigned int emulate_branch(os_context_t *context, unsigned int inst) { @@ -46,64 +67,69 @@ unsigned int r2 = (inst >> 16) & 0x1f; unsigned int r3 = (inst >> 11) & 0x1f; unsigned int disp = ((inst&(1<<15)) ? inst | (-1 << 16) : inst&0x7fff) << 2; - unsigned int jtgt = (*os_context_pc_addr(context) & ~0x0fffffff) | (inst&0x3ffffff) << 2; - unsigned int tgt = *os_context_pc_addr(context); + unsigned int jtgt = (os_context_pc(context) & ~0x0fffffff) | (inst&0x3ffffff) << 2; + unsigned int tgt = os_context_pc(context); switch(opcode) { case 0x0: /* jr, jalr */ switch(inst & 0x3f) { case 0x08: /* jr */ - tgt = *os_context_register_addr(context, r1); + tgt = os_context_register(context, r1); break; case 0x09: /* jalr */ - tgt = *os_context_register_addr(context, r1); + tgt = os_context_register(context, r1); *os_context_register_addr(context, r3) - = *os_context_pc_addr(context) + 4; + = os_context_pc(context) + 4; + break; + default: + tgt += 4; break; } break; case 0x1: /* bltz, bgez, bltzal, bgezal */ switch((inst >> 16) & 0x1f) { case 0x00: /* bltz */ - if(*os_context_register_addr(context, r1) < 0) + if(os_context_register(context, r1) < 0) tgt += disp; break; case 0x01: /* bgez */ - if(*os_context_register_addr(context, r1) >= 0) + if(os_context_register(context, r1) >= 0) tgt += disp; break; case 0x10: /* bltzal */ - if(*os_context_register_addr(context, r1) < 0) + if(os_context_register(context, r1) < 0) tgt += disp; *os_context_register_addr(context, 31) - = *os_context_pc_addr(context) + 4; + = os_context_pc(context) + 4; break; case 0x11: /* bgezal */ - if(*os_context_register_addr(context, r1) >= 0) + if(os_context_register(context, r1) >= 0) tgt += disp; *os_context_register_addr(context, 31) - = *os_context_pc_addr(context) + 4; + = os_context_pc(context) + 4; + break; + default: /* conditional branches/traps for > MIPS I, ignore for now. */ break; } break; case 0x4: /* beq */ - if(*os_context_register_addr(context, r1) - == *os_context_register_addr(context, r2)) + if(os_context_register(context, r1) + == os_context_register(context, r2)) tgt += disp; break; case 0x5: /* bne */ - if(*os_context_register_addr(context, r1) - != *os_context_register_addr(context, r2)) + if(os_context_register(context, r1) + != os_context_register(context, r2)) tgt += disp; break; case 0x6: /* blez */ - if(*os_context_register_addr(context, r1) - <= *os_context_register_addr(context, r2)) + if(os_context_register(context, r1) + <= os_context_register(context, r2)) tgt += disp; break; case 0x7: /* bgtz */ - if(*os_context_register_addr(context, r1) - > *os_context_register_addr(context, r2)) + if(os_context_register(context, r1) + > os_context_register(context, r2)) tgt += disp; break; case 0x2: /* j */ @@ -112,7 +138,10 @@ case 0x3: /* jal */ tgt = jtgt; *os_context_register_addr(context, 31) - = *os_context_pc_addr(context) + 4; + = os_context_pc(context) + 4; + break; + default: + tgt += 4; break; } return tgt; @@ -122,33 +151,23 @@ arch_skip_instruction(os_context_t *context) { /* Skip the offending instruction */ - if (os_context_bd_cause(context)) { - /* Currently, we never get here, because Linux' support for - bd_cause seems not terribly solid (c.f os_context_bd_cause - in mips-linux-os.c). If a port to Irix comes along, this - code will be executed, because presumably Irix' support is - better (it can hardly be worse). We lose() to remind the - porter to review this code. -- CSR, 2002-09-06 */ - lose("bd_cause branch taken; review code for new OS?\n"); - *os_context_pc_addr(context) - = emulate_branch(context, *os_context_pc_addr(context)); - } else - *os_context_pc_addr(context) += 4; + *os_context_pc_addr(context) + = emulate_branch(context, os_context_insn(context)); } unsigned char * arch_internal_error_arguments(os_context_t *context) { if (os_context_bd_cause(context)) - return (unsigned char *)(*os_context_pc_addr(context) + 8); + return (unsigned char *)(os_context_pc(context) + 8); else - return (unsigned char *)(*os_context_pc_addr(context) + 4); + return (unsigned char *)(os_context_pc(context) + 4); } boolean arch_pseudo_atomic_atomic(os_context_t *context) { - return *os_context_register_addr(context, reg_ALLOC) & 1; + return os_context_register(context, reg_ALLOC) & 1; } void @@ -161,8 +180,29 @@ arch_install_breakpoint(void *pc) { unsigned int *ptr = (unsigned int *)pc; - unsigned long result = (unsigned long) *ptr; + unsigned long result; + + /* Don't install over a branch/jump. */ + switch (*ptr >> 26) { + case 0x0: /* immediate jumps */ + switch (*ptr & 0x3f) { + case 0x08: + case 0x09: + ptr++; + } + break; + /* branches and register jumps */ + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + ptr++; + } + result = (unsigned long) *ptr; *ptr = (trap_Breakpoint << 16) | 0xd; os_flush_icache((os_vm_address_t)ptr, sizeof(unsigned int)); @@ -184,10 +224,9 @@ void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst) { - unsigned int *pc = (unsigned int *)*os_context_pc_addr(context); + unsigned int *pc = (unsigned int *)os_context_pc(context); unsigned int *break_pc, *next_pc; unsigned int next_inst; - int opcode; orig_sigmask = *os_context_sigmask_addr(context); sigaddset_blockable(os_context_sigmask_addr(context)); @@ -196,8 +235,7 @@ if (os_context_bd_cause(context)) { break_pc = pc+1; next_inst = *pc; - } - else { + } else { break_pc = pc; next_inst = orig_inst; } @@ -207,11 +245,7 @@ skipped_break_addr = break_pc; /* Figure out where it goes. */ - opcode = next_inst >> 26; - if (opcode == 1 || ((opcode & 0x3c) == 0x4) || ((next_inst & 0xf00e0000) == 0x80000000)) - next_pc = (unsigned int *)emulate_branch(context, next_inst); - else - next_pc = pc+1; + next_pc = (unsigned int *)emulate_branch(context, next_inst); displaced_after_inst = arch_install_breakpoint(next_pc); } @@ -229,9 +263,7 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); - unsigned int code; - - code = ((*(int *) (*os_context_pc_addr(context))) >> 16) & 0x1f; + unsigned int code = (os_context_insn(context) >> 16) & 0x1f; switch (code) { case trap_Halt: @@ -245,7 +277,7 @@ case trap_Error: case trap_Cerror: - interrupt_internal_error(signal, info, context, code==trap_Cerror); + interrupt_internal_error(signal, info, context, code == trap_Cerror); break; case trap_Breakpoint: @@ -253,8 +285,9 @@ break; case trap_FunEndBreakpoint: - *os_context_pc_addr(context) = (int)handle_fun_end_breakpoint(signal, info, context); - os_flush_icache((os_vm_address_t)*os_context_pc_addr(context), sizeof(unsigned int)); + *os_context_pc_addr(context) + = (os_context_register_t)(unsigned int) + handle_fun_end_breakpoint(signal, info, context); break; case trap_AfterBreakpoint: @@ -284,13 +317,13 @@ unsigned int bad_inst; unsigned int op, rs, rt, rd, funct, dest = 32; int immed; - unsigned int result; + int result; os_context_t *context = arch_os_get_context(&void_context); if (os_context_bd_cause(context)) - bad_inst = *(unsigned int *)(*os_context_pc_addr(context) + 4); + bad_inst = *(unsigned int *)(os_context_pc(context) + 4); else - bad_inst = *(unsigned int *)(*os_context_pc_addr(context)); + bad_inst = os_context_insn(context); op = (bad_inst >> 26) & 0x3f; rs = (bad_inst >> 21) & 0x1f; @@ -303,50 +336,43 @@ case 0x0: /* SPECIAL */ switch (funct) { case 0x20: /* ADD */ - /* FIXME: Hopefully, this whole section can just go away, - with the rewrite of pseudo-atomic and the deletion of - overflow VOPs */ - /* Check to see if this is really a pa_interrupted hit */ - if (rs == reg_ALLOC && rt == reg_NL4) { - *os_context_register_addr(context, reg_ALLOC) - += *os_context_register_addr(context, reg_NL4) &= ~(-1LL<<31); - arch_skip_instruction(context); - interrupt_handle_pending(context); - return; - } - result = FIXNUM_VALUE(*os_context_register_addr(context, rs)) - + FIXNUM_VALUE(*os_context_register_addr(context, rt)); + result = FIXNUM_VALUE(os_context_register(context, rs)) + + FIXNUM_VALUE(os_context_register(context, rt)); dest = rd; break; case 0x22: /* SUB */ - result = FIXNUM_VALUE(*os_context_register_addr(context, rs)) - - FIXNUM_VALUE(*os_context_register_addr(context, rt)); + result = FIXNUM_VALUE(os_context_register(context, rs)) + - FIXNUM_VALUE(os_context_register(context, rt)); dest = rd; break; + + default: + interrupt_handle_now(signal, info, context); + return; } break; case 0x8: /* ADDI */ - result = FIXNUM_VALUE(*os_context_register_addr(context,rs)) + (immed>>2); + result = FIXNUM_VALUE(os_context_register(context,rs)) + + (immed >> N_FIXNUM_TAG_BITS); dest = rt; break; - } - if (dest < 32) { - dynamic_space_free_pointer = - (lispobj *) *os_context_register_addr(context,reg_ALLOC); + default: + interrupt_handle_now(signal, info, context); + return; + } - *os_context_register_addr(context,dest) = alloc_number(result); + dynamic_space_free_pointer = + (lispobj *)(unsigned int)*os_context_register_addr(context,reg_ALLOC); - *os_context_register_addr(context, reg_ALLOC) = - (unsigned int) dynamic_space_free_pointer; + *os_context_register_addr(context,dest) = alloc_number(result); - arch_skip_instruction(context); + *os_context_register_addr(context, reg_ALLOC) = + (unsigned int) dynamic_space_free_pointer; - } - else - interrupt_handle_now(signal, info, context); + arch_skip_instruction(context); } void Index: mips-linux-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/mips-linux-os.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- mips-linux-os.c 14 Jul 2005 15:41:20 -0000 1.7 +++ mips-linux-os.c 19 Aug 2005 22:21:02 -0000 1.8 @@ -37,6 +37,9 @@ /* for cacheflush() */ #include <sys/cachectl.h> +/* for BD_CAUSE */ +#include <asm/mipsregs.h> + #include "validate.h" size_t os_vm_page_size; @@ -82,6 +85,7 @@ os_context_fp_control(os_context_t *context) { /* FIXME: Probably do something. */ + return 0; } void @@ -101,12 +105,34 @@ loop" where a (BREAK 16) not in a branch delay slot would have CAUSEF_BD filled. So, we comment - #include <asm/mipsregs.h> - return (((struct sigcontext *) &(context->uc_mcontext))->sc_cause & CAUSEF_BD); out and return 0 always. -- CSR, 2002-09-02 */ + /* Unfortunately, returning 0 fails for taken branches because + os_context_bd_cause is also used to find out if a branch + emulation is needed. We work around that by checking if the + current instruction is a jump or a branch. */ + unsigned int inst = *((unsigned int *)(unsigned int)(*os_context_pc_addr(context))); + + switch (inst >> 26) { + case 0x0: /* immediate jumps */ + switch (inst & 0x3f) { + case 0x08: + case 0x09: + return CAUSEF_BD; + } + break; + /* branches and register jumps */ + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + return CAUSEF_BD; + } return 0; } Index: thread.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/thread.c,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- thread.c 19 Aug 2005 15:14:17 -0000 1.48 +++ thread.c 19 Aug 2005 22:21:02 -0000 1.49 @@ -75,7 +75,7 @@ extern lispobj call_into_lisp_first_time(lispobj fun, lispobj *args, int nargs); #endif -int +static int initial_thread_trampoline(struct thread *th) { lispobj function; @@ -256,7 +256,8 @@ return th; } -void link_thread(struct thread *th,os_thread_t kid_tid) +static void +link_thread(struct thread *th,os_thread_t kid_tid) { if (all_threads) all_threads->prev=th; th->next=all_threads; Index: linux-nm =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/linux-nm,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- linux-nm 12 Jun 2005 22:08:23 -0000 1.3 +++ linux-nm 19 Aug 2005 22:21:02 -0000 1.4 @@ -3,5 +3,7 @@ # " A " used to be in the set of removed symbols, but it turns out # that the alpha implementation of closure_tramp and undefined_tramp # is as an A. Whatever that is. CSR, 2005-06-12. +# " A " is a global absolute symbol, that is a symbol with a fixed +# assembly time value (which is used for offset calculations). nm -p "$@" | grep -v " [abcdgIiNnrstUuvw?-] " Index: mips-assem.S =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/mips-assem.S,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- mips-assem.S 28 Jul 2005 14:23:32 -0000 1.7 +++ mips-assem.S 19 Aug 2005 22:21:02 -0000 1.8 @@ -358,19 +358,33 @@ .word NIL /* arglist */ .word NIL /* type */ LEAF(undefined_tramp) - break trap_Error - .byte 4 - .byte UNDEFINED_FUN_ERROR - .byte 254 - .byte (0xc0 + sc_DescriptorReg) - .byte 1 + .set noreorder + /* Continuable errors break here for some reason. + b 1f + break trap_Cerror */ + break trap_Error + /* Error data length. */ + .byte 4 + /* Error number. */ + .byte UNDEFINED_FUN_ERROR + /* Magic value 254 means a 16bit little endian value follows. + See interr.c:describe_internal_error. */ + .byte 254 + /* reg_FDEFN is #14. */ + .byte ((14 << 5) + sc_DescriptorReg) % 0x100 + .byte ((14 << 5) + sc_DescriptorReg) / 0x100 .align 2 + .set reorder +1: lw reg_LIP, FDEFN_RAW_ADDR_OFFSET(reg_FDEFN) + jr reg_LIP END(undefined_tramp) /* * The closure trampoline. */ - .align 2 + .align 5 /* common MIPS cacheline size */ + .word 0 /* pad 1 */ + .word 0 /* pad 2 */ .word SIMPLE_FUN_HEADER_WIDETAG /* header */ .word closure_tramp - SIMPLE_FUN_CODE_OFFSET /* self */ .word NIL /* next */ @@ -387,7 +401,7 @@ /* * Function-end breakpoint magic. */ - .align 3 + .align 2 LEAF(fun_end_breakpoint_guts) .set noreorder .word RETURN_PC_HEADER_WIDETAG Index: mips-lispregs.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/mips-lispregs.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- mips-lispregs.h 14 Jul 2005 15:41:20 -0000 1.3 +++ mips-lispregs.h 19 Aug 2005 22:21:02 -0000 1.4 @@ -51,6 +51,3 @@ reg_A0, reg_A1, reg_A2, reg_A3, reg_A4, reg_A5, reg_FDEFN, reg_LEXENV, \ reg_NFP, reg_OCFP, reg_LRA, reg_L0, reg_L1, reg_CODE \ } - -#define SC_REG(sc, n) ((sc)->sc_regs[n]) -#define SC_PC(sc) ((sc)->sc_pc) |