1 //===-- Implementation of at-fork callback helpers -----------------------===// 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 "fork_callbacks.h" 10 11 #include "src/__support/CPP/mutex.h" // lock_guard 12 #include "src/__support/threads/mutex.h" 13 14 #include <stddef.h> // For size_t 15 16 namespace LIBC_NAMESPACE { 17 18 namespace { 19 20 struct ForkCallbackTriple { 21 ForkCallback *prepare = nullptr; 22 ForkCallback *parent = nullptr; 23 ForkCallback *child = nullptr; 24 constexpr ForkCallbackTriple() = default; 25 }; 26 27 class AtForkCallbackManager { 28 static constexpr size_t CALLBACK_SIZE = 32; 29 // TODO: Replace this with block store when integration tests 30 // can use allocators. 31 ForkCallbackTriple list[CALLBACK_SIZE]; 32 Mutex mtx; 33 size_t next_index; 34 35 public: 36 constexpr AtForkCallbackManager() : mtx(false, false, false), next_index(0) {} 37 38 bool register_triple(const ForkCallbackTriple &triple) { 39 cpp::lock_guard lock(mtx); 40 if (next_index >= CALLBACK_SIZE) 41 return false; 42 list[next_index] = triple; 43 ++next_index; 44 return true; 45 } 46 47 void invoke_prepare() { 48 cpp::lock_guard lock(mtx); 49 for (size_t i = 0; i < next_index; ++i) { 50 auto prepare = list[i].prepare; 51 if (prepare) 52 prepare(); 53 } 54 } 55 56 void invoke_parent() { 57 cpp::lock_guard lock(mtx); 58 for (size_t i = 0; i < next_index; ++i) { 59 auto parent = list[i].parent; 60 if (parent) 61 parent(); 62 } 63 } 64 65 void invoke_child() { 66 cpp::lock_guard lock(mtx); 67 for (size_t i = 0; i < next_index; ++i) { 68 auto child = list[i].child; 69 if (child) 70 child(); 71 } 72 } 73 }; 74 75 AtForkCallbackManager cb_manager; 76 77 } // Anonymous namespace 78 79 bool register_atfork_callbacks(ForkCallback *prepare_cb, 80 ForkCallback *parent_cb, 81 ForkCallback *child_cb) { 82 return cb_manager.register_triple({prepare_cb, parent_cb, child_cb}); 83 } 84 85 void invoke_child_callbacks() { cb_manager.invoke_child(); } 86 87 void invoke_prepare_callbacks() { cb_manager.invoke_prepare(); } 88 89 void invoke_parent_callbacks() { cb_manager.invoke_parent(); } 90 91 } // namespace LIBC_NAMESPACE 92