[Gc] Extend win32 static root handling to Cygwin targets.

Dave Korn dave.korn.cygwin at googlemail.com
Fri Mar 19 07:34:43 PST 2010


    Hi Hans and list,

  Hans, you may remember giving me some help with GCC PR42811 on the libjava
list a month or so ago.  This patch follows on from that investigation; Andrew
Haley asked me to run the GC changes past you when he reviewed it, so I've
up-ported it to your current CVS HEAD.

  The problem arising in the GCC PR is that none of the static data/bss areas
of the main executable get registered with the GC.  The libjava DLL registers
its own data and bss, because it is the one that calls GC_init; but if it
returns a pointer to an allocated object to the main executable (that it does
not also retain a copy of in its own registered root areas), that pointer is
then invisible to GC and it thinks the object is unreferenced and may release
it and reallocate the space.  I solve this by adding the win32 dynamic
registration code into the mix(*), which should thoroughly take care of
detecting all program and library data areas and malloc heaps.

  The attached patch switches the Cygwin target to use the same dynamic
registration used on the native win32 targets.  I've built it on cygwin and
verified that the testsuite shows no regressions.  I've also created a
testcase that illustrates the problem, loosely based on the trace test.  It
FAILs with current HEAD and PASSes after applying the cygwin-mem-registration
diff.

bdwgc/ChangeLog:

<date/name/email line elided for despam - see email headers for details>

	* dyn_load.c (GC_get_next_stack): Define for Cygwin as well as
	other win32 targets.
	(GC_cond_add_roots): Likewise.
	(GC_register_main_static_data): Likewise.
	(GC_wnt): Define to constant true.
	(GC_register_dynamic_libraries): Define for Cygwin as well
	as other win32 targets.
	* mark_rts.c (rt_hash): Don't define for Cygwin, as on other win32.
	(GC_roots_present): Likewise.
	(add_roots_to_index): Likewise.
	(GC_add_roots_inner): Handle on Cygwin as for other win32 targets.
	(GC_clear_roots): Likewise.
	(GC_rebuild_root_index): Don't declare on Cygwin, as other win32.
	(GC_remove_tmp_roots): Do declare on Cygwin as on other win32.
	(GC_remove_roots): Don't declare on Cygwin as on other win32.
	(GC_remove_roots_inner): Likewise.
	(GC_is_tmp_root): Do declare on Cygwin when !NO_DEBUGGING, as on
	other win32 targets.
	(GC_cond_register_dynamic_libraries): Handle on Cygwin as for other
	win32 targets.
	* os_dep.c (GC_setpagesize): Handle on Cygwin as on other win32.
	(GC_get_main_stack_base): Don't declare on Cygwin, as other win32.
	(GC_no_win32_dlls): Define to constant false on Cygwin.
	(GC_sysinfo): Declare on Cygwin, as other win32.
	(GLOBAL_ALLOC_TEST): Likewise.
	(GC_win32_get_mem): Declare on Cygwin, as on other win32, but call
	GC_unix_get_mem instead of GlobalAlloc.
	(GC_win32_free_heap): Declare on Cygwin, as on other win32, but call
	free instead of GlobalFree.
	* ptr_chck.c (GC_is_visible): Register dynamic libraries on Cygwin
	as on other win32 platforms.
	* win32_threads.c (GC_get_next_stack): Define on Cygwin as well as
	for dynamic loading targets.
	* include/private/gc_priv.h (GC_INNER): Don't try to use visibility
	on Cygwin which does not support it.
	(struct roots): Don't declare r_next member on Cygwin as on other
	windows hosts.
	(LOG_RT_SIZE): Don't define likewise.
	(RT_SIZE): Likewise.
	(struct _GC_arrays): Do declare _heap_bases[] member and don't
	declare _root_index likewise.
	(GC_heap_bases): Do define likewise.
	(struct _SYSTEM_INFO): Do forward-declare likewise.
	(GC_sysinfo): Do declare extern likewise.
	* include/private/gcconfig.h (GC_win32_get_mem): Do prototype on
	Cygwin as other win32 platforms.
	(GET_MEM): Do define likewise.

	* tests/staticrootstest.c: New file.
	* tests/staticrootslib.c: Likewise.
	* tests/tests.am: Build them into a new test executable and
	supporting shared library.

  There is one slight hiccup that I'm not sure what to do about: I couldn't
figure out how to get libtool to build a shared-but-not-installed library,
because libtool assumes that any library you aren't planning to install will
only be needed as a convenience (i.e. static archive) library.  There might be
a way round that, or you might want not to check in the testcase but just use
it to verify the problem I've identified and fixed in the patch.

  Any comments or advice?  Anything I should bear in mind when implementing
this in the slightly-old version of the GC in libjava?

    cheers,
      DaveK

-- 
(*) - Although it is win32-ish rather than posix-ish, it relies only on using
VirtualQuery to determine properties of allocated memory ranges, which is a
perfectly safe thing to do under cygwin.  We still use posix interfaces for
malloc/free/pthread stuff.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: cygwin-mem-registration.diff
Type: text/x-c
Size: 13992 bytes
Desc: not available
Url : http://napali.hpl.hp.com/pipermail/gc/attachments/20100319/51dd5b83/cygwin-mem-registration.bin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test-with-lib-and-staticroots.diff
Type: text/x-c
Size: 982 bytes
Desc: not available
Url : http://napali.hpl.hp.com/pipermail/gc/attachments/20100319/51dd5b83/test-with-lib-and-staticroots.bin
-------------- next part --------------
#include <stdio.h>

#ifndef GC_DEBUG
# define GC_DEBUG
#endif

#include "gc.h"

struct treenode {
    struct treenode *x;
    struct treenode *y;
} * root[10];

struct treenode * libsrl_mktree(int i)
{
  struct treenode * r = GC_MALLOC(sizeof(struct treenode));
  if (0 == i) return 0;
  if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode));
  r -> x = libsrl_mktree(i-1);
  r -> y = libsrl_mktree(i-1);
  return r;
}

void * libsrl_init(void)
{
  GC_INIT();
  return GC_MALLOC(sizeof(struct treenode));
}
-------------- next part --------------
#include <stdio.h>

#ifndef GC_DEBUG
# define GC_DEBUG
#endif

#include "gc.h"
#include "gc_backptr.h"

struct treenode {
    struct treenode *x;
    struct treenode *y;
} * root[10];

static char *staticroot = 0;

extern struct treenode * libsrl_mktree(int i);
extern void * libsrl_init(void);

/*struct treenode * mktree(int i) {
  struct treenode * r = GC_MALLOC(sizeof(struct treenode));
  if (0 == i) return 0;
  if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode));
  r -> x = mktree(i-1);
  r -> y = mktree(i-1);
  return r;
}*/

int main(void)
{
  int i;
  /*GC_INIT();
  staticroot = GC_MALLOC(sizeof(struct treenode));*/
  staticroot = libsrl_init();
  memset(staticroot, 0x42, sizeof(struct treenode));
  GC_gcollect();
  for (i = 0; i < 10; ++i) {
    root[i] = libsrl_mktree(12);
    GC_gcollect();
  }
  for (i = 0; i < sizeof(struct treenode); ++i) {
    if (staticroot[i] != 0x42)
      return -1;
  }
  for (i = 0; i < 10; ++i) {
    root[i] = libsrl_mktree(12);
    GC_gcollect();
  }
  for (i = 0; i < sizeof(struct treenode); ++i) {
    if (staticroot[i] != 0x42)
      return -1;
  }
  return 0;
}


More information about the Gc mailing list