[Gc] Win32 thread support
hans.boehm at hp.com
Wed Mar 30 18:02:54 PST 2005
It still seems like allocating memory inside DllMain is risky?
Especially if it's done through GC_INTERNAL_MALLOC, which
can trigger a GC, etc. Even if not, do you run into problems
if you end up having to expand the heap, e.g. as a result of
a GC_scratch_alloc? And if you can't allocate memory there,
it seems that you're stuck with a fixed bound on the number of
I guess I'm still leaning toward option 2, especially given
the disclaimers associated with description of DllMain semantics.
(Not that Windows is the only OS with dynamic loader lock issues ...)
> -----Original Message-----
> From: Ben Hutchings [mailto:ben.hutchings at businesswebsoftware.com]
> Sent: Wednesday, March 30, 2005 8:07 AM
> To: Boehm, Hans
> Cc: gc at napali.hpl.hp.com
> Subject: Re: [Gc] Win32 thread support
> Boehm, Hans wrote:
> > I'm looking at the win32 threading code in the gc7 tree again.
> > Basically this code is really ugly due to DllMain semantics.
> > Unfortunately, the DllMain manual entry doesn't seem to
> have improved
> > as much as I had hoped. Are there any win32 experts who know
> > if the _DETACH calls are guaranteed to be made
> > in an ordinary thread context, and can thus lock?
> > It looks like there is no sane reason for that not to be the
> > case (unlike the _ATTACH calls). But the documentation
> > seems a bit contradictory on this particular point.
> Actually all calls to DllMain are made in a standard context. Here's
> what I wrote in my local code, which does use a lock during DllMain:
> * DllMain is called by the dynamic linker after the DLL is loaded,
> * when it is about to be unloaded, and whenever a thread begins or
> * exits (cleanly) in a process the DLL is loaded into.
> * The MSDN Library documentation says that this "should not attempt
> * to communicate with other threads or processes" but this is overly
> * conservative. The dynamic linker synchronises access to its state
> * with a mutex called the "loader lock" and holds this while loading
> * modules and whenever it calls DllMain. This means that any lock
> * acquired by DllMain other than during process attachment (when
> * there should be no other threads running) must be lower
> in the lock
> * hierarchy than the "loader lock", which in turn must be lower than
> * any locks that could be held by a thread when it loads a DLL. We
> * attempt to satisfy this requirement by locking only GC_threads_ml
> * during thread attachment and placing GC_threads_ml at the
> bottom of
> * the lock hierarchy.
> * Note also that during process attachment we should not call
> * functions in DLLs other than kernel32.dll since those DLLs may not
> * yet have been initialised. We break this rule if we call ABORT()
> * since that calls MessageBox from user32.dll. There is no obvious
> * solution to this.
> This is based on explanations in MS blogs, in particular
(search for "The OS Loader Lock").
> I can think of several options:
> 1) Default: Continue along the current path. If we can't lock in the
> _DETACH path in DllMain, this may be impractical. In any case, it
> looks more and more like a mess.
> 2) Split this into two different win32 thread support layers, one
> that relies on explicit interception of thread calls, and one
> the relies on the DllMain hack. The former could work a
> lot more like the pthreads version. This seems cleaner to
> me. It does mean that you need to compile differently for
> different thread registration methods.
> 3) Drop the DllMain support entirely. I suspect this is dubious
> because people are relying on it. But I'm not sure.
> I'm leaning towards (2). Opinions?
Our experience, which admittedly does not include testing on Win9x, is
that locking in DllMain is safe if done with great care. However if
this turns out not to be generally safe then I would favour (2).
More information about the Gc