1 //===-- Implementation of atexit ------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/stdlib/atexit.h" 10 #include "src/__support/CPP/vector.h" 11 #include "src/__support/common.h" 12 #include "src/threads/mtx_init.h" 13 #include "src/threads/mtx_lock.h" 14 #include "src/threads/mtx_unlock.h" 15 16 namespace __llvm_libc { 17 18 namespace { 19 20 mtx_t lock; 21 // TODO need an easier way to use mtx_t internally, or use pthread_mutex_t 22 // with PTHREAD_MUTEX_INITIALIZER when it lands. 23 struct Init { 24 Init() { __llvm_libc::mtx_init(&lock, mtx_plain); } 25 } init; 26 27 // TOOD should we make cpp::vector like llvm::SmallVector<T, N> where it will 28 // allocate at least N before needing dynamic allocation? 29 static cpp::vector<void (*)(void)> handlers; 30 31 } // namespace 32 33 namespace internal { 34 35 void call_exit_handlers() { 36 __llvm_libc::mtx_lock(&lock); 37 // TODO: implement rbegin() + rend() for cpp::vector 38 for (int i = handlers.size() - 1; i >= 0; i--) { 39 __llvm_libc::mtx_unlock(&lock); 40 handlers[i](); 41 __llvm_libc::mtx_lock(&lock); 42 } 43 } 44 45 } // namespace internal 46 47 LLVM_LIBC_FUNCTION(int, atexit, (void (*function)())) { 48 __llvm_libc::mtx_lock(&lock); 49 handlers.push_back(function); 50 __llvm_libc::mtx_unlock(&lock); 51 return 0; 52 } 53 54 } // namespace __llvm_libc 55