diff --git a/lisp/Darwin-os.c b/lisp/Darwin-os.c index d3c2d9cd0c09129ded0319da445946f02883ba21..452519f1719a7a8fca95e526cc7a0bc255ac7fd8 100644 --- a/lisp/Darwin-os.c +++ b/lisp/Darwin-os.c @@ -14,7 +14,7 @@ * Frobbed for OpenBSD by Pierre R. Mai, 2001. * Frobbed for Darwin by Pierre R. Mai, 2003. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Darwin-os.c,v 1.18 2008/09/11 00:15:28 rtoy Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Darwin-os.c,v 1.19 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -371,7 +371,6 @@ sigbus_handler(HANDLER_ARGS) { #if defined(GENCGC) caddr_t fault_addr = code->si_addr; - int page_index = find_page_index((void *) fault_addr); #endif #ifdef __ppc__ @@ -390,30 +389,13 @@ sigbus_handler(HANDLER_ARGS) fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n", signal, fault_addr, page_index); #endif - - /* Check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigsegv in page not marked as write protected\n"); - - os_protect(page_address(page_index), PAGE_SIZE, OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - } else { - /* a *real* protection fault */ - fprintf(stderr, "segv_handler: Real protection violation: %p\n", fault_addr); - interrupt_handle_now(signal, code, context); - } + if (gc_write_barrier(code->si_addr)) + return; #else - - if (!interrupt_maybe_gc(signal, code, context)) { - interrupt_handle_now(signal, code, context); - } + if (interrupt_maybe_gc(signal, code, context)) + return; #endif + interrupt_handle_now(signal, code, context); #ifdef __ppc__ /* Work around G5 bug; fix courtesy gbyers via chandler */ sigreturn(context); diff --git a/lisp/FreeBSD-os.c b/lisp/FreeBSD-os.c index 12f12b3654b8dabbd28683b4f53fedc44e221aa5..d5b1e88470f82165384c604ba7d266cc06758d53 100644 --- a/lisp/FreeBSD-os.c +++ b/lisp/FreeBSD-os.c @@ -12,7 +12,7 @@ * Much hacked by Paul Werkowski * GENCGC support by Douglas Crosher, 1996, 1997. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/FreeBSD-os.c,v 1.23 2008/03/18 09:22:55 cshapiro Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/FreeBSD-os.c,v 1.24 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -201,8 +201,6 @@ boolean valid_addr(os_vm_address_t addr) static void sigbus_handler(int signal, siginfo_t *info, ucontext_t *context) { - int page_index; - #ifdef RED_ZONE_HIT if (os_control_stack_overflow(info->si_addr, context)) return; @@ -210,21 +208,7 @@ sigbus_handler(int signal, siginfo_t *info, ucontext_t *context) #if defined GENCGC if (info->si_code == PROTECTION_VIOLATION_CODE) { - page_index = find_page_index(info->si_addr); - - /* Check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigbus in page not marked as write protected\n"); - - os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - + if (gc_write_barrier(info->si_addr)) { return; } } diff --git a/lisp/Linux-os.c b/lisp/Linux-os.c index 19792b4d4778e406a1cdf3d12e1b2246056fe2a8..10ff1e655438994a6345d2be643ecf793ae8dddd 100644 --- a/lisp/Linux-os.c +++ b/lisp/Linux-os.c @@ -15,7 +15,7 @@ * GENCGC support by Douglas Crosher, 1996, 1997. * Alpha support by Julian Dolby, 1999. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.37 2008/01/03 11:41:54 cshapiro Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.38 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -280,27 +280,13 @@ void sigsegv_handler(HANDLER_ARGS) { int fault_addr = context->uc_mcontext.cr2; - int page_index = find_page_index((void *) fault_addr); #ifdef RED_ZONE_HIT if (os_control_stack_overflow((void *) fault_addr, context)) return; #endif - - /* check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigsegv in page not marked as write protected\n"); - os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - + if (gc_write_barrier(code->si_addr)) return; - } #if defined(__x86_64) DPRINTF(0, (stderr, "sigsegv: rip: %p\n", context->uc_mcontext.gregs[REG_RIP])); #else diff --git a/lisp/NetBSD-os.c b/lisp/NetBSD-os.c index 07546ee5f27566c7a96e5183877ed5baa82d8f01..90c1dae76fc413f38936c8959b2bcae48cd31867 100644 --- a/lisp/NetBSD-os.c +++ b/lisp/NetBSD-os.c @@ -15,7 +15,7 @@ * Frobbed for OpenBSD by Pierre R. Mai, 2001. * Frobbed for NetBSD by Pierre R. Mai, 2002. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.9 2008/05/16 13:30:21 rswindells Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.10 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -213,28 +213,14 @@ sigsegv_handler(HANDLER_ARGS) { #if defined GENCGC caddr_t fault_addr = code ? code->si_addr : 0; - int page_index = find_page_index((void *) fault_addr); #if SIGSEGV_VERBOSE fprintf(stderr, "Signal %d, fault_addr=%p, page_index=%d:\n", signal, fault_addr, page_index); #endif - /* Check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigsegv in page not marked as write protected\n"); - - os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - + if (gc_write_barrier(code->si_addr)) return; - } #endif SAVE_CONTEXT(); diff --git a/lisp/OpenBSD-os.c b/lisp/OpenBSD-os.c index bbc8f18646f91a8ed0a2ce7aa648dd20d8e40545..161fbb798bbcd10eb400a1124f43222952ef7622 100644 --- a/lisp/OpenBSD-os.c +++ b/lisp/OpenBSD-os.c @@ -13,7 +13,7 @@ * GENCGC support by Douglas Crosher, 1996, 1997. * Frobbed for OpenBSD by Pierre R. Mai, 2001. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/OpenBSD-os.c,v 1.6 2007/07/30 07:24:46 cshapiro Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/OpenBSD-os.c,v 1.7 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -164,28 +164,14 @@ sigsegv_handler(HANDLER_ARGS) { #if defined GENCGC caddr_t fault_addr = code->si_addr; - int page_index = find_page_index((void *) fault_addr); #if SIGSEGV_VERBOSE fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n", signal, fault_addr, page_index); #endif - /* Check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigsegv in page not marked as write protected\n"); - - os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - + if (gc_write_barrier(code->si_addr)) return; - } #endif SAVE_CONTEXT(); diff --git a/lisp/gencgc.c b/lisp/gencgc.c index ede257886e147fdd3c073d47682431222c3f71fc..483e29f5412e680f83f5d190e7dc4b7f4fa42336 100644 --- a/lisp/gencgc.c +++ b/lisp/gencgc.c @@ -7,7 +7,7 @@ * * Douglas Crosher, 1996, 1997, 1998, 1999. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.96 2008/09/11 00:15:28 rtoy Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.97 2008/09/16 08:52:31 cshapiro Exp $ * */ @@ -385,7 +385,7 @@ static char *heap_base = NULL; /* * Calculate the start address for the given page number. */ -inline char * +static char * page_address(int page_num) { return heap_base + PAGE_SIZE * page_num; @@ -395,7 +395,7 @@ page_address(int page_num) * Find the page index within the page_table for the given address. * Returns -1 on failure. */ -inline int +int find_page_index(void *addr) { int index = (char *) addr - heap_base; @@ -409,6 +409,38 @@ find_page_index(void *addr) return -1; } +/* + * This routine implements a write barrier used to record stores into + * to boxed regions outside of generation 0. When such a store occurs + * this routine will be automatically invoked by the page fault + * handler. If passed an address outside of the dynamic space, this + * routine will return immediately with a value of 0. Otherwise, the + * page belonging to the address is made writable, the protection + * change is recorded in the garbage collector page table, and a value + * of 1 is returned. + */ +int +gc_write_barrier(void *addr) +{ + int page_index = find_page_index(addr); + + /* Check if the fault is within the dynamic space. */ + if (page_index == -1) { + return 0; + } + + /* The page should have been marked write protected */ + if (!PAGE_WRITE_PROTECTED(page_index)) + fprintf(stderr, + "*** Page fault in page not marked as write protected\n"); + + /* Un-protect the page */ + os_protect(page_address(page_index), PAGE_SIZE, OS_VM_PROT_ALL); + page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; + page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; + + return 1; +} /* * A structure to hold the state of a generation. diff --git a/lisp/gencgc.h b/lisp/gencgc.h index 8d3a515c2451716582166020a5fcade492ac6dd9..ea3023dd7186cd0863255359ad758ae0cd11e0c9 100644 --- a/lisp/gencgc.h +++ b/lisp/gencgc.h @@ -7,7 +7,7 @@ * * Douglas Crosher, 1996, 1997. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.h,v 1.13 2006/01/18 15:21:26 rtoy Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.h,v 1.14 2008/09/16 08:52:32 cshapiro Rel $ * */ @@ -15,8 +15,7 @@ #define _GENCGC_H_ void gc_free_heap(void); -inline int find_page_index(void *); -inline char *page_address(int); +int gc_write_barrier(void *); diff --git a/lisp/solaris-os.c b/lisp/solaris-os.c index bb37779d3c527e2b4df661da2ce7ab5799cd1321..1c49f1754b2b251797cdfb326fcbb4a0ca08dea6 100644 --- a/lisp/solaris-os.c +++ b/lisp/solaris-os.c @@ -1,5 +1,5 @@ /* - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.21 2008/09/07 07:07:50 cshapiro Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.22 2008/09/16 08:52:32 cshapiro Exp $ * * OS-dependent routines. This file (along with os.h) exports an * OS-independent interface to the operating system VM facilities. @@ -211,32 +211,16 @@ void segv_handler(HANDLER_ARGS) { caddr_t addr = code->si_addr; - int page_index; SAVE_CONTEXT(); - page_index = find_page_index((void *) addr); - #ifdef RED_ZONE_HIT if (os_control_stack_overflow(addr, context)) return; #endif - /* check if the fault is within the dynamic space. */ - if (page_index != -1) { - /* Un-protect the page */ - - /* The page should have been marked write protected */ - if (!PAGE_WRITE_PROTECTED(page_index)) - fprintf(stderr, - "*** Sigsegv in page not marked as write protected\n"); - os_protect((os_vm_address_t) page_address(page_index), PAGE_SIZE, - OS_VM_PROT_ALL); - page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK; - page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK; - - return; - } + if (gc_write_barrier(code->si_addr)) + return; /* * Could be a C stack overflow. Let's check