=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/gc/misc.c,v retrieving revision 1.4 retrieving revision 1.9 diff -u -p -r1.4 -r1.9 --- OpenXM_contrib2/asir2000/gc/misc.c 2001/04/20 07:39:19 1.4 +++ OpenXM_contrib2/asir2000/gc/misc.c 2009/02/15 17:20:31 1.9 @@ -1,6 +1,7 @@ /* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -15,6 +16,7 @@ #include +#include #ifndef _WIN32_WCE #include #endif @@ -22,7 +24,7 @@ #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */ #include "private/gc_pmark.h" -#ifdef SOLARIS_THREADS +#ifdef GC_SOLARIS_THREADS # include #endif #if defined(MSWIN32) || defined(MSWINCE) @@ -41,29 +43,29 @@ /* Critical section counter is defined in the M3 runtime */ /* That's all we use. */ # else -# ifdef SOLARIS_THREADS +# ifdef GC_SOLARIS_THREADS mutex_t GC_allocate_ml; /* Implicitly initialized. */ # else -# ifdef WIN32_THREADS -# if defined(_DLL) || defined(GC_DLL) +# if defined(GC_WIN32_THREADS) +# if defined(GC_PTHREADS) + pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; +# elif defined(GC_DLL) __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; # else CRITICAL_SECTION GC_allocate_ml; # endif # else -# if defined(IRIX_THREADS) \ - || (defined(LINUX_THREADS) && defined(USE_SPIN_LOCK)) - pthread_t GC_lock_holder = NO_THREAD; -# else -# if defined(HPUX_THREADS) \ - || defined(LINUX_THREADS) && !defined(USE_SPIN_LOCK) +# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) +# if defined(USE_SPIN_LOCK) + pthread_t GC_lock_holder = NO_THREAD; +# else pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; pthread_t GC_lock_holder = NO_THREAD; /* Used only for assertions, and to prevent */ /* recursive reentry in the system call wrapper. */ -# else +# endif +# else --> declare allocator lock here -# endif # endif # endif # endif @@ -71,6 +73,18 @@ # endif # endif +#if defined(NOSYS) || defined(ECOS) +#undef STACKBASE +#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 } */; @@ -78,6 +92,7 @@ GC_bool GC_debugging_started = FALSE; /* defined here so we don't have to load debug_malloc.o */ void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; +void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; @@ -95,6 +110,12 @@ GC_bool GC_quiet = 0; GC_bool GC_print_stats = 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 int GC_find_leak = 1; #else @@ -107,6 +128,103 @@ GC_bool GC_print_stats = 0; int GC_all_interior_pointers = 0; #endif +#if 0 +long GC_large_alloc_warn_interval = 5; +#else +long GC_large_alloc_warn_interval = LONG_MAX; +#endif + /* Interval between unsuppressed warnings. */ + +long GC_large_alloc_warn_suppressed = 0; + /* Number of warnings suppressed so far. */ + +#include + +#if defined(VISUAL) +#include + +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 +#include + +static double get_clock() +{ + struct tms buf; + + times(&buf); + return (double)(buf.tms_utime+buf.tms_stime)/(double)CLK_TCK; +} + +#else + +#include +#include + +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*/ GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested)) { @@ -117,6 +235,13 @@ GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) extern signed_word GC_mem_found; +void * GC_project2(arg1, arg2) +void *arg1; +void *arg2; +{ + return arg2; +} + # ifdef MERGE_SIZES /* Set things up so that GC_size_map[i] >= words(i), */ /* but not too much bigger */ @@ -297,6 +422,8 @@ ptr_t arg; if (++random_no % 13 == 0) { limit = sp; MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word)); + limit &= ~0xf; /* Make it sufficiently aligned for assembly */ + /* implementations of GC_clear_stack_inner. */ return GC_clear_stack_inner(arg, limit); } else { BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word)); @@ -432,11 +559,34 @@ void GC_init() DCL_LOCK_STATE; DISABLE_SIGNALS(); + +#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) + if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml); +#endif /* MSWIN32 */ + LOCK(); GC_init_inner(); UNLOCK(); ENABLE_SIGNALS(); +# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + /* Make sure marker threads and started and thread local */ + /* allocation is initialized, in case we didn't get */ + /* called from GC_init_parallel(); */ + { + extern void GC_init_parallel(void); + GC_init_parallel(); + } +# 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) @@ -449,6 +599,22 @@ void GC_init() 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 extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int))); @@ -459,6 +625,23 @@ int sig; GC_err_printf1("Caught signal %d: looping in handler\n", sig); for(;;); } + +static GC_bool installed_looping_handler = FALSE; + +void maybe_install_looping_handler() +{ + /* 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 void GC_init_inner() @@ -472,11 +655,22 @@ void GC_init_inner() # ifdef PRINTSTATS GC_print_stats = 1; # endif +# if defined(MSWIN32) || defined(MSWINCE) + InitializeCriticalSection(&GC_write_cs); +# endif if (0 != GETENV("GC_PRINT_STATS")) { GC_print_stats = 1; } +# ifndef NO_DEBUGGING + if (0 != GETENV("GC_DUMP_REGULARLY")) { + GC_dump_regularly = 1; + } +# endif if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1; +# ifdef __STDC__ + atexit(GC_exit_check); +# endif } if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; @@ -484,18 +678,41 @@ void GC_init_inner() if (0 != GETENV("GC_DONT_GC")) { GC_dont_gc = 1; } -# ifdef UNIX_LIKE - if (0 != GETENV("GC_LOOP_ON_ABORT")) { - GC_set_and_save_fault_handler(looping_handler); + if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) { + GC_print_back_height = 1; + } + if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) { + GC_large_alloc_warn_interval = LONG_MAX; + } + { + char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); + if (0 != time_limit_string) { + long time_limit = atol(time_limit_string); + if (time_limit < 5) { + WARN("GC_PAUSE_TIME_TARGET environment variable value too small " + "or bad syntax: Ignoring\n", 0); + } else { + GC_time_limit = time_limit; + } } -# endif + } + { + char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL"); + if (0 != interval_string) { + long interval = atol(interval_string); + if (interval <= 0) { + WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has " + "bad value: Ignoring\n", 0); + } else { + GC_large_alloc_warn_interval = interval; + } + } + } + maybe_install_looping_handler(); /* Adjust normal object descriptor for extra allocation. */ if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); } -# if defined(MSWIN32) || defined(MSWINCE) - InitializeCriticalSection(&GC_write_cs); -# endif GC_setpagesize(); GC_exclude_static_roots(beginGC_arrays, endGC_arrays); GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds); @@ -509,30 +726,38 @@ void GC_init_inner() # if defined(SEARCH_FOR_DATA_START) GC_init_linux_data_start(); # endif -# if defined(NETBSD) && defined(__ELF__) +# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) GC_init_netbsd_elf(); # endif -# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \ - || defined(HPUX_THREADS) || defined(SOLARIS_THREADS) +# if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) GC_thr_init(); # endif -# ifdef SOLARIS_THREADS +# ifdef GC_SOLARIS_THREADS /* We need dirty bits in order to find live stack sections. */ GC_dirty_init(); # endif -# if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \ - || defined(IRIX_THREADS) || defined(LINUX_THREADS) \ - || defined(HPUX_THREADS) +# if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \ + || defined(GC_SOLARIS_THREADS) if (GC_stackbottom == 0) { GC_stackbottom = GC_get_stack_base(); # if defined(LINUX) && defined(IA64) GC_register_stackbottom = GC_get_register_stack_base(); # 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 - GC_ASSERT(sizeof (ptr_t) == sizeof(word)); - GC_ASSERT(sizeof (signed_word) == sizeof(word)); - GC_ASSERT(sizeof (struct hblk) == HBLKSIZE); + GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); + GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); + GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); # ifndef THREADS # if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) ABORT( @@ -556,7 +781,7 @@ void GC_init_inner() /* Add initial guess of root sets. Do this first, since sbrk(0) */ /* might be used. */ - GC_register_data_segments(); + if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments(); GC_init_headers(); GC_bl_init(); GC_mark_init(); @@ -571,6 +796,18 @@ void GC_init_inner() 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)) { GC_err_printf0("Can't start up: not enough memory\n"); EXIT(); @@ -595,8 +832,20 @@ void GC_init_inner() PCR_IL_Unlock(); GC_pcr_install(); # endif - /* Get black list set up */ - if (!GC_dont_precollect) GC_gcollect_inner(); +# if !defined(SMALL_CONFIG) + if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) { + GC_ASSERT(!GC_incremental); + GC_setpagesize(); +# ifndef GC_SOLARIS_THREADS + GC_dirty_init(); +# endif + GC_ASSERT(GC_words_allocd == 0) + GC_incremental = TRUE; + } +# endif /* !SMALL_CONFIG */ + COND_DUMP; + /* Get black list set up and/or incrmental GC started */ + if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); GC_is_initialized = TRUE; # ifdef STUBBORN_ALLOC GC_stubborn_init(); @@ -629,20 +878,15 @@ void GC_enable_incremental GC_PROTO(()) LOCK(); if (GC_incremental) goto out; GC_setpagesize(); -# ifdef MSWIN32 - { - extern GC_bool GC_is_win32s(); - - /* VirtualProtect is not functional under win32s. */ - if (GC_is_win32s()) goto out; - } -# endif /* MSWIN32 */ -# ifndef SOLARIS_THREADS - GC_dirty_init(); + if (GC_no_win32_dlls) goto out; +# ifndef GC_SOLARIS_THREADS + maybe_install_looping_handler(); /* Before write fault handler! */ + GC_dirty_init(); # endif if (!GC_is_initialized) { GC_init_inner(); } + if (GC_incremental) goto out; if (GC_dont_gc) { /* Can't easily do it. */ UNLOCK(); @@ -678,7 +922,7 @@ out: } int GC_write(buf, len) - char * buf; + GC_CONST char * buf; size_t len; { BOOL tmp; @@ -728,17 +972,18 @@ int GC_tmp; /* Should really be local ... */ # endif #endif -#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) && !defined(MACOS) +#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \ + && !defined(MACOS) && !defined(ECOS) && !defined(NOSYS) int GC_write(fd, buf, len) int fd; -char *buf; +GC_CONST char *buf; size_t len; { register int bytes_written = 0; register int result; while (bytes_written < len) { -# ifdef SOLARIS_THREADS +# ifdef GC_SOLARIS_THREADS result = syscall(SYS_write, fd, buf + bytes_written, len - bytes_written); # else @@ -751,6 +996,23 @@ size_t len; } #endif /* UN*X */ +#ifdef ECOS +int GC_write(fd, buf, len) +{ + _Jv_diag_write (buf, len); + return len; +} +#endif + +#ifdef NOSYS +int GC_write(fd, buf, len) +{ + /* No writing. */ + return len; +} +#endif + + #if defined(MSWIN32) || defined(MSWINCE) # define WRITE(f, buf, len) GC_write(buf, len) #else @@ -838,6 +1100,17 @@ GC_warn_proc GC_current_warn_proc = GC_default_warn_pr 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 void GC_abort(msg) @@ -854,7 +1127,7 @@ GC_CONST char * msg; /* It's arguably nicer to sleep, but that makes it harder */ /* to look at the thread if the debugger doesn't know much */ /* about threads. */ - for(;;); + for(;;) {} } # ifdef MSWIN32 DebugBreak(); @@ -864,49 +1137,18 @@ GC_CONST char * msg; } #endif -#ifdef NEED_CALLINFO - -void GC_print_callers (info) -struct callinfo info[NFRAMES]; -{ - register int i; - -# if NFRAMES == 1 - GC_err_printf0("\tCaller at allocation:\n"); -# else - GC_err_printf0("\tCall chain at allocation:\n"); -# endif - for (i = 0; i < NFRAMES; i++) { - if (info[i].ci_pc == 0) break; -# if NARGS > 0 - { - int j; - - GC_err_printf0("\t\targs: "); - for (j = 0; j < NARGS; j++) { - if (j != 0) GC_err_printf0(", "); - GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]), - ~(info[i].ci_arg[j])); - } - GC_err_printf0("\n"); - } -# endif - GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc); - } -} - -#endif /* SAVE_CALL_CHAIN */ - -/* Needed by SRC_M3, gcj, and should perhaps be the official interface */ -/* to GC_dont_gc. */ void GC_enable() { + LOCK(); GC_dont_gc--; + UNLOCK(); } void GC_disable() { + LOCK(); GC_dont_gc++; + UNLOCK(); } #if !defined(NO_DEBUGGING) @@ -921,6 +1163,8 @@ void GC_dump() GC_print_hblkfreelist(); GC_printf0("\n***Blocks in use:\n"); GC_print_block_list(); + GC_printf0("\n***Finalization statistics:\n"); + GC_print_finalization_stats(); } #endif /* NO_DEBUGGING */