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