Data races in BLAS static initialization
Submitted by Benoit Jacob
Assigned to Nobody
Link to original bugzilla bug (#1152)
Version: 3.3 (current stable)
Description
The blas/ implementation has several instances of this idiom:
int some_blas_func() {
static some_type some_static_data;
static bool init = false;
if(!init)
{
initialize(some_static_data);
init = true;
}
...
}
The problem is that such initialization code is not reentrant. This concretely leads to errors with thread-safety-checking tools such as Thread Sanitizer and Helgrind; I could share a self-contained testcase if needed, but I hope that the problem is obvious enough that we would agree that there is no need for it.
The question is, do you have a preferred way to address this issue?
What would you think of using this idiom:
struct SomeHelper {
some_type some_data;
SomeHelper() {
initialize(some_data);
}
};
int some_blas_func() {
static SomeHelper some_helper;
}
Indeed, this would have the following advantages:
- Compiles in plain C++98 without dependency.
- Guaranteed in C++11 mode to be thread-safe, according to http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11
- Though not guaranteed in the C++98 language, this seems to have been mandated by the C++ ABI and implemented in GCC since 2004:
https://gcc.gnu.org/ml/gcc-patches/2004-08/msg01598.html - GCC has nondefault -fno-threadsafe-statics, which (see GCC man page) further supports that GCC is guarding statics by default, and the man page refers to the ABI requirement...
- for MSVC, from some googling it seems like MSVC 2010 might NOT be safe but 2013 probably is:
http://herbsutter.com/2013/09/09/visual-studio-2013-rc-is-now-available/
In short, I'd be very surprised if this idiom were unsafe on any current compiler! (Does anyone care about Eigen/BLAS on MSVC 2010?)
Or, do you have any other preferred implementation strategy?