gallivm: handle llvm 16 atexit ordering problems.

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 b3cfec2fd8)
This commit is contained in:
Dave Airlie
2024-01-04 06:17:50 +10:00
committed by Eric Engestrom
parent 1c4c1c8431
commit 548cc0dd8c
2 changed files with 35 additions and 1 deletions

View File

@@ -364,7 +364,7 @@
"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

View 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
@@ -100,6 +101,8 @@
#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();
}