X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fcheneygc.c;h=14b52085d4a34faf52315bdc01b370673a160f8b;hb=961c6bf2eda5d492d5dbb7e275fe4e0931f7adf8;hp=4e5c135ac86d19d7f8b3501975b5b420f0dc7287;hpb=1479483c5f40fc470053da0fc5cd8e42fc77676e;p=sbcl.git diff --git a/src/runtime/cheneygc.c b/src/runtime/cheneygc.c index 4e5c135..14b5208 100644 --- a/src/runtime/cheneygc.c +++ b/src/runtime/cheneygc.c @@ -30,6 +30,7 @@ #include "genesis/static-symbols.h" #include "genesis/primitive-objects.h" #include "thread.h" +#include "arch.h" /* So you need to debug? */ #if 0 @@ -48,8 +49,6 @@ lispobj *new_space_free_pointer; static void scavenge_newspace(void); -extern unsigned long bytes_consed_between_gcs; - /* collecting garbage */ @@ -62,45 +61,20 @@ tv_diff(struct timeval *x, struct timeval *y) } #endif -#define BYTES_ZERO_BEFORE_END (1<<12) - -/* FIXME do we need this? Doesn't it duplicate lisp code in - * scrub-control-stack? */ - -static void -zero_stack(void) -{ - lispobj *ptr = current_control_stack_pointer; - search: - do { - if (*ptr) - goto fill; - ptr++; - } while (((unsigned long)ptr) & (BYTES_ZERO_BEFORE_END-1)); - return; - fill: - do { - *ptr++ = 0; - } while (((unsigned long)ptr) & (BYTES_ZERO_BEFORE_END-1)); - - goto search; -} - - void * -gc_general_alloc(long bytes, int unboxed_p, int quick_p) { +gc_general_alloc(word_t bytes, int page_type_flag, int quick_p) { lispobj *new=new_space_free_pointer; new_space_free_pointer+=(bytes/N_WORD_BYTES); return new; } -lispobj copy_large_unboxed_object(lispobj object, long nwords) { +lispobj copy_large_unboxed_object(lispobj object, sword_t nwords) { return copy_object(object,nwords); } -lispobj copy_unboxed_object(lispobj object, long nwords) { +lispobj copy_unboxed_object(lispobj object, sword_t nwords) { return copy_object(object,nwords); } -lispobj copy_large_object(lispobj object, long nwords) { +lispobj copy_large_object(lispobj object, sword_t nwords) { return copy_object(object,nwords); } @@ -133,9 +107,7 @@ collect_garbage(generation_index_t ignore) /* it's possible that signals are blocked already if this was called * from a signal handler (e.g. with the sigsegv gc_trigger stuff) */ - sigemptyset(&tmp); - sigaddset_blockable(&tmp); - thread_sigmask(SIG_BLOCK, &tmp, &old); + block_blockable_signals(0, &old); current_static_space_free_pointer = (lispobj *) ((unsigned long) @@ -168,7 +140,7 @@ collect_garbage(generation_index_t ignore) #ifdef PRINTNOISE printf("Scavenging interrupt contexts ...\n"); #endif - scavenge_interrupt_contexts(); + scavenge_interrupt_contexts(th); #ifdef PRINTNOISE printf("Scavenging interrupt handlers (%d bytes) ...\n", @@ -177,24 +149,18 @@ collect_garbage(generation_index_t ignore) scavenge((lispobj *) interrupt_handlers, sizeof(interrupt_handlers) / sizeof(lispobj)); - /* _size quantities are in units of sizeof(lispobj) - i.e. 4 */ - control_stack_size = - current_control_stack_pointer- - (lispobj *)th->control_stack_start; #ifdef PRINTNOISE - printf("Scavenging the control stack at %p (%ld words) ...\n", - ((lispobj *)th->control_stack_start), - control_stack_size); + printf("Scavenging the control stack ...\n"); #endif - scavenge(((lispobj *)th->control_stack_start), control_stack_size); + scavenge_control_stack(th); binding_stack_size = - current_binding_stack_pointer - + (lispobj *)get_binding_stack_pointer(th) - (lispobj *)th->binding_stack_start; #ifdef PRINTNOISE printf("Scavenging the binding stack %x - %x (%d words) ...\n", - th->binding_stack_start,current_binding_stack_pointer, + th->binding_stack_start,get_binding_stack_pointer(th), (int)(binding_stack_size)); #endif scavenge(((lispobj *)th->binding_stack_start), binding_stack_size); @@ -240,8 +206,12 @@ collect_garbage(generation_index_t ignore) /* Maybe FIXME: it's possible that we could significantly reduce * RSS by zeroing the from_space or madvise(MADV_DONTNEED) or * similar os-dependent tricks here */ +#ifdef LISP_FEATURE_HPUX + /* hpux cant handle unmapping areas that are not 100% mapped */ + clear_auto_gc_trigger(); +#endif os_zero((os_vm_address_t) from_space, - (os_vm_size_t) DYNAMIC_SPACE_SIZE); + (os_vm_size_t) dynamic_space_size); current_dynamic_space = new_space; dynamic_space_free_pointer = new_space_free_pointer; @@ -257,7 +227,7 @@ collect_garbage(generation_index_t ignore) #ifdef PRINTNOISE printf("Zeroing empty part of control stack ...\n"); #endif - zero_stack(); + scrub_control_stack(); set_auto_gc_trigger(size_retained+bytes_consed_between_gcs); thread_sigmask(SIG_SETMASK, &old, 0); @@ -307,134 +277,6 @@ scavenge_newspace(void) /* printf("done with newspace\n"); */ } -/* scavenging interrupt contexts */ - -static int boxed_registers[] = BOXED_REGISTERS; - -static void -scavenge_interrupt_context(os_context_t *context) -{ - 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 - /* Find the LIP's register pair and calculate its offset */ - /* before we scavenge the context. */ -#ifdef reg_LIP - 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 < (sizeof(boxed_registers) / sizeof(int)); i++) { - unsigned long reg; - 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<interrupt_contexts[i]; - scavenge_interrupt_context(context); - } -} - - /* debugging code */ void @@ -589,12 +431,12 @@ void set_auto_gc_trigger(os_vm_size_t dynamic_usage) (unsigned long)((os_vm_address_t)dynamic_space_free_pointer - (os_vm_address_t)current_dynamic_space)); - length = os_trunc_size_to_page(DYNAMIC_SPACE_SIZE - dynamic_usage); + length = os_trunc_size_to_page(dynamic_space_size - dynamic_usage); if (length < 0) lose("set_auto_gc_trigger: tried to set gc trigger too high! (0x%08lx)\n", (unsigned long)dynamic_usage); -#if defined(SUNOS) || defined(SOLARIS) +#if defined(SUNOS) || defined(SOLARIS) || defined(LISP_FEATURE_HPUX) os_invalidate(addr, length); #else os_protect(addr, length, 0); @@ -612,9 +454,9 @@ void clear_auto_gc_trigger(void) return; addr = (os_vm_address_t)current_auto_gc_trigger; - length = DYNAMIC_SPACE_SIZE + (os_vm_address_t)current_dynamic_space - addr; + length = dynamic_space_size + (os_vm_address_t)current_dynamic_space - addr; -#if defined(SUNOS) || defined(SOLARIS) +#if defined(SUNOS) || defined(SOLARIS) || defined(LISP_FEATURE_HPUX) /* don't want to force whole space into swapping mode... */ os_validate(addr, length); #else @@ -623,3 +465,44 @@ void clear_auto_gc_trigger(void) current_auto_gc_trigger = NULL; } + +static boolean +gc_trigger_hit(void *addr) +{ + if (current_auto_gc_trigger == NULL) + return 0; + else{ + return (addr >= (void *)current_auto_gc_trigger && + addr <((void *)current_dynamic_space + dynamic_space_size)); + } +} + +boolean +cheneygc_handle_wp_violation(os_context_t *context, void *addr) +{ + if(!foreign_function_call_active && gc_trigger_hit(addr)){ + struct thread *thread=arch_os_get_current_thread(); + clear_auto_gc_trigger(); + /* Don't flood the system with interrupts if the need to gc is + * already noted. This can happen for example when SUB-GC + * allocates or after a gc triggered in a WITHOUT-GCING. */ + if (SymbolValue(GC_PENDING,thread) == NIL) { + if (SymbolValue(GC_INHIBIT,thread) == NIL) { + if (arch_pseudo_atomic_atomic(context)) { + /* set things up so that GC happens when we finish + * the PA section */ + SetSymbolValue(GC_PENDING,T,thread); + arch_set_pseudo_atomic_interrupted(context); + maybe_save_gc_mask_and_block_deferrables + (os_context_sigmask_addr(context)); + } else { + maybe_gc(context); + } + } else { + SetSymbolValue(GC_PENDING,T,thread); + } + } + return 1; + } + return 0; +}