| /* |
| * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. |
| * |
| * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED |
| * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
| * |
| * Permission is hereby granted to use or copy this program |
| * for any purpose, provided the above notices are retained on all copies. |
| * Permission to modify the code and to distribute modified code is granted, |
| * provided the above notices are retained, and a notice that the code was |
| * modified is included with the above copyright notice. |
| */ |
| # include "private/gc_priv.h" |
| |
| # ifdef PCR |
| /* |
| * Note that POSIX PCR requires an ANSI C compiler. Hence we are allowed |
| * to make the same assumption here. |
| * We wrap all of the allocator functions to avoid questions of |
| * compatibility between the prototyped and nonprototyped versions of the f |
| */ |
| # include "config/PCR_StdTypes.h" |
| # include "mm/PCR_MM.h" |
| # include <errno.h> |
| |
| # define MY_MAGIC 17L |
| # define MY_DEBUGMAGIC 42L |
| |
| void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear ) |
| { |
| if (ptrFree) { |
| void * result = (void *)GC_malloc_atomic(size); |
| if (clear && result != 0) BZERO(result, size); |
| return(result); |
| } else { |
| return((void *)GC_malloc(size)); |
| } |
| } |
| |
| void * GC_DebugAllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear ) |
| { |
| if (ptrFree) { |
| void * result = (void *)GC_debug_malloc_atomic(size, __FILE__, |
| __LINE__); |
| if (clear && result != 0) BZERO(result, size); |
| return(result); |
| } else { |
| return((void *)GC_debug_malloc(size, __FILE__, __LINE__)); |
| } |
| } |
| |
| # define GC_ReallocProc GC_realloc |
| void * GC_DebugReallocProc(void * old_object, size_t new_size_in_bytes) |
| { |
| return(GC_debug_realloc(old_object, new_size_in_bytes, __FILE__, __LINE__)); |
| } |
| |
| # define GC_FreeProc GC_free |
| # define GC_DebugFreeProc GC_debug_free |
| |
| typedef struct { |
| PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data); |
| GC_bool ed_pointerfree; |
| PCR_ERes ed_fail_code; |
| PCR_Any ed_client_data; |
| } enumerate_data; |
| |
| void GC_enumerate_block(h, ed) |
| register struct hblk *h; |
| enumerate_data * ed; |
| { |
| register hdr * hhdr; |
| register int sz; |
| word *p; |
| word * lim; |
| |
| hhdr = HDR(h); |
| sz = hhdr -> hb_sz; |
| if (sz >= 0 && ed -> ed_pointerfree |
| || sz <= 0 && !(ed -> ed_pointerfree)) return; |
| if (sz < 0) sz = -sz; |
| lim = (word *)(h+1) - sz; |
| p = (word *)h; |
| do { |
| if (PCR_ERes_IsErr(ed -> ed_fail_code)) return; |
| ed -> ed_fail_code = |
| (*(ed -> ed_proc))(p, WORDS_TO_BYTES(sz), ed -> ed_client_data); |
| p+= sz; |
| } while (p <= lim); |
| } |
| |
| struct PCR_MM_ProcsRep * GC_old_allocator = 0; |
| |
| PCR_ERes GC_EnumerateProc( |
| PCR_Bool ptrFree, |
| PCR_ERes (*proc)(void *p, size_t size, PCR_Any data), |
| PCR_Any data |
| ) |
| { |
| enumerate_data ed; |
| |
| ed.ed_proc = proc; |
| ed.ed_pointerfree = ptrFree; |
| ed.ed_fail_code = PCR_ERes_okay; |
| ed.ed_client_data = data; |
| GC_apply_to_all_blocks(GC_enumerate_block, &ed); |
| if (ed.ed_fail_code != PCR_ERes_okay) { |
| return(ed.ed_fail_code); |
| } else { |
| /* Also enumerate objects allocated by my predecessors */ |
| return((*(GC_old_allocator->mmp_enumerate))(ptrFree, proc, data)); |
| } |
| } |
| |
| void GC_DummyFreeProc(void *p) {} |
| |
| void GC_DummyShutdownProc(void) {} |
| |
| struct PCR_MM_ProcsRep GC_Rep = { |
| MY_MAGIC, |
| GC_AllocProc, |
| GC_ReallocProc, |
| GC_DummyFreeProc, /* mmp_free */ |
| GC_FreeProc, /* mmp_unsafeFree */ |
| GC_EnumerateProc, |
| GC_DummyShutdownProc /* mmp_shutdown */ |
| }; |
| |
| struct PCR_MM_ProcsRep GC_DebugRep = { |
| MY_DEBUGMAGIC, |
| GC_DebugAllocProc, |
| GC_DebugReallocProc, |
| GC_DummyFreeProc, /* mmp_free */ |
| GC_DebugFreeProc, /* mmp_unsafeFree */ |
| GC_EnumerateProc, |
| GC_DummyShutdownProc /* mmp_shutdown */ |
| }; |
| |
| GC_bool GC_use_debug = 0; |
| |
| void GC_pcr_install() |
| { |
| PCR_MM_Install((GC_use_debug? &GC_DebugRep : &GC_Rep), &GC_old_allocator); |
| } |
| |
| PCR_ERes |
| PCR_GC_Setup(void) |
| { |
| return PCR_ERes_okay; |
| } |
| |
| PCR_ERes |
| PCR_GC_Run(void) |
| { |
| |
| if( !PCR_Base_TestPCRArg("-nogc") ) { |
| GC_quiet = ( PCR_Base_TestPCRArg("-gctrace") ? 0 : 1 ); |
| GC_use_debug = (GC_bool)PCR_Base_TestPCRArg("-debug_alloc"); |
| GC_init(); |
| if( !PCR_Base_TestPCRArg("-nogc_incremental") ) { |
| /* |
| * awful hack to test whether VD is implemented ... |
| */ |
| if( PCR_VD_Start( 0, NIL, 0) != PCR_ERes_FromErr(ENOSYS) ) { |
| GC_enable_incremental(); |
| } |
| } |
| } |
| return PCR_ERes_okay; |
| } |
| |
| void GC_push_thread_structures(void) |
| { |
| /* PCR doesn't work unless static roots are pushed. Can't get here. */ |
| ABORT("In GC_push_thread_structures()"); |
| } |
| |
| # endif |