I have a simple sample code which illustrates the issue. Basically, if multiple threads invoke a function which has local static object, the ctor and dtor are called multiple times on the same object in non reentrant manner until object is fully constructed. Here is a sample program which illustrates the issue #include <stdio.h> #include <unistd.h> #include <pthread.h> volatile int i; class A { public: int i; A(int i) { this->i = i; sleep(1); printf("I am in A ctor %d this:%p\n", i, this); } ~A() { printf("A dtor %d this:%p\n", i, this); } }; extern "C" void *foo(void *) { printf("before static ctor in foo\n"); static A a(i++); printf("in foo %p a(i) %d\n", &a, a.i); return NULL; } main() { printf("I am in main\n"); pthread_t tid; pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); pthread_create(&tid,NULL, foo, NULL); sleep(3); foo(NULL); } The output of this program is I am in main before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo before static ctor in foo I am in A ctor 1 this:210b0 I am in A ctor 3 this:210b0 in foo 210b0 a(i) 10 in foo 210b0 a(i) 10 I am in A ctor 4 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 6 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 8 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 9 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 2 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 5 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 0 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 10 this:210b0 in foo 210b0 a(i) 10 I am in A ctor 7 this:210b0 in foo 210b0 a(i) 10 before static ctor in foo in foo 210b0 a(i) 10 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0 A dtor 10 this:210b0
Basically allocation of static variables in functions are not done thread safe, I do not think there is any way that GCC will be able to do this efficiently, I would not use local static variables if you are going to use threads.
dont we follow c++ abi specification ? http://www.armdevzone.com/EABI/GVariables.txt
*** Bug 13487 has been marked as a duplicate of this bug. ***
Andrew wrote: > Basically allocation of static variables in functions are not done thread > safe, I do not think there is any way that GCC will be able to do this > efficiently, I would not use local static variables if you are > going to use threads. Actually, it can be quite efficient on some platforms. Also, since this is a one-time thing, efficiency is not that big a deal. This posting from Zack Weinberg indicates pretty much how it could be done in a way that more-or-less works as efficiently as it does without thread safety. http://gcc.gnu.org/ml/gcc/2002-08/msg00284.html
It's not quite a one-time thing, of course: every time you run over a static variable, you have to check whether it has already been initialized. If this check has to be guarded by a lock, it gets vastly more expensive than just checking for zero-or-one. Nevertheless, I believe that this should eventually be implemented. W.
> It's not quite a one-time thing, of course: every time you run over > a static variable, you have to check whether it has already been > initialized. I suspect that this is done with the current gcc. > If this check has to be guarded by a lock, it gets vastly > more expensive than just checking for zero-or-one. I don't understand why you think so. Zack's suggestion (and this concept is also used in lots of other code) is this: if (guard) { if (__cxa_guard_acquire (&guard)) { // construct variable. __cxa_guard_release (&guard) } } The first conditional is not thread safe, however, once the object is correctly initialized the first conditional will be false and hence it will render code that is practically the same speed as non thread-safe code (code size will be larger, obviously!).
The cost of static local variables that are objects is actually quite expensive in general because it requires testing whether or not the object has been constructed. This is has nothing to do with thread safety. Using the double-checked locking as is indicated allows for thread-safe initialization that is no more costly than normal initialization with the exception of having to acquire a mutex. The code as indicated is not quite correct though, because initialization requires a global mutex to avoid a deadlock. So initialization needs to be done like this: static volatile bool guard=true; if (guard) { if (__cxa_guard_acquire (&global_guard)) { if (guard) { // construct variable. guard = false; } __cxa_guard_release (&global_guard) } } Also, the guard boolean needs to be volatile.
Zack's code may have been missing the details but the code below is still perfectly valid. if (guard) { if (__cxa_guard_acquire (&guard)) { // construct variable. __cxa_guard_release (&guard) } } If you take these definitions for aquire/release functions. bool __cxa_guard_acquire ( volatile bool * pguard ) { __lock_reentrant_mutex( & global_mutex ); if ( ! * pguard ) { __unlock_reentrant_mutex( &global_mutex ); return false; } return true; } void __cxa_guard_release (bool * guard) { * guard = false; __unlock_reentrant_mutex( &global_mutex ); } I'd imagine that the sense of the guard is more like "is initialized" so the code below is more like somthing that could be plugged in. if (! is_initialized) { if (__cxa_guard_acquire(is_initialized)) { // construct variable. __cxa_guard_release(is_initialized) } } And these would be the corresponding aquire/release functions. bool __cxa_guard_acquire ( volatile bool & is_initialized ) { __lock_reentrant_mutex( & global_mutex ); if ( ! is_initialized ) { __unlock_reentrant_mutex( &global_mutex ); return true; } return false; } void __cxa_guard_release( volatile bool & is_initialized ) { is_initialized = true; __unlock_reentrant_mutex( &global_mutex ); }
Subject: Bug 13684 CVSROOT: /cvs/gcc Module name: gcc Changes by: jason@gcc.gnu.org 2004-08-28 02:33:54 Modified files: gcc : ChangeLog c-common.c c-common.h c-opts.c c.opt gimplify.c gthr-dce.h gthr.h gthr-posix.h gthr-single.h gthr-solaris.h gthr-vxworks.h gthr-win32.h tsystem.h gcc/config/i386: gthr-win32.c gcc/cp : ChangeLog cp-tree.h decl.c decl2.c tree.c gcc/doc : invoke.texi libstdc++-v3 : ChangeLog libstdc++-v3/libsupc++: guard.cc Log message: PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.5120&r2=2.5121 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-common.c.diff?cvsroot=gcc&r1=1.561&r2=1.562 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-common.h.diff?cvsroot=gcc&r1=1.258&r2=1.259 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-opts.c.diff?cvsroot=gcc&r1=1.124&r2=1.125 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c.opt.diff?cvsroot=gcc&r1=1.32&r2=1.33 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gimplify.c.diff?cvsroot=gcc&r1=2.67&r2=2.68 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-dce.h.diff?cvsroot=gcc&r1=1.20&r2=1.21 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr.h.diff?cvsroot=gcc&r1=1.15&r2=1.16 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-posix.h.diff?cvsroot=gcc&r1=1.28&r2=1.29 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-single.h.diff?cvsroot=gcc&r1=1.12&r2=1.13 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-solaris.h.diff?cvsroot=gcc&r1=1.15&r2=1.16 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-vxworks.h.diff?cvsroot=gcc&r1=1.12&r2=1.13 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-win32.h.diff?cvsroot=gcc&r1=1.23&r2=1.24 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tsystem.h.diff?cvsroot=gcc&r1=1.11&r2=1.12 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/gthr-win32.c.diff?cvsroot=gcc&r1=1.7&r2=1.8 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4313&r2=1.4314 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&r1=1.1035&r2=1.1036 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl.c.diff?cvsroot=gcc&r1=1.1281&r2=1.1282 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl2.c.diff?cvsroot=gcc&r1=1.737&r2=1.738 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/tree.c.diff?cvsroot=gcc&r1=1.406&r2=1.407 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/doc/invoke.texi.diff?cvsroot=gcc&r1=1.516&r2=1.517 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.2644&r2=1.2645 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/guard.cc.diff?cvsroot=gcc&r1=1.4&r2=1.5
Fixed.
(In reply to comment #10) > Fixed. Very cool. Much appreciated.
It looks to me that the solution applies the Double-Checked Locking Pattern, and could be unsafe on some multi-processor platforms, most notably Alpha and IA-64.
Subject: Bug 13684 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-rhl-branch Changes by: jakub@gcc.gnu.org 2004-09-01 16:58:05 Modified files: gcc : ChangeLog c-common.c c-common.h c-opts.c c.opt gthr-dce.h gthr-posix.h gthr-single.h gthr-solaris.h gthr-vxworks.h gthr.h tsystem.h gcc/cp : ChangeLog cp-tree.h decl.c decl2.c tree.c gcc/doc : invoke.texi libstdc++-v3 : ChangeLog libstdc++-v3/libsupc++: guard.cc Log message: 2004-08-27 Jason Merrill <jason@redhat.com> PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=2.2326.2.399.2.36&r2=2.2326.2.399.2.37 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-common.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.476.4.6.2.3&r2=1.476.4.6.2.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-common.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.216.2.4&r2=1.216.2.4.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-opts.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.96.4.7.2.1&r2=1.96.4.7.2.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c.opt.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.17.12.2.2.1&r2=1.17.12.2.2.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-dce.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.20&r2=1.20.28.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-posix.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.27&r2=1.27.18.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-single.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.12&r2=1.12.38.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-solaris.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.15&r2=1.15.28.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr-vxworks.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.12&r2=1.12.28.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gthr.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.13&r2=1.13.28.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tsystem.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.11&r2=1.11.14.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.3892.2.99.2.10&r2=1.3892.2.99.2.11 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.946.4.11.2.5&r2=1.946.4.11.2.6 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.1174.2.19.2.6&r2=1.1174.2.19.2.7 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl2.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.695.4.7.2.3&r2=1.695.4.7.2.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/tree.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.360.4.5.2.3&r2=1.360.4.5.2.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/doc/invoke.texi.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.390.2.24.2.6&r2=1.390.2.24.2.7 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.2224.2.77.2.8&r2=1.2224.2.77.2.9 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/guard.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.1&r2=1.1.56.1
Subject: Re: local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads On 31 Aug 2004 06:41:13 -0000, "adah at netstd dot com" <gcc-bugzilla@gcc.gnu.org> wrote: > It looks to me that the solution applies the Double-Checked Locking Pattern, > and could be unsafe on some multi-processor platforms, most notably Alpha and > IA-64. Hmm, indeed. As I understand it from some googling, particularly this thread: http://www.google.com/groups?threadm=6kuldj$4sk%40bmtlh10.bnr.ca the problem is that modern architectures such as the ones you mention can reorder stores and loads so that another processor could see the guard variable set, but the controlled variable not yet fully initialized. The cheapest workaround is to add memory barriers in the initialization path if the architecture reorders stores (SPARC also does this) and in the already-initialized path if it reorders loads. Unfortunately, pthreads (for instance) don't have a portable way of forcing a memory barrier other than with a mutex. I suppose the simplest fix is just to remove the check in the compiler-generated code, but having all calls to functions with initialized static locals go through the same mutex seems rather unfortunate. Hmm. Jason
I myself have had headaches about this problem (unsafe DLCP) too. Indeed, I do not have problems with DLCP, since I have access only to IA-32 platforms, but I really like to make my code more portable. Currently there is no known way to make memory barriers portable. So I guess it might be a good idea that GCC provide built-in functions to do the job. On IA-32 platforms it is a just a null operation, but on other systems it might really do significant stuff.
This is not a GCC bug and should not be fixed in GCC. The bug is in the test code which accesses an object that is shared by multiple threads without proper mutexes. Period. End of story. The correct fix is to acquire a mutex before calling a function that might accessed shared data (and constructing a static object counts). This should be common sense, and it's surprising to me that it is not. Anyone can create code that fails if you call functions that manipulate shared data without holding any mutexes. DS
> This is not a GCC bug and should not be fixed in GCC. The bug is in the test > code which accesses an object that is shared by multiple threads without proper > mutexes. Period. End of story. This approach makes it very difficult to use library code that would otherwise be thread safe. Since there is no standard C++ API for threading, resolving this issue would otherwise cause a significant dependantcy on external libraries, not to mention the potential bugs that arise from ad-hoc fixes. (like deadlocks). The only way to truly resolve this is to ensure proper functioning code is to have the compiler generate code that adheres to the letter of the C++ standard, even in a multi-threaded environment. Why do you object to havingthe compiler generate MT safe code ?
I am not David but let me try to name some possible objections. * The current code is unsafe on some architectures (DLCP is unsafe) * For cross-compiler code, users SHOULD have already locked a mutex before entering the function that might have race conditions: so there will be unnecessary overhead * If users do not use a mutex, if might well be the case that the specific function will be called by only one thread; or that the function has been called at least once in the initialization (one thread only) code; and the "fix" creates unnecessary overhead again Granted, there is no standard C++ API for threading. But when users write a multi-threaded program, they have already begun to use non-standard threading APIs. They might well use the APIs to protect what this fix tries to do.
I want to emphasize here again one principle of C and C++: Trust the programmers, and allow them to do low-level tunings for performance. Or what is the purpose of C++ (when compared with "high-level" languages like Python)? This "fix" rid the programmers of their right to choose the way they want. Unless the future C++ standard demands protection in such cases, I do not think the compiler-provided mechanism a good idea.
(In reply to comment #19) > I want to emphasize here again one principle of C and C++: Trust the > programmers, and allow them to do low-level tunings for performance. Or what is > the purpose of C++ (when compared with "high-level" languages like Python)? > This "fix" rid the programmers of their right to choose the way they want. > > Unless the future C++ standard demands protection in such cases, I do not think > the compiler-provided mechanism a good idea. I would agree with you. Btw, what is the approach adopted in case the app. is a single threaded one? Are the locks still taken in this case? Also, if it is an mt-app. but the programmer is sure that that particula function will NOT be reentrant, why should he pay the penalty of a lock or/and a check every time the function is called? Stroustrup continuously emphasised that C++ was designed to be as fast if not faster than C in most respects, and I guess that's why C++ is gaining popularity. If it were to use the java approach then it would be just another bloat-language.... -Dhruv.
Subject: Re: local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads DCL with explicit memory barriers is safe. That's what I'm using. But don't take my word for it, see the "DCL is Broken" Declaration: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html Scroll down to "Making it work with explicit memory barriers". The fast path does not use a lock. There, the only overhead compared to the old code is a function call and a read/read hoist memory barrier on targets where the memory barrier is necessary; targets that do not reorder loads have no overhead at all. It is impossible for users to implement this protection as efficiently as the compiler can. The C++ committee is working on improving thread support in C++; when this particular topic came up the other day, there was general support for having the compiler guarantee that the initialization be threadsafe, though possibly with a keyword to either enable or disable this guarantee.
Function calls, memory barriers, (and "lock" operations?) are all overheads. I would like that * GCC provide extensions so that GCC users can use memory barriers and threading calls in a platform-independent way, and * - Revert the patch, or at least - Provide a command-line option (or pragma/attribute?) to disable/enable static initialization protection. With the former, users can implement the protection as efficiently as the compiler can (correct me if I am wrong). With the latter, the new GCC is still usable in some applications that require performance no less than C. I am really worried that with the improvements introduced to GCC beginning with GCC 3, some of my applications are running slower and slower, though some problems only show up on Windows.
Subject: Re: local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads On 18 Apr 2005 09:07:00 -0000, "adah at netstd dot com" <gcc-bugzilla@gcc.gnu.org> wrote: > I would like that > > * GCC provide extensions so that GCC users can use memory barriers and > threading calls in a platform-independent way, and I'd like that too. > - Provide a command-line option (or pragma/attribute?) to disable/enable > static initialization protection. Already there: -fno-threadsafe-statics. Jason
*** Bug 260998 has been marked as a duplicate of this bug. *** Seen from the domain http://volichat.com Page where seen: http://volichat.com/adult-chat-rooms Marked for reference. Resolved as fixed @bugzilla.