gallivm: handle llvm 16 atexit ordering problems.
authorDave Airlie <airlied@redhat.com>
Wed, 3 Jan 2024 20:17:50 +0000 (06:17 +1000)
committerEric Engestrom <eric@engestrom.ch>
Thu, 4 Jan 2024 18:35:32 +0000 (18:35 +0000)
This is ported from amd ac_llvm_helper.cpp, thanks to Marek for the pointer.

This is needed to avoid crashes due to atexit ordering between some piglit
tests and mesa internals.

Cc: mesa-stable
Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26883>
(cherry picked from commit b3cfec2fd824a52023c92fd5928f4f5c1cb449a0)

.pick_status.json
src/gallium/auxiliary/gallivm/lp_bld_misc.cpp

index e5127e9..eb12e5e 100644 (file)
         "description": "gallivm: handle llvm 16 atexit ordering problems.",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": null,
         "notes": null
index e213f7e..a5e84d7 100644 (file)
@@ -62,6 +62,7 @@
 #include <llvm/Support/PrettyStackTrace.h>
 #include <llvm/ExecutionEngine/ObjectCache.h>
 #include <llvm/Support/TargetSelect.h>
+#include <llvm/CodeGen/SelectionDAGNodes.h>
 #if LLVM_VERSION_MAJOR >= 15
 #include <llvm/Support/MemoryBuffer.h>
 #endif
 #include "lp_bld_misc.h"
 #include "lp_bld_debug.h"
 
+static void lp_run_atexit_for_destructors(void);
+
 namespace {
 
 class LLVMEnsureMultithreaded {
@@ -147,6 +150,7 @@ static void init_native_targets()
       }
    }
 #endif
+   lp_run_atexit_for_destructors();
 }
 
 extern "C" void
@@ -623,3 +627,33 @@ lp_set_module_stack_alignment_override(LLVMModuleRef MRef, unsigned align)
    M->setOverrideStackAlignment(align);
 #endif
 }
+
+using namespace llvm;
+
+class GallivmRunAtExitForStaticDestructors : public SDNode
+{
+public:
+   /* getSDVTList (protected) calls getValueTypeList (private), which contains static variables. */
+   GallivmRunAtExitForStaticDestructors(): SDNode(0, 0, DebugLoc(), getSDVTList(MVT::Other))
+   {
+   }
+};
+
+static void
+lp_run_atexit_for_destructors(void)
+{
+   /* LLVM >= 16 registers static variable destructors on the first compile, which gcc
+    * implements by calling atexit there. Before that, u_queue registers its atexit
+    * handler to kill all threads. Since exit() runs atexit handlers in the reverse order,
+    * the LLVM destructors are called first while shader compiler threads may still be
+    * running, which crashes in LLVM in SelectionDAG.cpp.
+    *
+    * The solution is to run the code that declares the LLVM static variables first,
+    * so that atexit for LLVM is registered first and u_queue is registered after that,
+    * which ensures that all u_queue threads are terminated before LLVM destructors are
+    * called.
+    *
+    * This just executes the code that declares static variables.
+    */
+   GallivmRunAtExitForStaticDestructors();
+}