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/macros/config.h"
13#include "src/__support/threads/mutex.h"
14
15#include <stddef.h> // For size_t
16
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 tests
31 // 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 namespace
82
83bool register_atfork_callbacks(ForkCallback *prepare_cb,
84 ForkCallback *parent_cb,
85 ForkCallback *child_cb) {
86 return cb_manager.register_triple(triple: {.prepare: prepare_cb, .parent: parent_cb, .child: 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_DECL
96

source code of libc/src/__support/threads/fork_callbacks.cpp