gcc4 and local statics

Brian Dessent brian@dessent.net
Wed May 18 21:39:00 GMT 2005

Christopher Faylor wrote:

> It seems like static is being used like this in 28 different cases.  It
> shouldn't be a big problem to audit the usage here and see if we really
> need a gcc4-only option, with all of the headaches that will introduce
> to the Makefile.
> In the case of granularity, I think I'd actually opt for just making it
> an automatic variable rather than a static variable.  There doesn't seem
> to be any reason to ever initialize granularity unless mmap64 is used,
> and the call is pretty cheap.  I'm not even sure how granularity is
> supposed to be initialized when it is being set to the value of a
> function.  Is it only supposed to call the function once and once-only?
> If so, that would imply logic to avoid calling getshmlba more than once
> which almost negates the overhead of just calling getshmlba every time.

If you look at the patch in the PR, what it's actually doing is emitting
the following (pseudocode) for the static local object:

   static <type> guard;
   if (!guard.first_byte) {
     if (__cxa_guard_acquire (&guard)) {
       bool flag = false;
       try {
         // Do initialization.
         flag = true; __cxa_guard_release (&guard);
         // Register variable for destruction at end of program.
       } catch {
         if (!flag) __cxa_guard_abort (&guard);

It allocates this guard variable which itself is static and starts out
at 0, and iff initialization was successful it sets guard to 1 so that
all of this is skipped next time.  In this case granularity's
initializer is just calling getshmlba(), and this will only happen once;
however 'guard' will be checked each time.

If the initialization is cheap then it's not really saving much by
bothering with a static variable, then you're right that we should just
use an automatic variable.

However, the case for a static variable in file scope is very
different.  In that case the compiler knows that it can do the
initialization of the variable before any user code begins executing, so
it doesn't have to bother with the thread safety.  This is why moving
the function to file scope fixes the problem.  It also means that in
this case it's like C in that the function call to initialize it is only
done once and there is zero penalty later on because it is known that
it's been initialized by the time user code begins executing.  If there
are any static local objects that have an expensive initialization or
constructor, then we should move them to file scope.

Incidently, enabling -fno-threadsafe-statics for all cygwin C++ modules
eliminates that problem I was having with ilockincr() being passed NULL
and causing segfault.  That makes perfect sence since the argument to it
must have been a local static object that was supposed to have been
initialized but was not.  That eliminated the ugly need to compile with
-O0.  So, count that as one of the two dozen cases we'll have to review.

I'm still seeing the cygheap_user::init problem, but it's looking very
probable that it's just another case of a static object that was
supposed to be initialized but is actually 0.


More information about the Cygwin-developers mailing list