[compiler-rt] [AIX][PGO] Handle atexit functions when dlclose'ing shared libraries (PR #102940)
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 27 14:59:49 PDT 2024
================
@@ -373,3 +373,72 @@ COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
return 0;
#endif
}
+
+#ifdef _AIX
+typedef struct fn_node {
+ AtExit_Fn_ptr func;
+ struct fn_node *next;
+} fn_node;
+typedef struct {
+ fn_node *top;
+} fn_stack;
+
+static void fn_stack_push(fn_stack *, AtExit_Fn_ptr);
+static AtExit_Fn_ptr fn_stack_pop(fn_stack *);
+/* return 1 if stack is empty, 0 otherwise */
+static int fn_stack_is_empty(fn_stack *);
+
+static fn_stack AtExit_stack = {0};
+#define ATEXIT_STACK (&AtExit_stack)
+
+/* On AIX, atexit() functions registered by a shared library do not get called
+ * when the library is dlclose'd, causing a crash when they are eventually
+ * called at main program exit. However, a destructor does get called. So we
+ * collect all atexit functions registered by profile-rt and at program
+ * termination time (normal exit, shared library unload, or dlclose) we walk
+ * the list and execute any function that is still sitting in the atexit system
+ * queue.
+ */
+__attribute__((__destructor__)) static void cleanup() {
+ while (!fn_stack_is_empty(ATEXIT_STACK)) {
+ AtExit_Fn_ptr func = fn_stack_pop(ATEXIT_STACK);
+ if (func && unatexit(func) == 0)
+ func();
+ }
+}
+
+static void fn_stack_push(fn_stack *st, AtExit_Fn_ptr func) {
+ fn_node *old_top, *n = (fn_node *)malloc(sizeof(fn_node));
+ n->func = func;
+
+ while (1) {
+ old_top = st->top;
----------------
vitalybuka wrote:
I guess it's fine, we don't use relaxed stuff here, and CMPXCHG will fix tearing.
https://github.com/llvm/llvm-project/pull/102940
More information about the llvm-commits
mailing list