X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fcheneygc.c;h=4948da85d0e69a469da9deb6e0e42bec2bad62de;hb=eaa8a506790bb6ed627da617247bfd13802eb365;hp=f557521c8c1371b21bb1db8ef779a8c11c9436fe;hpb=305177dc7a7d11245e42e003ac4070eb1705c699;p=sbcl.git diff --git a/src/runtime/cheneygc.c b/src/runtime/cheneygc.c index f557521..4948da8 100644 --- a/src/runtime/cheneygc.c +++ b/src/runtime/cheneygc.c @@ -17,8 +17,8 @@ #include #include #include -#include "runtime.h" #include "sbcl.h" +#include "runtime.h" #include "os.h" #include "gc.h" #include "gc-internal.h" @@ -27,6 +27,9 @@ #include "validate.h" #include "lispregs.h" #include "interr.h" +#include "genesis/static-symbols.h" +#include "genesis/primitive-objects.h" +#include "thread.h" /* So you need to debug? */ #if 0 @@ -45,6 +48,9 @@ lispobj *new_space_free_pointer; 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; /* collecting garbage */ @@ -66,7 +72,7 @@ tv_diff(struct timeval *x, struct timeval *y) static void zero_stack(void) { - u32 *ptr = (u32 *)current_control_stack_pointer; + lispobj *ptr = current_control_stack_pointer; search: do { if (*ptr) @@ -84,19 +90,19 @@ zero_stack(void) void * -gc_general_alloc(int bytes, int unboxed_p, int quick_p) { +gc_general_alloc(long bytes, int unboxed_p, int quick_p) { lispobj *new=new_space_free_pointer; - new_space_free_pointer+=(bytes/4); + new_space_free_pointer+=(bytes/N_WORD_BYTES); return new; } -lispobj copy_large_unboxed_object(lispobj object, int nwords) { +lispobj copy_large_unboxed_object(lispobj object, long nwords) { return copy_object(object,nwords); } -lispobj copy_unboxed_object(lispobj object, int nwords) { +lispobj copy_unboxed_object(lispobj object, long nwords) { return copy_object(object,nwords); } -lispobj copy_large_object(lispobj object, int nwords) { +lispobj copy_large_object(lispobj object, long nwords) { return copy_object(object,nwords); } @@ -112,12 +118,16 @@ collect_garbage(unsigned ignore) double real_time, system_time, user_time; double percent_retained, gc_rate; unsigned long size_discarded; - unsigned long size_retained; #endif + unsigned long size_retained; lispobj *current_static_space_free_pointer; unsigned long static_space_size; 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; + #ifdef PRINTNOISE printf("[Collecting garbage ... \n"); @@ -126,13 +136,15 @@ collect_garbage(unsigned ignore) gettimeofday(&start_tv, (struct timezone *) 0); #endif + /* 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); sigprocmask(SIG_BLOCK, &tmp, &old); current_static_space_free_pointer = (lispobj *) ((unsigned long) - SymbolValue(STATIC_SPACE_FREE_POINTER)); + SymbolValue(STATIC_SPACE_FREE_POINTER,0)); /* Set up from space and new space pointers. */ @@ -167,30 +179,30 @@ collect_garbage(unsigned ignore) printf("Scavenging interrupt handlers (%d bytes) ...\n", (int)sizeof(interrupt_handlers)); #endif - scavenge((lispobj *) interrupt_handlers, - sizeof(interrupt_handlers) / sizeof(lispobj)); + scavenge((lispobj *) data->interrupt_handlers, + sizeof(data->interrupt_handlers) / sizeof(lispobj)); /* _size quantities are in units of sizeof(lispobj) - i.e. 4 */ control_stack_size = current_control_stack_pointer- - (lispobj *)CONTROL_STACK_START; + (lispobj *)th->control_stack_start; #ifdef PRINTNOISE printf("Scavenging the control stack at %p (%ld words) ...\n", - ((lispobj *)CONTROL_STACK_START), + ((lispobj *)th->control_stack_start), control_stack_size); #endif - scavenge(((lispobj *)CONTROL_STACK_START), control_stack_size); + scavenge(((lispobj *)th->control_stack_start), control_stack_size); binding_stack_size = current_binding_stack_pointer - - (lispobj *)BINDING_STACK_START; + (lispobj *)th->binding_stack_start; #ifdef PRINTNOISE printf("Scavenging the binding stack %x - %x (%d words) ...\n", - BINDING_STACK_START,current_binding_stack_pointer, + th->binding_stack_start,current_binding_stack_pointer, (int)(binding_stack_size)); #endif - scavenge(((lispobj *)BINDING_STACK_START), binding_stack_size); + scavenge(((lispobj *)th->binding_stack_start), binding_stack_size); static_space_size = current_static_space_free_pointer - (lispobj *) STATIC_SPACE_START; @@ -225,7 +237,10 @@ collect_garbage(unsigned ignore) printf("Flipping spaces ...\n"); #endif - os_zero((os_vm_address_t) current_dynamic_space, + /* 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 */ + os_zero((os_vm_address_t) from_space, (os_vm_size_t) DYNAMIC_SPACE_SIZE); current_dynamic_space = new_space; @@ -233,15 +248,17 @@ collect_garbage(unsigned ignore) #ifdef PRINTNOISE size_discarded = (from_space_free_pointer - from_space) * sizeof(lispobj); - size_retained = (new_space_free_pointer - new_space) * sizeof(lispobj); #endif + size_retained = (new_space_free_pointer - new_space) * sizeof(lispobj); + + os_flush_icache((os_vm_address_t)new_space, size_retained); /* Zero stack. */ #ifdef PRINTNOISE printf("Zeroing empty part of control stack ...\n"); #endif zero_stack(); - + set_auto_gc_trigger(size_retained+bytes_consed_between_gcs); sigprocmask(SIG_SETMASK, &old, 0); @@ -261,24 +278,13 @@ collect_garbage(unsigned ignore) user_time = tv_diff(&stop_rusage.ru_utime, &start_rusage.ru_utime); system_time = tv_diff(&stop_rusage.ru_stime, &start_rusage.ru_stime); -#if 0 - printf("Statistics:\n"); - printf("%10.2f sec of real time\n", real_time); - printf("%10.2f sec of user time,\n", user_time); - printf("%10.2f sec of system time.\n", system_time); -#else printf("Statistics: %10.2fs real, %10.2fs user, %10.2fs system.\n", real_time, user_time, system_time); -#endif gc_rate = ((float) size_retained / (float) (1<<20)) / real_time; printf("%10.2f M bytes/sec collected.\n", gc_rate); #endif - /* os_flush_icache((os_vm_address_t) 0, sizeof(unsigned long)); */ - /* 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 */ } @@ -327,8 +333,9 @@ scavenge_interrupt_context(os_context_t *context) /* before we scavenge the context. */ #ifdef reg_LIP lip = *os_context_register_addr(context, reg_LIP); - /* 0x7FFFFFFF or 0x7FFFFFFFFFFFFFFF ? */ - lip_offset = 0x7FFFFFFF; + /* 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; @@ -412,13 +419,16 @@ void scavenge_interrupt_contexts(void) int i, index; os_context_t *context; - index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)); + struct thread *th=arch_os_get_current_thread(); + + index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,0)); + #ifdef DEBUG_SCAVENGE_VERBOSE fprintf(stderr, "%d interrupt contexts to scan\n",index); #endif for (i = 0; i < index; i++) { - context = lisp_interrupt_contexts[i]; + context = th->interrupt_contexts[i]; scavenge_interrupt_context(context); } } @@ -484,49 +494,9 @@ print_garbage(lispobj *from_space, lispobj *from_space_free_pointer) } -/* code and code-related objects */ - -/* FIXME (1) this could probably be defined using something like - * sizeof(lispobj)*floor(sizeof(struct simple_fun)/sizeof(lispobj)) - * - FUN_POINTER_LOWTAG - * as I'm reasonably sure that simple_fun->code must always be the - * last slot in the object - - * FIXME (2) it also appears in purify.c, and it has a different value - * for SPARC users in that bit - */ - -#define FUN_RAW_ADDR_OFFSET (6*sizeof(lispobj) - FUN_POINTER_LOWTAG) - -/* Note: on the sparc we don't have to do anything special for fdefns, */ -/* 'cause the raw-addr has a function lowtag. */ -#ifndef LISP_FEATURE_SPARC -static int -scav_fdefn(lispobj *where, lispobj object) -{ - struct fdefn *fdefn; - - fdefn = (struct fdefn *)where; - - if ((char *)(fdefn->fun + FUN_RAW_ADDR_OFFSET) - == (char *)((unsigned long)(fdefn->raw_addr))) { - scavenge(where + 1, sizeof(struct fdefn)/sizeof(lispobj) - 1); - fdefn->raw_addr = - (u32) ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET; - return sizeof(struct fdefn) / sizeof(lispobj); - } - else - return 1; -} -#endif - - - /* vector-like objects */ -/* #define NWORDS(x,y) (CEILING((x),(y)) / (y)) */ - -static int +static long scav_vector(lispobj *where, lispobj object) { if (HeaderValue(object) == subtype_VectorValidHashing) { @@ -543,7 +513,7 @@ scav_vector(lispobj *where, lispobj object) #define WEAK_POINTER_NWORDS \ CEILING((sizeof(struct weak_pointer) / sizeof(lispobj)), 2) -static int +static long scav_weak_pointer(lispobj *where, lispobj object) { /* Do not let GC scavenge the value slot of the weak pointer */ @@ -552,7 +522,42 @@ scav_weak_pointer(lispobj *where, lispobj object) return WEAK_POINTER_NWORDS; } + +lispobj * +search_read_only_space(void *pointer) +{ + lispobj* start = (lispobj*)READ_ONLY_SPACE_START; + lispobj* end = (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0); + if ((pointer < (void *)start) || (pointer >= (void *)end)) + return NULL; + return (gc_search_space(start, + (((lispobj *)pointer)+2)-start, + (lispobj *)pointer)); +} + +lispobj * +search_static_space(void *pointer) +{ + lispobj* start = (lispobj*)STATIC_SPACE_START; + lispobj* end = (lispobj*)SymbolValue(STATIC_SPACE_FREE_POINTER,0); + if ((pointer < (void *)start) || (pointer >= (void *)end)) + return NULL; + return (gc_search_space(start, + (((lispobj *)pointer)+2)-start, + (lispobj *)pointer)); +} +lispobj * +search_dynamic_space(void *pointer) +{ + lispobj *start = (lispobj *) current_dynamic_space; + lispobj *end = (lispobj *) dynamic_space_free_pointer; + if ((pointer < (void *)start) || (pointer >= (void *)end)) + return NULL; + return (gc_search_space(start, + (((lispobj *)pointer)+2)-start, + (lispobj *)pointer)); +} /* initialization. if gc_init can be moved to after core load, we could * combine these two functions */ @@ -582,25 +587,27 @@ gc_initialize_pointers(void) /* noise to manipulate the gc trigger stuff */ +/* Functions that substantially change the dynamic space free pointer + * (collect_garbage, purify) are responsible also for resettting the + * auto_gc_trigger */ void set_auto_gc_trigger(os_vm_size_t dynamic_usage) { os_vm_address_t addr=(os_vm_address_t)current_dynamic_space + dynamic_usage; - long length = DYNAMIC_SPACE_SIZE - dynamic_usage; if (addr < (os_vm_address_t)dynamic_space_free_pointer) { fprintf(stderr, - "set_auto_gc_trigger: tried to set gc trigger too low! (%d < %p)\n", - (unsigned int)dynamic_usage, - (os_vm_address_t)dynamic_space_free_pointer - - (os_vm_address_t)current_dynamic_space); + "set_auto_gc_trigger: tried to set gc trigger too low! (%ld < 0x%08lx)\n", + (unsigned long)dynamic_usage, + (unsigned long)((os_vm_address_t)dynamic_space_free_pointer + - (os_vm_address_t)current_dynamic_space)); lose("lost"); } else if (length < 0) { fprintf(stderr, - "set_auto_gc_trigger: tried to set gc trigger too high! (%p)\n", - dynamic_usage); + "set_auto_gc_trigger: tried to set gc trigger too high! (0x%08lx)\n", + (unsigned long)dynamic_usage); lose("lost"); }