version 1.6, 2002/07/24 08:00:10 |
version 1.11, 2015/08/14 13:51:55 |
|
|
# if defined(GC_WIN32_THREADS) |
# if defined(GC_WIN32_THREADS) |
# if defined(GC_PTHREADS) |
# if defined(GC_PTHREADS) |
pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; |
pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; |
# elif !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL)) |
# elif defined(GC_DLL) |
__declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; |
__declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; |
# else |
# else |
CRITICAL_SECTION GC_allocate_ml; |
CRITICAL_SECTION GC_allocate_ml; |
|
|
#undef STACKBASE |
#undef STACKBASE |
#endif |
#endif |
|
|
|
/* Dont unnecessarily call GC_register_main_static_data() in case */ |
|
/* dyn_load.c isn't linked in. */ |
|
#ifdef DYNAMIC_LOADING |
|
# define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data() |
|
#else |
|
# define GC_REGISTER_MAIN_STATIC_DATA() TRUE |
|
#endif |
|
|
GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */; |
GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */; |
|
|
|
|
Line 104 GC_bool GC_print_stats = 0; |
|
Line 112 GC_bool GC_print_stats = 0; |
|
|
|
GC_bool GC_print_back_height = 0; |
GC_bool GC_print_back_height = 0; |
|
|
|
#ifndef NO_DEBUGGING |
|
GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */ |
|
#endif |
|
|
#ifdef FIND_LEAK |
#ifdef FIND_LEAK |
int GC_find_leak = 1; |
int GC_find_leak = 1; |
#else |
#else |
Line 116 GC_bool GC_print_back_height = 0; |
|
Line 128 GC_bool GC_print_back_height = 0; |
|
int GC_all_interior_pointers = 0; |
int GC_all_interior_pointers = 0; |
#endif |
#endif |
|
|
|
#if 0 |
long GC_large_alloc_warn_interval = 5; |
long GC_large_alloc_warn_interval = 5; |
|
#else |
|
long GC_large_alloc_warn_interval = LONG_MAX; |
|
#endif |
/* Interval between unsuppressed warnings. */ |
/* Interval between unsuppressed warnings. */ |
|
|
long GC_large_alloc_warn_suppressed = 0; |
long GC_large_alloc_warn_suppressed = 0; |
/* Number of warnings suppressed so far. */ |
/* Number of warnings suppressed so far. */ |
|
|
|
#include <time.h> |
|
|
|
#if defined(VISUAL) || defined(__MINGW32__) |
|
#include <windows.h> |
|
|
|
static double get_clock() |
|
{ |
|
static int initialized = 0; |
|
static int is_winnt = 0; |
|
static HANDLE curproc; |
|
|
|
if ( !initialized ) { |
|
OSVERSIONINFO vinfo; |
|
|
|
curproc = GetCurrentProcess(); |
|
vinfo.dwOSVersionInfoSize = sizeof(vinfo); |
|
GetVersionEx(&vinfo); |
|
if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) |
|
is_winnt = 1; |
|
else |
|
is_winnt = 0; |
|
} |
|
if ( is_winnt ) { |
|
FILETIME c,e,k,u; |
|
|
|
GetProcessTimes(curproc,&c,&e,&k,&u); |
|
return ((double)k.dwLowDateTime+(double)u.dwLowDateTime |
|
+4294967296.0*((double)k.dwHighDateTime+(double)u.dwHighDateTime))/10000000.0; |
|
} else |
|
// return (double)clock()/(double)CLOCKS_PER_SEC; |
|
return ((double)GetTickCount())/1000.0; |
|
} |
|
|
|
#elif defined(THINK_C) || defined(__MWERKS__) || defined(MSWIN32) |
|
|
|
static double get_clock() |
|
{ |
|
clock_t c; |
|
|
|
c = clock(); |
|
return (double)c/(double)CLOCKS_PER_SEC; |
|
} |
|
|
|
#elif defined(_PA_RISC1_1) || defined(__svr4__) || defined(__CYGWIN__) |
|
|
|
#include <sys/time.h> |
|
#include <limits.h> |
|
|
|
static double get_clock() |
|
{ |
|
struct tms buf; |
|
|
|
times(&buf); |
|
return (double)(buf.tms_utime+buf.tms_stime)/(double)CLK_TCK; |
|
} |
|
|
|
#else |
|
|
|
#include <sys/time.h> |
|
#include <sys/resource.h> |
|
|
|
static double get_clock() |
|
{ |
|
int tv_sec,tv_usec; |
|
struct rusage ru; |
|
|
|
getrusage(RUSAGE_SELF,&ru); |
|
tv_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; |
|
tv_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; |
|
return (double)tv_sec+(double)tv_usec/(double)1000000; |
|
} |
|
#endif |
|
|
|
static double gctime, gcstart; |
|
|
|
void GC_timerstart() { |
|
gcstart = get_clock(); |
|
} |
|
|
|
void GC_timerstop() { |
|
gctime += get_clock() - gcstart; |
|
} |
|
|
|
double GC_get_gctime() { |
|
return gctime; |
|
} |
|
|
/*ARGSUSED*/ |
/*ARGSUSED*/ |
GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested)) |
GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested)) |
{ |
{ |
Line 132 GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) |
|
Line 235 GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) |
|
|
|
extern signed_word GC_mem_found; |
extern signed_word GC_mem_found; |
|
|
|
void * GC_project2(arg1, arg2) |
|
void *arg1; |
|
void *arg2; |
|
{ |
|
return arg2; |
|
} |
|
|
# ifdef MERGE_SIZES |
# ifdef MERGE_SIZES |
/* Set things up so that GC_size_map[i] >= words(i), */ |
/* Set things up so that GC_size_map[i] >= words(i), */ |
/* but not too much bigger */ |
/* but not too much bigger */ |
|
|
GC_init_parallel(); |
GC_init_parallel(); |
} |
} |
# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ |
# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ |
|
|
|
# if defined(DYNAMIC_LOADING) && defined(DARWIN) |
|
{ |
|
/* This must be called WITHOUT the allocation lock held |
|
and before any threads are created */ |
|
extern void GC_init_dyld(); |
|
GC_init_dyld(); |
|
} |
|
# endif |
} |
} |
|
|
#if defined(MSWIN32) || defined(MSWINCE) |
#if defined(MSWIN32) || defined(MSWINCE) |
|
|
|
|
extern void GC_setpagesize(); |
extern void GC_setpagesize(); |
|
|
|
|
|
#ifdef MSWIN32 |
|
extern GC_bool GC_no_win32_dlls; |
|
#else |
|
# define GC_no_win32_dlls FALSE |
|
#endif |
|
|
|
void GC_exit_check GC_PROTO((void)) |
|
{ |
|
GC_gcollect(); |
|
} |
|
|
|
#ifdef SEARCH_FOR_DATA_START |
|
extern void GC_init_linux_data_start GC_PROTO((void)); |
|
#endif |
|
|
#ifdef UNIX_LIKE |
#ifdef UNIX_LIKE |
|
|
extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int))); |
extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int))); |
|
|
GC_err_printf1("Caught signal %d: looping in handler\n", sig); |
GC_err_printf1("Caught signal %d: looping in handler\n", sig); |
for(;;); |
for(;;); |
} |
} |
#endif |
|
|
|
#ifdef MSWIN32 |
static GC_bool installed_looping_handler = FALSE; |
extern GC_bool GC_no_win32_dlls; |
|
#else |
void maybe_install_looping_handler() |
# define GC_no_win32_dlls FALSE |
{ |
|
/* Install looping handler before the write fault handler, so we */ |
|
/* handle write faults correctly. */ |
|
if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { |
|
GC_set_and_save_fault_handler(looping_handler); |
|
installed_looping_handler = TRUE; |
|
} |
|
} |
|
|
|
#else /* !UNIX_LIKE */ |
|
|
|
# define maybe_install_looping_handler() |
|
|
#endif |
#endif |
|
|
void GC_init_inner() |
void GC_init_inner() |
Line 515 void GC_init_inner() |
|
Line 661 void GC_init_inner() |
|
if (0 != GETENV("GC_PRINT_STATS")) { |
if (0 != GETENV("GC_PRINT_STATS")) { |
GC_print_stats = 1; |
GC_print_stats = 1; |
} |
} |
|
# ifndef NO_DEBUGGING |
|
if (0 != GETENV("GC_DUMP_REGULARLY")) { |
|
GC_dump_regularly = 1; |
|
} |
|
# endif |
if (0 != GETENV("GC_FIND_LEAK")) { |
if (0 != GETENV("GC_FIND_LEAK")) { |
GC_find_leak = 1; |
GC_find_leak = 1; |
|
# ifdef __STDC__ |
|
atexit(GC_exit_check); |
|
# endif |
} |
} |
if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { |
if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { |
GC_all_interior_pointers = 1; |
GC_all_interior_pointers = 1; |
Line 554 void GC_init_inner() |
|
Line 708 void GC_init_inner() |
|
} |
} |
} |
} |
} |
} |
# ifdef UNIX_LIKE |
maybe_install_looping_handler(); |
if (0 != GETENV("GC_LOOP_ON_ABORT")) { |
|
GC_set_and_save_fault_handler(looping_handler); |
|
} |
|
# endif |
|
/* Adjust normal object descriptor for extra allocation. */ |
/* Adjust normal object descriptor for extra allocation. */ |
if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { |
if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { |
GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); |
GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); |
Line 593 void GC_init_inner() |
|
Line 743 void GC_init_inner() |
|
# if defined(LINUX) && defined(IA64) |
# if defined(LINUX) && defined(IA64) |
GC_register_stackbottom = GC_get_register_stack_base(); |
GC_register_stackbottom = GC_get_register_stack_base(); |
# endif |
# endif |
|
} else { |
|
# if defined(LINUX) && defined(IA64) |
|
if (GC_register_stackbottom == 0) { |
|
WARN("GC_register_stackbottom should be set with GC_stackbottom", 0); |
|
/* The following is likely to fail, since we rely on */ |
|
/* alignment properties that may not hold with a user set */ |
|
/* GC_stackbottom. */ |
|
GC_register_stackbottom = GC_get_register_stack_base(); |
|
} |
|
# endif |
} |
} |
# endif |
# endif |
GC_ASSERT(sizeof (ptr_t) == sizeof(word)); |
GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); |
GC_ASSERT(sizeof (signed_word) == sizeof(word)); |
GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); |
GC_ASSERT(sizeof (struct hblk) == HBLKSIZE); |
GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); |
# ifndef THREADS |
# ifndef THREADS |
# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) |
# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) |
ABORT( |
ABORT( |
Line 621 void GC_init_inner() |
|
Line 781 void GC_init_inner() |
|
|
|
/* Add initial guess of root sets. Do this first, since sbrk(0) */ |
/* Add initial guess of root sets. Do this first, since sbrk(0) */ |
/* might be used. */ |
/* might be used. */ |
GC_register_data_segments(); |
if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments(); |
GC_init_headers(); |
GC_init_headers(); |
GC_bl_init(); |
GC_bl_init(); |
GC_mark_init(); |
GC_mark_init(); |
Line 636 void GC_init_inner() |
|
Line 796 void GC_init_inner() |
|
initial_heap_sz = divHBLKSZ(initial_heap_sz); |
initial_heap_sz = divHBLKSZ(initial_heap_sz); |
} |
} |
} |
} |
|
{ |
|
char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); |
|
if (sz_str != NULL) { |
|
word max_heap_sz = (word)atol(sz_str); |
|
if (max_heap_sz < initial_heap_sz * HBLKSIZE) { |
|
WARN("Bad maximum heap size %s - ignoring it.\n", |
|
sz_str); |
|
} |
|
if (0 == GC_max_retries) GC_max_retries = 2; |
|
GC_set_max_heap_size(max_heap_sz); |
|
} |
|
} |
if (!GC_expand_hp_inner(initial_heap_sz)) { |
if (!GC_expand_hp_inner(initial_heap_sz)) { |
GC_err_printf0("Can't start up: not enough memory\n"); |
GC_err_printf0("Can't start up: not enough memory\n"); |
EXIT(); |
EXIT(); |
Line 671 void GC_init_inner() |
|
Line 843 void GC_init_inner() |
|
GC_incremental = TRUE; |
GC_incremental = TRUE; |
} |
} |
# endif /* !SMALL_CONFIG */ |
# endif /* !SMALL_CONFIG */ |
|
COND_DUMP; |
/* Get black list set up and/or incrmental GC started */ |
/* Get black list set up and/or incrmental GC started */ |
if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); |
if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); |
GC_is_initialized = TRUE; |
GC_is_initialized = TRUE; |
Line 706 void GC_enable_incremental GC_PROTO(()) |
|
Line 879 void GC_enable_incremental GC_PROTO(()) |
|
if (GC_incremental) goto out; |
if (GC_incremental) goto out; |
GC_setpagesize(); |
GC_setpagesize(); |
if (GC_no_win32_dlls) goto out; |
if (GC_no_win32_dlls) goto out; |
# ifndef GC_SOLARIS_THREADS |
# ifndef GC_SOLARIS_THREADS |
GC_dirty_init(); |
maybe_install_looping_handler(); /* Before write fault handler! */ |
|
GC_dirty_init(); |
# endif |
# endif |
if (!GC_is_initialized) { |
if (!GC_is_initialized) { |
GC_init_inner(); |
GC_init_inner(); |
Line 926 GC_warn_proc GC_current_warn_proc = GC_default_warn_pr |
|
Line 1100 GC_warn_proc GC_current_warn_proc = GC_default_warn_pr |
|
return(result); |
return(result); |
} |
} |
|
|
|
# if defined(__STDC__) || defined(__cplusplus) |
|
GC_word GC_set_free_space_divisor (GC_word value) |
|
# else |
|
GC_word GC_set_free_space_divisor (value) |
|
GC_word value; |
|
# endif |
|
{ |
|
GC_word old = GC_free_space_divisor; |
|
GC_free_space_divisor = value; |
|
return old; |
|
} |
|
|
#ifndef PCR |
#ifndef PCR |
void GC_abort(msg) |
void GC_abort(msg) |
Line 952 GC_CONST char * msg; |
|
Line 1137 GC_CONST char * msg; |
|
} |
} |
#endif |
#endif |
|
|
|
|
/* Needed by SRC_M3, gcj, and should perhaps be the official interface */ |
|
/* to GC_dont_gc. */ |
|
void GC_enable() |
void GC_enable() |
{ |
{ |
|
LOCK(); |
GC_dont_gc--; |
GC_dont_gc--; |
|
UNLOCK(); |
} |
} |
|
|
void GC_disable() |
void GC_disable() |
{ |
{ |
|
LOCK(); |
GC_dont_gc++; |
GC_dont_gc++; |
|
UNLOCK(); |
} |
} |
|
|
#if !defined(NO_DEBUGGING) |
#if !defined(NO_DEBUGGING) |
|
|
GC_print_hblkfreelist(); |
GC_print_hblkfreelist(); |
GC_printf0("\n***Blocks in use:\n"); |
GC_printf0("\n***Blocks in use:\n"); |
GC_print_block_list(); |
GC_print_block_list(); |
|
GC_printf0("\n***Finalization statistics:\n"); |
|
GC_print_finalization_stats(); |
} |
} |
|
|
#endif /* NO_DEBUGGING */ |
#endif /* NO_DEBUGGING */ |