[Gc] Problems with GC_INIT and GC_WIN32_THREADS under mingw
Fri, 8 Aug 2003 17:07:41 -0700
> -----Original Message-----
> From: Stewart Greenhill [mailto:firstname.lastname@example.org]
> I'm trying to make a threaded GC for Win32 using GNU mingw32
> (gcc 3.2).
> It looks like the documentation is rather old, and I've had to
> experiment quite a bit to get it working.
> For the moment, I'm building a statically linked application. I added
> -DGC_WIN32_THREADS to the CFLAGS for the library and client builds.
> Problem #1.
> In win32_threads.c the compiler complains about the redeclaration of
> GC_CreateThread, so I changed:
> HANDLE WINAPI GC_CreateThread(
> GCAPI HANDLE GC_CreateThread(
> WIth that fix, it will compile and link, and gctest runs OK.
Thanks. That was recently reported on the gcj mailing list and fixed in my version.
> Problem #2.
> My application linked to the library crashes in
> GC_REGISTER_DISPLACEMENT. Eventually, I traced this down to LOCK()
> which is defined to EnterCriticalSection which is operating on an
> uninitialised Win32 CRITICALSECTION variable. It looks like this is
> supposed to be initialised in GC_init. However, the application calls
> GC_INIT and this is not correctly being redirected to GC_init in gc.h.
> I guess there are a number of workarounds possible here:
> - have the application call GC_init rather than GC_INIT
> - adjust gc.h to redirect GC_INIT to GC_init
> - explore other options for LOCK() that don't require initialisation
> My questions:
> Assuming gcc for Win32, are critical sections the preferred
> implementation for LOCK()?
> Under what circumstances should GC_init be called? It seems that in
> most cases, the GC can be used without initialisation, except in this
> kind of situation. I guess this is probably the place where
> things need
> to be fixed.
The current convention is supposed to be:
1) GC_init() is called to explicitly initialize the collector. This is documented to be needed only if thread-local allocation is used. Otherwise this can be and is done with minimal overhead during the first allocation.
2) GC_INIT() is an ugly workaround for platforms that insist you do something from the main program as opposed to a dynamic libarary, typically because a linker-defined symbol like &end or &etext has a different value when seen from a dynamic library. If you need to support one or more of these platforms, you need to invoke this FROM THE MAIN PROGRAM.
Looking at this now, I think the documentation for GC_init() is wrong. With win32 threads, it needs to be called explicitly. I just changed the comment. I also defined GC_INIT() to do GC_init() for GC_WIN32_THREADS.
It would probably be better to build a spin-yield-sleep lock out of atomic exchanges, analogously to the one implemented in pthread_support.c. Locks that can't be statically initialized are a pain, and it's probably best just to avoid them.