X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgc-common.c;h=95b5c3b2702a0287401596fa7e4461158a13e3b0;hb=f71d9c8d57630ca41e149e03305e678cc3e7fc0f;hp=c99afb7122c95029d43d151f7fb08a001481b2b4;hpb=ab9c6bbaaa409e815a1c9696885c9621b429aed6;p=sbcl.git diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index c99afb7..95b5c3b 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -2514,7 +2514,7 @@ scrub_control_stack(void) #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK sp = (lispobj *)&sp - 1; #else - sp = current_control_stack_pointer; + sp = access_control_stack_pointer(th); #endif scrub: if ((((os_vm_address_t)sp < (hard_guard_page_address + os_vm_page_size)) && @@ -2548,88 +2548,160 @@ scrub_control_stack(void) #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) -/* scavenging interrupt contexts */ +/* Scavenging Interrupt Contexts */ static int boxed_registers[] = BOXED_REGISTERS; +/* The GC has a notion of an "interior pointer" register, an unboxed + * register that typically contains a pointer to inside an object + * referenced by another pointer. The most obvious of these is the + * program counter, although many compiler backends define a "Lisp + * Interior Pointer" register known to the runtime as reg_LIP, and + * various CPU architectures have other registers that also partake of + * the interior-pointer nature. As the code for pairing an interior + * pointer value up with its "base" register, and fixing it up after + * scavenging is complete is horribly repetitive, a few macros paper + * over the monotony. --AB, 2010-Jul-14 */ + +/* These macros are only ever used over a lexical environment which + * defines a pointer to an os_context_t called context, thus we don't + * bother to pass that context in as a parameter. */ + +/* Define how to access a given interior pointer. */ +#define ACCESS_INTERIOR_POINTER_pc \ + *os_context_pc_addr(context) +#define ACCESS_INTERIOR_POINTER_lip \ + *os_context_register_addr(context, reg_LIP) +#define ACCESS_INTERIOR_POINTER_lr \ + *os_context_lr_addr(context) +#define ACCESS_INTERIOR_POINTER_npc \ + *os_context_npc_addr(context) +#define ACCESS_INTERIOR_POINTER_ctr \ + *os_context_ctr_addr(context) + +#define INTERIOR_POINTER_VARS(name) \ + unsigned long name##_offset; \ + int name##_register_pair + +#define PAIR_INTERIOR_POINTER(name) \ + pair_interior_pointer(context, \ + ACCESS_INTERIOR_POINTER_##name, \ + &name##_offset, \ + &name##_register_pair) + +/* One complexity here is that if a paired register is not found for + * an interior pointer, then that pointer does not get updated. + * Originally, there was some commentary about using an index of -1 + * when calling os_context_register_addr() on SPARC referring to the + * program counter, but the real reason is to allow an interior + * pointer register to point to the runtime, read-only space, or + * static space without problems. */ +#define FIXUP_INTERIOR_POINTER(name) \ + do { \ + if (name##_register_pair >= 0) { \ + ACCESS_INTERIOR_POINTER_##name = \ + (*os_context_register_addr(context, \ + name##_register_pair) \ + & ~LOWTAG_MASK) \ + + name##_offset; \ + } \ + } while (0) + + static void -scavenge_interrupt_context(os_context_t *context) +pair_interior_pointer(os_context_t *context, unsigned long pointer, + unsigned long *saved_offset, int *register_pair) { int i; -#ifdef reg_LIP - unsigned long lip; - unsigned long lip_offset; - int lip_register_pair; -#endif - unsigned long pc_code_offset; - -#ifdef ARCH_HAS_LINK_REGISTER - unsigned long lr_code_offset; -#endif -#ifdef ARCH_HAS_NPC_REGISTER - unsigned long npc_code_offset; -#endif -#ifdef DEBUG_SCAVENGE_VERBOSE - fprintf(stderr, "Scavenging interrupt context at 0x%x\n",context); -#endif - -#ifdef reg_LIP - /* Find the LIP's register pair and calculate its offset */ - /* before we scavenge the context. */ - /* * I (RLT) think this is trying to find the boxed register that is * closest to the LIP address, without going past it. Usually, it's * reg_CODE or reg_LRA. But sometimes, nothing can be found. */ - lip = *os_context_register_addr(context, reg_LIP); /* 0x7FFFFFFF on 32-bit platforms; 0x7FFFFFFFFFFFFFFF on 64-bit platforms */ - lip_offset = (((unsigned long)1) << (N_WORD_BITS - 1)) - 1; - lip_register_pair = -1; - for (i = 0; i < (int)(sizeof(boxed_registers) / sizeof(int)); i++) { + *saved_offset = (((unsigned long)1) << (N_WORD_BITS - 1)) - 1; + *register_pair = -1; + for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) { unsigned long reg; - unsigned long offset; + long offset; int index; index = boxed_registers[i]; reg = *os_context_register_addr(context, index); - /* would be using PTR if not for integer length issues */ - if ((reg & ~((1L<uc_mcontext.gregs[2]. But gregs[2] is REG_nPC. Is - * that what we really want? My guess is that that is not what we - * want, so if lip_register_pair is -1, we don't touch reg_LIP at - * all. But maybe it doesn't really matter if LIP is trashed? - */ - if (lip_register_pair >= 0) { - *os_context_register_addr(context, reg_LIP) = - *os_context_register_addr(context, lip_register_pair) - + lip_offset; - } -#endif /* reg_LIP */ - - /* Fix the PC if it was in from space */ - if (from_space_p(*os_context_pc_addr(context))) - *os_context_pc_addr(context) = - *os_context_register_addr(context, reg_CODE) + pc_code_offset; - + FIXUP_INTERIOR_POINTER(lip); +#endif #ifdef ARCH_HAS_LINK_REGISTER - /* Fix the LR ditto; important if we're being called from - * an assembly routine that expects to return using blr, otherwise - * harmless */ - if (from_space_p(*os_context_lr_addr(context))) - *os_context_lr_addr(context) = - *os_context_register_addr(context, reg_CODE) + lr_code_offset; + FIXUP_INTERIOR_POINTER(lr); #endif - #ifdef ARCH_HAS_NPC_REGISTER - if (from_space_p(*os_context_npc_addr(context))) - *os_context_npc_addr(context) = - *os_context_register_addr(context, reg_CODE) + npc_code_offset; -#endif /* ARCH_HAS_NPC_REGISTER */ + FIXUP_INTERIOR_POINTER(npc); +#endif +#ifdef LISP_FEATURE_PPC + FIXUP_INTERIOR_POINTER(ctr); +#endif } -void scavenge_interrupt_contexts(struct thread *th) +void +scavenge_interrupt_contexts(struct thread *th) { int i, index; os_context_t *context; index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th)); -#ifdef DEBUG_SCAVENGE_VERBOSE - fprintf(stderr, "%d interrupt contexts to scan\n",index); +#if defined(DEBUG_PRINT_CONTEXT_INDEX) + printf("Number of active contexts: %d\n", index); #endif for (i = 0; i < index; i++) {