allchblk.c (GC_allochblk_nth): Dont overlook available space if GC disabled...

* allchblk.c (GC_allochblk_nth): Dont overlook available space if
	  GC disabled, correctly convert GC_finalizer_mem_freed to byte,
  	  total_size to words.
  	* dyn_load.c (win32 GC_register_dynamic_libraries): Consider only
	  MEM_IMAGE regions.
  	* mach_dep.c (GC_with_callee_saves_pushed): separate into new function,
	  and indent appropriately.
  	* mark_rts.c (GC_approx_sp): Access stack.
	* pthread_stop_world.c: (GC_suspend_handler): Explicitly push
	  callee-saves registers when appropriate.
  	  (GC_stop_world): Handle EINTR from sem_wait (sync with Mono GC).

From-SVN: r94776
This commit is contained in:
Hans Boehm 2005-02-09 21:33:02 +00:00 committed by Hans Boehm
parent dab80c81c6
commit 328d1d4c1c
6 changed files with 125 additions and 61 deletions

View File

@ -1,3 +1,17 @@
2005-02-07 Hans Boehm <Hans.Boehm@hp.com>
* allchblk.c (GC_allochblk_nth): Dont overlook available space if
GC disabled, correctly convert GC_finalizer_mem_freed to byte,
total_size to words.
* dyn_load.c (win32 GC_register_dynamic_libraries): Consider only
MEM_IMAGE regions.
* mach_dep.c (GC_with_callee_saves_pushed): separate into new function,
and indent appropriately.
* mark_rts.c (GC_approx_sp): Access stack.
* pthread_stop_world.c: (GC_suspend_handler): Explicitly push
callee-saves registers when appropriate.
(GC_stop_world): Handle EINTR from sem_wait (sync with Mono GC).
2005-01-01 Bryce McKinlay <mckinlay@redhat.com>
* configure.ac (AC_CONFIG_HEADERS): Build both include/gc_config.h

View File

@ -590,8 +590,9 @@ int n;
GET_HDR(hbp, hhdr);
size_avail = hhdr->hb_sz;
if (size_avail < size_needed) continue;
if (!GC_use_entire_heap
&& size_avail != size_needed
if (size_avail != size_needed
&& !GC_use_entire_heap
&& !GC_dont_gc
&& USED_HEAP_SIZE >= GC_requested_heapsize
&& !TRUE_INCREMENTAL && GC_should_collect()) {
# ifdef USE_MUNMAP
@ -608,7 +609,8 @@ int n;
/* If we are deallocating lots of memory from */
/* finalizers, fail and collect sooner rather */
/* than later. */
if (GC_finalizer_mem_freed > (GC_heapsize >> 4)) {
if (WORDS_TO_BYTES(GC_finalizer_mem_freed)
> (GC_heapsize >> 4)) {
continue;
}
# endif /* !USE_MUNMAP */
@ -698,7 +700,7 @@ int n;
struct hblk * h;
struct hblk * prev = hhdr -> hb_prev;
GC_words_wasted += total_size;
GC_words_wasted += BYTES_TO_WORDS(total_size);
GC_large_free_bytes -= total_size;
GC_remove_from_fl(hhdr, n);
for (h = hbp; h < limit; h++) {

View File

@ -735,6 +735,10 @@ void GC_register_dynamic_libraries()
# define HAVE_REGISTER_MAIN_STATIC_DATA
/* The frame buffer testing code is dead in this version. */
/* We leave it here temporarily in case the switch to just */
/* testing for MEM_IMAGE sections causes un expected */
/* problems. */
GC_bool GC_warn_fb = TRUE; /* Warn about traced likely */
/* graphics memory. */
GC_bool GC_disallow_ignore_fb = FALSE;
@ -856,7 +860,11 @@ void GC_register_dynamic_libraries()
&& (protect == PAGE_EXECUTE_READWRITE
|| protect == PAGE_READWRITE)
&& !GC_is_heap_base(buf.AllocationBase)
&& !is_frame_buffer(p, buf.RegionSize)) {
/* This used to check for
* !is_frame_buffer(p, buf.RegionSize, buf.Type)
* instead of just checking for MEM_IMAGE.
* If something breaks, change it back. */
&& buf.Type == MEM_IMAGE) {
# ifdef DEBUG_VIRTUALQUERY
GC_dump_meminfo(&buf);
# endif

View File

@ -400,64 +400,79 @@ void GC_push_regs()
}
#endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
void GC_with_callee_saves_pushed(fn, arg)
void (*fn)();
ptr_t arg;
{
word dummy;
# if defined(USE_GENERIC_PUSH_REGS)
# ifdef HAVE_BUILTIN_UNWIND_INIT
/* This was suggested by Richard Henderson as the way to */
/* force callee-save registers and register windows onto */
/* the stack. */
__builtin_unwind_init();
# else /* !HAVE_BUILTIN_UNWIND_INIT */
/* Generic code */
/* The idea is due to Parag Patel at HP. */
/* We're not sure whether he would like */
/* to be he acknowledged for it or not. */
jmp_buf regs;
register word * i = (word *) regs;
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
/* Setjmp doesn't always clear all of the buffer. */
/* That tends to preserve garbage. Clear it. */
for (; (char *)i < lim; i++) {
*i = 0;
}
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
(void) setjmp(regs);
# else
(void) _setjmp(regs);
/* We don't want to mess with signals. According to */
/* SUSV3, setjmp() may or may not save signal mask. */
/* _setjmp won't, but is less portable. */
# endif
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
# elif defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */
/* We may still need this to save thread contexts. */
/* This should probably be used in all Posix/non-gcc */
/* settings. We defer that change to minimize risk. */
ucontext_t ctxt;
getcontext(&ctxt);
# else /* Shouldn't be needed */
ABORT("Unexpected call to GC_with_callee_saves_pushed");
# endif
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|| defined(IA64)
/* On a register window machine, we need to save register */
/* contents on the stack for this to work. The setjmp */
/* is probably not needed on SPARC, since pointers are */
/* only stored in windowed or scratch registers. It is */
/* needed on IA64, since some non-windowed registers are */
/* preserved. */
{
GC_save_regs_ret_val = GC_save_regs_in_stack();
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
/* __builtin_ia64_flushrs(). The latter will be done */
/* implicitly by __builtin_unwind_init() for gcc3.0.1 */
/* and later. */
}
# endif
fn(arg);
/* Strongly discourage the compiler from treating the above */
/* as a tail-call, since that would pop the register */
/* contents before we get a chance to look at them. */
GC_noop1((word)(&dummy));
}
#if defined(USE_GENERIC_PUSH_REGS)
void GC_generic_push_regs(cold_gc_frame)
ptr_t cold_gc_frame;
{
{
word dummy;
# ifdef HAVE_BUILTIN_UNWIND_INIT
/* This was suggested by Richard Henderson as the way to */
/* force callee-save registers and register windows onto */
/* the stack. */
__builtin_unwind_init();
# else /* !HAVE_BUILTIN_UNWIND_INIT */
/* Generic code */
/* The idea is due to Parag Patel at HP. */
/* We're not sure whether he would like */
/* to be he acknowledged for it or not. */
jmp_buf regs;
register word * i = (word *) regs;
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
/* Setjmp doesn't always clear all of the buffer. */
/* That tends to preserve garbage. Clear it. */
for (; (char *)i < lim; i++) {
*i = 0;
}
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
(void) setjmp(regs);
# else
(void) _setjmp(regs);
/* We don't want to mess with signals. According to */
/* SUSV3, setjmp() may or may not save signal mask. */
/* _setjmp won't, but is less portable. */
# endif
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|| defined(IA64)
/* On a register window machine, we need to save register */
/* contents on the stack for this to work. The setjmp */
/* is probably not needed on SPARC, since pointers are */
/* only stored in windowed or scratch registers. It is */
/* needed on IA64, since some non-windowed registers are */
/* preserved. */
{
GC_save_regs_ret_val = GC_save_regs_in_stack();
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
/* __builtin_ia64_flushrs(). The latter will be done */
/* implicitly by __builtin_unwind_init() for gcc3.0.1 */
/* and later. */
}
# endif
GC_push_current_stack(cold_gc_frame);
/* Strongly discourage the compiler from treating the above */
/* as a tail-call, since that would pop the register */
/* contents before we get a chance to look at them. */
GC_noop1((word)(&dummy));
}
GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);
}
#endif /* USE_GENERIC_PUSH_REGS */

View File

@ -368,8 +368,11 @@ ptr_t p;
ptr_t GC_approx_sp()
{
word dummy;
VOLATILE word dummy;
dummy = 42; /* Force stack to grow if necessary. Otherwise the */
/* later accesses might cause the kernel to think we're */
/* doing something wrong. */
# ifdef _MSC_VER
# pragma warning(disable:4172)
# endif

View File

@ -101,8 +101,28 @@ word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
sem_t GC_suspend_ack_sem;
void GC_suspend_handler_inner(ptr_t sig_arg);
#if defined(IA64) || defined(HP_PA)
extern void GC_with_callee_saves_pushed();
void GC_suspend_handler(int sig)
{
GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
}
#else
/* We believe that in all other cases the full context is already */
/* in the signal handler frame. */
void GC_suspend_handler(int sig)
{
GC_suspend_handler_inner((ptr_t)(word)sig);
}
#endif
void GC_suspend_handler_inner(ptr_t sig_arg)
{
int sig = (int)(word)sig_arg;
int dummy;
pthread_t my_thread = pthread_self();
GC_thread me;
@ -369,9 +389,11 @@ void GC_stop_world()
}
}
for (i = 0; i < n_live_threads; i++) {
if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
while (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
if (errno != EINTR) {
GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
ABORT("sem_wait for handler failed");
}
}
}
# ifdef PARALLEL_MARK