1d6698386SAlex Brachet //===-- Implementation of atexit ------------------------------------------===//
2d6698386SAlex Brachet //
3d6698386SAlex Brachet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d6698386SAlex Brachet // See https://llvm.org/LICENSE.txt for license information.
5d6698386SAlex Brachet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d6698386SAlex Brachet //
7d6698386SAlex Brachet //===----------------------------------------------------------------------===//
8d6698386SAlex Brachet 
9d6698386SAlex Brachet #include "src/stdlib/atexit.h"
1019c60980SSiva Chandra Reddy #include "src/__support/CPP/blockstore.h"
11d6698386SAlex Brachet #include "src/__support/common.h"
1283b8878fSSiva Chandra Reddy #include "src/__support/threads/mutex.h"
13d6698386SAlex Brachet 
14d6698386SAlex Brachet namespace __llvm_libc {
15d6698386SAlex Brachet 
16d6698386SAlex Brachet namespace {
17d6698386SAlex Brachet 
1883b8878fSSiva Chandra Reddy Mutex handler_list_mtx(false, false, false);
19d6698386SAlex Brachet 
2019c60980SSiva Chandra Reddy using AtExitCallback = void(void);
2119c60980SSiva Chandra Reddy using ExitCallbackList = cpp::ReverseOrderBlockStore<AtExitCallback *, 32>;
2219c60980SSiva Chandra Reddy constinit ExitCallbackList exit_callbacks;
23d6698386SAlex Brachet 
24d6698386SAlex Brachet } // namespace
25d6698386SAlex Brachet 
26d6698386SAlex Brachet namespace internal {
27d6698386SAlex Brachet 
call_exit_callbacks()2819c60980SSiva Chandra Reddy void call_exit_callbacks() {
2983b8878fSSiva Chandra Reddy   handler_list_mtx.lock();
30ae4b59f1SAlex Brachet   while (!exit_callbacks.empty()) {
31ae4b59f1SAlex Brachet     auto *callback = exit_callbacks.back();
32ae4b59f1SAlex Brachet     exit_callbacks.pop_back();
33*89aa4bd3SAlex Brachet     handler_list_mtx.unlock();
3419c60980SSiva Chandra Reddy     callback();
3583b8878fSSiva Chandra Reddy     handler_list_mtx.lock();
36d6698386SAlex Brachet   }
3719c60980SSiva Chandra Reddy   ExitCallbackList::destroy(&exit_callbacks);
38d6698386SAlex Brachet }
39d6698386SAlex Brachet 
40d6698386SAlex Brachet } // namespace internal
41d6698386SAlex Brachet 
4219c60980SSiva Chandra Reddy LLVM_LIBC_FUNCTION(int, atexit, (AtExitCallback * callback)) {
4383b8878fSSiva Chandra Reddy   handler_list_mtx.lock();
4419c60980SSiva Chandra Reddy   exit_callbacks.push_back(callback);
4583b8878fSSiva Chandra Reddy   handler_list_mtx.unlock();
46d6698386SAlex Brachet   return 0;
47d6698386SAlex Brachet }
48d6698386SAlex Brachet 
49d6698386SAlex Brachet } // namespace __llvm_libc
50