xref: /aosp_15_r20/external/llvm-libc/src/__support/threads/fork_callbacks.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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 
17 namespace LIBC_NAMESPACE_DECL {
18 
19 namespace {
20 
21 struct ForkCallbackTriple {
22   ForkCallback *prepare = nullptr;
23   ForkCallback *parent = nullptr;
24   ForkCallback *child = nullptr;
25   constexpr ForkCallbackTriple() = default;
26 };
27 
28 class 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 
36 public:
AtForkCallbackManager()37   constexpr AtForkCallbackManager()
38       : mtx(/*timed=*/false, /*recursive=*/false, /*robust=*/false,
39             /*pshared=*/false),
40         next_index(0) {}
41 
register_triple(const ForkCallbackTriple & triple)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 
invoke_prepare()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 
invoke_parent()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 
invoke_child()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 
79 AtForkCallbackManager cb_manager;
80 
81 } // Anonymous namespace
82 
register_atfork_callbacks(ForkCallback * prepare_cb,ForkCallback * parent_cb,ForkCallback * child_cb)83 bool 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 
invoke_child_callbacks()89 void invoke_child_callbacks() { cb_manager.invoke_child(); }
90 
invoke_prepare_callbacks()91 void invoke_prepare_callbacks() { cb_manager.invoke_prepare(); }
92 
invoke_parent_callbacks()93 void invoke_parent_callbacks() { cb_manager.invoke_parent(); }
94 
95 } // namespace LIBC_NAMESPACE_DECL
96