[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