[Gc] RE: using threads that were not created by GC_pthread_create()

Boehm, Hans hans_boehm@hp.com
Thu, 24 Jul 2003 14:37:29 -0700


> From: eric lindvall [mailto:eric@5stops.com]
> 
> I am looking to embed mono (as a module) in an application 
> that makes use of 
> pthreads for which I do not have the source.
> 
> I've been told that if I use pthreads, I need to include gc.h 
> to override
> the standard pthread_create() which calls the boehm hooks 
> that are needed 
> for the GC to work.
That is currently correct.  You may be able to avoid it if threads started with
pthread_create don't ever do anything with the garbage-collected heap.  Otherwise
GC_pthread_create is needed to force thread startup in the GC, which then invokes
the real thread start function.   The fake startup function basically adds the
following to a table:

1) The thread id, so that it can be stopped during GC.
2) The cold stack end(s), so that the stack(s) can be scanned by the GC.

These updates should happen with proper collector synchronization, i.e. while
holding the GC lock.

If thread-local allocation is enabled (it should normally be for
multithreaded environments), it also initializes some thread-local tables for that.
> 
> Unfortunatly, because I am only writing a module for this 
> application, I
> cannot override the applications pthread_create(). Is there a 
> way that I
> can call something thit will do all of the GC setup stuff on 
> a thread that
> is already created (GC_thread_setup() or something similar)?
> 
> e.
I think it would be tricky to do that without cooperation of the thread itself.
You can certainly get the thread id, and you might be able to get the cold stack end,
depending on your platform.  But getting those in and out of the thread table without
introducing a race sounds quite tricky.  By the time you get a thread id into the table,
it may have been reused for another thread with a different stack.  The thread-local 
allocation code would probably also have to be restructured or turned off.

Even if the thread can cooperate, the code isn't currently structured to make that
easily possible.  But I wouldn't be at all opposed to fixing that.  (It would have
to cooperate to register itself, and to unregister itself on the way out.)

Depending on the definition of "module" and on your environment, another possible solution
sometimes is to play linker games to intercept pthread_create, e.g. to preload a library
that defines pthread_create,
and then uses dlopen and dlsym internally to call the pthread version.  (This is done by
the wrap.h header in http://www.hpl.hp.com/personal/Hans_Boehm/qprof/qprof-0.2.tar.gz ,
among other places.)  The collector will probably acquire built-in support for doing some
of this shortly, at least on linux.

Hans