Hi!

I found that with GCC's '-fthreadsafe-statics' implementation (..., which
is enabled by default) instrumented as follows:

    --- libstdc++-v3/libsupc++/guard.cc
    +++ libstdc++-v3/libsupc++/guard.cc
    @@ -271,6 +273,7 @@ namespace __cxxabiv1
       extern "C"
       int __cxa_guard_acquire (__guard *g)
       {
    +    asm("int3");
     #ifdef __GTHREADS
         // If the target can reorder loads, we need to insert a read memory
         // barrier so that accesses to the guarded variable happen after the

..., there is only one single libgomp C++ test case where this triggers;
'libgomp.c++/taskloop-6.C':

    Thread 1 "a.out" received signal SIGTRAP, Trace/breakpoint trap.
    __cxxabiv1::__cxa_guard_acquire (g=0x60b228 <guard variable for 
f17<121>(J<int>)::i>) at [...]/source-gcc/libstdc++-v3/libsupc++/guard.cc:281
    281         if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
    (gdb) bt
    #0  __cxxabiv1::__cxa_guard_acquire (g=0x60b228 <guard variable for 
f17<121>(J<int>)::i>) at [...]/source-gcc/libstdc++-v3/libsupc++/guard.cc:281
    #1  0x0000000000404772 in f17<121> (j=...) at 
source-gcc/libgomp/testsuite/libgomp.c++/taskloop-6.C:300
    #2  0x0000000000401e11 in main () at 
source-gcc/libgomp/testsuite/libgomp.c++/taskloop-6.C:411

That test case however isn't per se testing behavior of a C++ static
local variable vs. OpenMP.

OK to push the attached "Add 'libgomp.c++/static-local-variable-1.C'"?
(Also, I'm happy to extend the test case to verify any additional
features you think are userful to be tested there.)

(With '-fno-threadsafe-statics', this fails, as expected.)


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
>From d3140a1b4a649c5acb3735ef7fd04a4ebffe5e9a Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <tho...@codesourcery.com>
Date: Fri, 17 Nov 2023 16:06:25 +0100
Subject: [PATCH] Add 'libgomp.c++/static-local-variable-1.C'

A debug run may look as follows:

    int main()
    void f()
    S::S()
    void f()
    S::S()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()
    void f()/
    void f()/
    void f()/
      cSC = 1
      cf = 12
    int main()/
    S::~S()
    S::~S()/

	libgomp/
	* testsuite/libgomp.c++/static-local-variable-1.C: New.
---
 .../libgomp.c++/static-local-variable-1.C     | 95 +++++++++++++++++++
 1 file changed, 95 insertions(+)
 create mode 100644 libgomp/testsuite/libgomp.c++/static-local-variable-1.C

diff --git a/libgomp/testsuite/libgomp.c++/static-local-variable-1.C b/libgomp/testsuite/libgomp.c++/static-local-variable-1.C
new file mode 100644
index 00000000000..3169ba77d8d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/static-local-variable-1.C
@@ -0,0 +1,95 @@
+// Test basic behavior of a C++ static local variable vs. OpenMP.
+
+#include <omp.h>
+#include <unistd.h>
+
+#define DEBUG_PRINTF //__builtin_printf
+
+static int state;
+
+static int cSC, cSD, cf;
+
+struct S
+{
+  S()
+  {
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+    int c;
+#pragma omp atomic capture
+    c = ++cSC;
+    if (c != 1)
+      __builtin_abort();
+
+    if (state++ != 1)
+      __builtin_abort();
+
+    DEBUG_PRINTF("%s/\n", __PRETTY_FUNCTION__);
+  }
+
+  ~S()
+  {
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+    int c;
+#pragma omp atomic capture
+    c = ++cSD;
+    if (c != 1)
+      __builtin_abort();
+
+    if (state++ != 3)
+      __builtin_abort();
+
+    DEBUG_PRINTF("%s/\n", __PRETTY_FUNCTION__);
+    // Exit '0', now that we've verified all is OK.
+    _exit(0);
+  }
+};
+
+static void f()
+{
+  DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+#pragma omp atomic
+  ++cf;
+
+  // <https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables>
+  static S s;
+
+  DEBUG_PRINTF("%s/\n", __PRETTY_FUNCTION__);
+}
+
+int main()
+{
+  DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+  if (state++ != 0)
+    __builtin_abort();
+
+  int nthreads;
+
+#pragma omp parallel
+  {
+#pragma omp master
+    {
+      nthreads = omp_get_num_threads ();
+    }
+
+    f();
+  }
+
+  DEBUG_PRINTF("  cSC = %d\n", cSC);
+  DEBUG_PRINTF("  cf = %d\n", cf);
+  if (cSC != 1)
+    __builtin_abort();
+  if (cf != nthreads)
+    __builtin_abort();
+
+  if (state++ != 2)
+    __builtin_abort();
+
+  DEBUG_PRINTF("%s/\n", __PRETTY_FUNCTION__);
+
+  // See '_exit(0);' elsewhere.
+  return 1;
+}
-- 
2.34.1

Reply via email to