139d38d66Saaryanshukla //===-- Implementation header for exit_handler ------------------*- C++ -*-===// 239d38d66Saaryanshukla // 339d38d66Saaryanshukla // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 439d38d66Saaryanshukla // See https://llvm.org/LICENSE.txt for license information. 539d38d66Saaryanshukla // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 639d38d66Saaryanshukla // 739d38d66Saaryanshukla //===----------------------------------------------------------------------===// 839d38d66Saaryanshukla 939d38d66Saaryanshukla #ifndef LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H 1039d38d66Saaryanshukla #define LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H 1139d38d66Saaryanshukla 1239d38d66Saaryanshukla #include "src/__support/CPP/mutex.h" // lock_guard 1339d38d66Saaryanshukla #include "src/__support/blockstore.h" 1439d38d66Saaryanshukla #include "src/__support/common.h" 1539d38d66Saaryanshukla #include "src/__support/fixedvector.h" 165ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1739d38d66Saaryanshukla #include "src/__support/threads/mutex.h" 1839d38d66Saaryanshukla 195ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2039d38d66Saaryanshukla 2139d38d66Saaryanshukla using AtExitCallback = void(void *); 2239d38d66Saaryanshukla using StdCAtExitCallback = void(void); 2339d38d66Saaryanshukla constexpr size_t CALLBACK_LIST_SIZE_FOR_TESTS = 1024; 2439d38d66Saaryanshukla 2539d38d66Saaryanshukla struct AtExitUnit { 2639d38d66Saaryanshukla AtExitCallback *callback = nullptr; 2739d38d66Saaryanshukla void *payload = nullptr; 2839d38d66Saaryanshukla LIBC_INLINE constexpr AtExitUnit() = default; 2939d38d66Saaryanshukla LIBC_INLINE constexpr AtExitUnit(AtExitCallback *c, void *p) 3039d38d66Saaryanshukla : callback(c), payload(p) {} 3139d38d66Saaryanshukla }; 3239d38d66Saaryanshukla 3339d38d66Saaryanshukla #if defined(LIBC_TARGET_ARCH_IS_GPU) 3439d38d66Saaryanshukla using ExitCallbackList = FixedVector<AtExitUnit, 64>; 3539d38d66Saaryanshukla #elif defined(LIBC_COPT_PUBLIC_PACKAGING) 3639d38d66Saaryanshukla using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>; 3739d38d66Saaryanshukla #else 3839d38d66Saaryanshukla using ExitCallbackList = FixedVector<AtExitUnit, CALLBACK_LIST_SIZE_FOR_TESTS>; 3939d38d66Saaryanshukla #endif 4039d38d66Saaryanshukla 41aac3a2a2SJoseph Huber // This is handled by the 'atexit' implementation and shared by 'at_quick_exit'. 4239d38d66Saaryanshukla extern Mutex handler_list_mtx; 4339d38d66Saaryanshukla 44aac3a2a2SJoseph Huber LIBC_INLINE void stdc_at_exit_func(void *payload) { 45aac3a2a2SJoseph Huber reinterpret_cast<StdCAtExitCallback *>(payload)(); 46aac3a2a2SJoseph Huber } 4739d38d66Saaryanshukla 48aac3a2a2SJoseph Huber LIBC_INLINE void call_exit_callbacks(ExitCallbackList &callbacks) { 49aac3a2a2SJoseph Huber handler_list_mtx.lock(); 50aac3a2a2SJoseph Huber while (!callbacks.empty()) { 51*50839802SAlexey Samsonov AtExitUnit unit = callbacks.back(); 52aac3a2a2SJoseph Huber callbacks.pop_back(); 53aac3a2a2SJoseph Huber handler_list_mtx.unlock(); 54aac3a2a2SJoseph Huber unit.callback(unit.payload); 55aac3a2a2SJoseph Huber handler_list_mtx.lock(); 56aac3a2a2SJoseph Huber } 57aac3a2a2SJoseph Huber ExitCallbackList::destroy(&callbacks); 58aac3a2a2SJoseph Huber } 5939d38d66Saaryanshukla 60aac3a2a2SJoseph Huber LIBC_INLINE int add_atexit_unit(ExitCallbackList &callbacks, 61aac3a2a2SJoseph Huber const AtExitUnit &unit) { 62aac3a2a2SJoseph Huber cpp::lock_guard lock(handler_list_mtx); 63aac3a2a2SJoseph Huber if (callbacks.push_back(unit)) 64aac3a2a2SJoseph Huber return 0; 65aac3a2a2SJoseph Huber return -1; 66aac3a2a2SJoseph Huber } 6739d38d66Saaryanshukla 685ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 6939d38d66Saaryanshukla 7039d38d66Saaryanshukla #endif // LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H 71