summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c181
1 files changed, 147 insertions, 34 deletions
diff --git a/misc.c b/misc.c
index 94ef15d..b2adad2 100644
--- a/misc.c
+++ b/misc.c
@@ -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.
@@ -22,7 +23,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 <sys/syscall.h>
#endif
#if defined(MSWIN32) || defined(MSWINCE)
@@ -41,29 +42,27 @@
/* 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
+# ifdef GC_WIN32_THREADS
# if !defined(GC_NOT_DLL) && (defined(_DLL) || 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,7 +70,7 @@
# endif
# endif
-#ifdef ECOS
+#if defined(NOSYS) || defined(ECOS)
#undef STACKBASE
#endif
@@ -99,6 +98,8 @@ GC_bool GC_quiet = 0;
GC_bool GC_print_stats = 0;
+GC_bool GC_print_back_height = 0;
+
#ifdef FIND_LEAK
int GC_find_leak = 1;
#else
@@ -438,6 +439,11 @@ void GC_init()
DCL_LOCK_STATE;
DISABLE_SIGNALS();
+
+#ifdef GC_WIN32_THREADS
+ if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
+#endif /* MSWIN32 */
+
LOCK();
GC_init_inner();
UNLOCK();
@@ -476,6 +482,12 @@ int sig;
}
#endif
+#ifdef MSWIN32
+ extern GC_bool GC_is_win32s();
+#else
+# define GC_is_win32s() FALSE
+#endif
+
void GC_init_inner()
{
# if !defined(THREADS) && defined(GC_ASSERTIONS)
@@ -499,6 +511,22 @@ void GC_init_inner()
if (0 != GETENV("GC_DONT_GC")) {
GC_dont_gc = 1;
}
+ if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
+ GC_print_back_height = 1;
+ }
+ {
+ char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
+ if (0 != time_limit_string) {
+ long time_limit;
+ if (time_limit_string != 0) 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;
+ }
+ }
+ }
# ifdef UNIX_LIKE
if (0 != GETENV("GC_LOOP_ON_ABORT")) {
GC_set_and_save_fault_handler(looping_handler);
@@ -524,20 +552,18 @@ 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)
@@ -610,8 +636,19 @@ 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_is_win32s() && 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 */
+ /* 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();
@@ -644,20 +681,14 @@ 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
+ if (GC_is_win32s()) goto out;
+# ifndef GC_SOLARIS_THREADS
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();
@@ -743,7 +774,8 @@ 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;
GC_CONST char *buf;
@@ -753,7 +785,7 @@ size_t len;
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
@@ -766,7 +798,7 @@ size_t len;
}
#endif /* UN*X */
-#if defined(ECOS)
+#ifdef ECOS
int GC_write(fd, buf, len)
{
_Jv_diag_write (buf, len);
@@ -774,6 +806,14 @@ int GC_write(fd, buf, 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)
@@ -890,6 +930,13 @@ GC_CONST char * msg;
#ifdef NEED_CALLINFO
+#ifdef HAVE_BUILTIN_BACKTRACE
+# include <execinfo.h>
+# ifdef LINUX
+# include <unistd.h>
+# endif
+#endif
+
void GC_print_callers (info)
struct callinfo info[NFRAMES];
{
@@ -915,7 +962,73 @@ struct callinfo info[NFRAMES];
GC_err_printf0("\n");
}
# endif
- GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc);
+# if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC)
+ /* Unfortunately backtrace_symbols calls malloc, which makes */
+ /* it dangersous if that has been redirected. */
+ {
+ char **sym_name =
+ backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
+ char *name = sym_name[0];
+ GC_bool found_it = (strchr(name, '(') != 0);
+ FILE *pipe;
+# ifdef LINUX
+ if (!found_it) {
+# define EXE_SZ 100
+ static char exe_name[EXE_SZ];
+# define CMD_SZ 200
+ char cmd_buf[CMD_SZ];
+# define RESULT_SZ 200
+ static char result_buf[RESULT_SZ];
+ size_t result_len;
+ static GC_bool found_exe_name = FALSE;
+ static GC_bool will_fail = FALSE;
+ int ret_code;
+ /* Unfortunately, this is the common case for the */
+ /* main executable. */
+ /* Try to get it via a hairy and expensive scheme. */
+ /* First we get the name of the executable: */
+ if (will_fail) goto out;
+ if (!found_exe_name) {
+ ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
+ if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {
+ will_fail = TRUE; /* Dont try again. */
+ goto out;
+ }
+ exe_name[ret_code] = '\0';
+ found_exe_name = TRUE;
+ }
+ /* Then we use popen to start addr2line -e <exe> <addr> */
+ /* There are faster ways to do this, but hopefully this */
+ /* isn't time critical. */
+ sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name,
+ (unsigned long)info[i].ci_pc);
+ pipe = popen(cmd_buf, "r");
+ if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) {
+ will_fail = TRUE;
+ goto out;
+ }
+ result_len = strlen(result_buf);
+ if (result_buf[result_len - 1] == '\n') --result_len;
+ if (result_buf[0] == '?'
+ || result_buf[result_len-2] == ':'
+ && result_buf[result_len-1] == '0')
+ goto out;
+ if (result_len < RESULT_SZ - 25) {
+ /* Add in hex address */
+ sprintf(result_buf + result_len, " [0x%lx]",
+ (unsigned long)info[i].ci_pc);
+ }
+ name = result_buf;
+ pclose(pipe);
+ out:
+ }
+# endif
+ GC_err_printf1("\t\t%s\n", name);
+ free(sym_name);
+ }
+# else
+ GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
+# endif
}
}