mirror of git://gcc.gnu.org/git/gcc.git
mark_rts.c (GC_cond_register_dynamic_libraries): add.
2003-03-03 Hans Boehm <Hans.Boehm@hp.com> * mark_rts.c (GC_cond_register_dynamic_libraries): add. (GC_push_roots): explicitly mark free list headers, register dynamic libraries only if !REGISTER_LIBRARIES_EARLY. * alloc.c (GC_stopped_mark): Conditionally call GC_cond_register_dynamic_libraries(). (GC_collect_a_little_inner, GC_try_to_collect_inner): Check GC_dont_gc. * dyn_load.c (GC_register_main_static_data): define. (GC_register_dyn_libraries (Linux /proc, Linux ELF versions)): no longer skip main data. * misc.c (GC_REGISTER_MAIN_STATIC_DATA): define. (GC_init_inner): Make main data registration conditional. * include/private/gc_priv.h (GC_register_main_static_data): declare. * include/private/gcconfig.h (REGISTER_LIBRARIES_EARLY): define for LINUX. From-SVN: r63727
This commit is contained in:
parent
b22b239e5a
commit
ebcc6a7ec0
|
|
@ -1,3 +1,19 @@
|
||||||
|
2003-03-03 Hans Boehm <Hans.Boehm@hp.com>
|
||||||
|
* mark_rts.c (GC_cond_register_dynamic_libraries): add.
|
||||||
|
(GC_push_roots): explicitly mark free list headers, register
|
||||||
|
dynamic libraries only if !REGISTER_LIBRARIES_EARLY.
|
||||||
|
* alloc.c (GC_stopped_mark): Conditionally call
|
||||||
|
GC_cond_register_dynamic_libraries().
|
||||||
|
(GC_collect_a_little_inner, GC_try_to_collect_inner): Check GC_dont_gc.
|
||||||
|
* dyn_load.c (GC_register_main_static_data): define.
|
||||||
|
(GC_register_dyn_libraries (Linux /proc, Linux ELF versions)):
|
||||||
|
no longer skip main data.
|
||||||
|
* misc.c (GC_REGISTER_MAIN_STATIC_DATA): define.
|
||||||
|
(GC_init_inner): Make main data registration conditional.
|
||||||
|
* include/private/gc_priv.h (GC_register_main_static_data): declare.
|
||||||
|
* include/private/gcconfig.h (REGISTER_LIBRARIES_EARLY): define
|
||||||
|
for LINUX.
|
||||||
|
|
||||||
2003-02-20 Alexandre Oliva <aoliva@redhat.com>
|
2003-02-20 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
* configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to
|
* configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ void GC_maybe_gc()
|
||||||
GC_bool GC_try_to_collect_inner(stop_func)
|
GC_bool GC_try_to_collect_inner(stop_func)
|
||||||
GC_stop_func stop_func;
|
GC_stop_func stop_func;
|
||||||
{
|
{
|
||||||
|
if (GC_dont_gc) return FALSE;
|
||||||
if (GC_incremental && GC_collection_in_progress()) {
|
if (GC_incremental && GC_collection_in_progress()) {
|
||||||
# ifdef CONDPRINT
|
# ifdef CONDPRINT
|
||||||
if (GC_print_stats) {
|
if (GC_print_stats) {
|
||||||
|
|
@ -386,6 +387,7 @@ int n;
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
|
if (GC_dont_gc) return;
|
||||||
if (GC_incremental && GC_collection_in_progress()) {
|
if (GC_incremental && GC_collection_in_progress()) {
|
||||||
for (i = GC_deficit; i < GC_RATE*n; i++) {
|
for (i = GC_deficit; i < GC_RATE*n; i++) {
|
||||||
if (GC_mark_some((ptr_t)0)) {
|
if (GC_mark_some((ptr_t)0)) {
|
||||||
|
|
@ -446,6 +448,9 @@ GC_stop_func stop_func;
|
||||||
CLOCK_TYPE start_time, current_time;
|
CLOCK_TYPE start_time, current_time;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# if defined(REGISTER_LIBRARIES_EARLY)
|
||||||
|
GC_cond_register_dynamic_libraries();
|
||||||
|
# endif
|
||||||
STOP_WORLD();
|
STOP_WORLD();
|
||||||
# ifdef PRINTTIMES
|
# ifdef PRINTTIMES
|
||||||
GET_TIME(start_time);
|
GET_TIME(start_time);
|
||||||
|
|
|
||||||
|
|
@ -355,10 +355,6 @@ void GC_register_dynamic_libraries()
|
||||||
/* Stack mapping; discard */
|
/* Stack mapping; discard */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (start <= datastart && end > datastart && maj_dev != 0) {
|
|
||||||
/* Main data segment; discard */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# ifdef THREADS
|
# ifdef THREADS
|
||||||
if (GC_segment_is_thread_stack(start, end)) continue;
|
if (GC_segment_is_thread_stack(start, end)) continue;
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -384,6 +380,13 @@ void GC_register_dynamic_libraries()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We now take care of the main data segment ourselves: */
|
||||||
|
GC_bool GC_register_main_static_data()
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define HAVE_REGISTER_MAIN_STATIC_DATA
|
||||||
//
|
//
|
||||||
// parse_map_entry parses an entry from /proc/self/maps so we can
|
// parse_map_entry parses an entry from /proc/self/maps so we can
|
||||||
// locate all writable data segments that belong to shared libraries.
|
// locate all writable data segments that belong to shared libraries.
|
||||||
|
|
@ -469,13 +472,6 @@ static int GC_register_dynlib_callback(info, size, ptr)
|
||||||
+ sizeof (info->dlpi_phnum))
|
+ sizeof (info->dlpi_phnum))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Skip the first object - it is the main program. */
|
|
||||||
if (*(int *)ptr == 0)
|
|
||||||
{
|
|
||||||
*(int *)ptr = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = info->dlpi_phdr;
|
p = info->dlpi_phdr;
|
||||||
for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) {
|
for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) {
|
||||||
switch( p->p_type ) {
|
switch( p->p_type ) {
|
||||||
|
|
@ -510,6 +506,14 @@ GC_bool GC_register_dynamic_libraries_dl_iterate_phdr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do we need to separately register the main static data segment? */
|
||||||
|
GC_bool GC_register_main_static_data()
|
||||||
|
{
|
||||||
|
return (dl_iterate_phdr == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HAVE_REGISTER_MAIN_STATIC_DATA
|
||||||
|
|
||||||
# else /* !LINUX || version(glibc) < 2.2.4 */
|
# else /* !LINUX || version(glibc) < 2.2.4 */
|
||||||
|
|
||||||
/* Dynamic loading code for Linux running ELF. Somewhat tested on
|
/* Dynamic loading code for Linux running ELF. Somewhat tested on
|
||||||
|
|
@ -775,9 +779,22 @@ void GC_register_dynamic_libraries()
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef MSWINCE
|
# ifdef MSWINCE
|
||||||
|
/* Do we need to separately register the main static data segment? */
|
||||||
|
GC_bool GC_register_main_static_data()
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
# else /* win32 */
|
||||||
extern GC_bool GC_no_win32_dlls;
|
extern GC_bool GC_no_win32_dlls;
|
||||||
# endif
|
|
||||||
|
GC_bool GC_register_main_static_data()
|
||||||
|
{
|
||||||
|
return GC_no_win32_dlls;
|
||||||
|
}
|
||||||
|
# endif /* win32 */
|
||||||
|
|
||||||
|
# define HAVE_REGISTER_MAIN_STATIC_DATA
|
||||||
|
|
||||||
void GC_register_dynamic_libraries()
|
void GC_register_dynamic_libraries()
|
||||||
{
|
{
|
||||||
|
|
@ -1079,4 +1096,15 @@ void GC_register_dynamic_libraries(){}
|
||||||
int GC_no_dynamic_loading;
|
int GC_no_dynamic_loading;
|
||||||
|
|
||||||
#endif /* !PCR */
|
#endif /* !PCR */
|
||||||
|
|
||||||
#endif /* !DYNAMIC_LOADING */
|
#endif /* !DYNAMIC_LOADING */
|
||||||
|
|
||||||
|
#ifndef HAVE_REGISTER_MAIN_STATIC_DATA
|
||||||
|
|
||||||
|
/* Do we need to separately register the main static data segment? */
|
||||||
|
GC_bool GC_register_main_static_data()
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1463,6 +1463,11 @@ GC_bool GC_is_tmp_root GC_PROTO((ptr_t p));
|
||||||
void GC_register_dynamic_libraries GC_PROTO((void));
|
void GC_register_dynamic_libraries GC_PROTO((void));
|
||||||
/* Add dynamic library data sections to the root set. */
|
/* Add dynamic library data sections to the root set. */
|
||||||
|
|
||||||
|
GC_bool GC_register_main_static_data GC_PROTO((void));
|
||||||
|
/* We need to register the main data segment. Returns */
|
||||||
|
/* TRUE unless this is done implicitly as part of */
|
||||||
|
/* dynamic library registration. */
|
||||||
|
|
||||||
/* Machine dependent startup routines */
|
/* Machine dependent startup routines */
|
||||||
ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */
|
ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */
|
||||||
#ifdef IA64
|
#ifdef IA64
|
||||||
|
|
|
||||||
|
|
@ -1801,6 +1801,15 @@
|
||||||
# define CACHE_LINE_SIZE 32 /* Wild guess */
|
# define CACHE_LINE_SIZE 32 /* Wild guess */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef LINUX
|
||||||
|
# define REGISTER_LIBRARIES_EARLY
|
||||||
|
/* We sometimes use dl_iterate_phdr, which may acquire an internal */
|
||||||
|
/* lock. This isn't safe after the world has stopped. So we must */
|
||||||
|
/* call GC_register_dynamic_libraries before stopping the world. */
|
||||||
|
/* For performance reasons, this may be beneficial on other */
|
||||||
|
/* platforms as well, though it should be avoided in win32. */
|
||||||
|
# endif /* LINUX */
|
||||||
|
|
||||||
# ifndef CLEAR_DOUBLE
|
# ifndef CLEAR_DOUBLE
|
||||||
# define CLEAR_DOUBLE(x) \
|
# define CLEAR_DOUBLE(x) \
|
||||||
((word*)x)[0] = 0; \
|
((word*)x)[0] = 0; \
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,17 @@ void GC_push_gc_structures GC_PROTO((void))
|
||||||
void GC_mark_thread_local_free_lists();
|
void GC_mark_thread_local_free_lists();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void GC_cond_register_dynamic_libraries()
|
||||||
|
{
|
||||||
|
# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
|
||||||
|
|| defined(PCR)) && !defined(SRC_M3)
|
||||||
|
GC_remove_tmp_roots();
|
||||||
|
if (!GC_no_dls) GC_register_dynamic_libraries();
|
||||||
|
# else
|
||||||
|
GC_no_dls = TRUE;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
|
* Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
|
||||||
* on groups of pointers) on every top level accessible pointer.
|
* on groups of pointers) on every top level accessible pointer.
|
||||||
|
|
@ -519,19 +530,20 @@ void GC_push_roots(all, cold_gc_frame)
|
||||||
GC_bool all;
|
GC_bool all;
|
||||||
ptr_t cold_gc_frame;
|
ptr_t cold_gc_frame;
|
||||||
{
|
{
|
||||||
register int i;
|
int i;
|
||||||
|
int kind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next push static data. This must happen early on, since it's
|
* Next push static data. This must happen early on, since it's
|
||||||
* not robust against mark stack overflow.
|
* not robust against mark stack overflow.
|
||||||
*/
|
*/
|
||||||
/* Reregister dynamic libraries, in case one got added. */
|
/* Reregister dynamic libraries, in case one got added. */
|
||||||
# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
|
/* There is some argument for doing this as late as possible, */
|
||||||
|| defined(PCR)) && !defined(SRC_M3)
|
/* especially on win32, where it can change asynchronously. */
|
||||||
GC_remove_tmp_roots();
|
/* In those cases, we do it here. But on other platforms, it's */
|
||||||
if (!GC_no_dls) GC_register_dynamic_libraries();
|
/* not safe with the world stopped, so we do it earlier. */
|
||||||
# else
|
# if !defined(REGISTER_LIBRARIES_EARLY)
|
||||||
GC_no_dls = TRUE;
|
GC_cond_register_dynamic_libraries();
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Mark everything in static data areas */
|
/* Mark everything in static data areas */
|
||||||
|
|
@ -541,6 +553,18 @@ ptr_t cold_gc_frame;
|
||||||
GC_static_roots[i].r_end, all);
|
GC_static_roots[i].r_end, all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark all free list header blocks, if those were allocated from */
|
||||||
|
/* the garbage collected heap. This makes sure they don't */
|
||||||
|
/* disappear if we are not marking from static data. It also */
|
||||||
|
/* saves us the trouble of scanning them, and possibly that of */
|
||||||
|
/* marking the freelists. */
|
||||||
|
for (kind = 0; kind < GC_n_kinds; kind++) {
|
||||||
|
GC_PTR base = GC_base(GC_obj_kinds[kind].ok_freelist);
|
||||||
|
if (0 != base) {
|
||||||
|
GC_set_mark_bit(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark from GC internal roots if those might otherwise have */
|
/* Mark from GC internal roots if those might otherwise have */
|
||||||
/* been excluded. */
|
/* been excluded. */
|
||||||
if (GC_no_dls || roots_were_cleared) {
|
if (GC_no_dls || roots_were_cleared) {
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,14 @@
|
||||||
#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 } */;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -572,7 +580,7 @@ void GC_init_inner()
|
||||||
GC_init_win32();
|
GC_init_win32();
|
||||||
# endif
|
# endif
|
||||||
# if defined(SEARCH_FOR_DATA_START)
|
# if defined(SEARCH_FOR_DATA_START)
|
||||||
GC_init_linux_data_start();
|
if (GC_REGISTER_MAIN_STATIC_DATA()) GC_init_linux_data_start();
|
||||||
# endif
|
# endif
|
||||||
# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
|
# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
|
||||||
GC_init_netbsd_elf();
|
GC_init_netbsd_elf();
|
||||||
|
|
@ -619,7 +627,7 @@ 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();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue