• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
AtForkCallbackManager()36   constexpr AtForkCallbackManager()
37       : mtx(/*timed=*/false, /*recursive=*/false, /*robust=*/false,
38             /*pshared=*/false),
39         next_index(0) {}
40 
register_triple(const ForkCallbackTriple & triple)41   bool register_triple(const ForkCallbackTriple &triple) {
42     cpp::lock_guard lock(mtx);
43     if (next_index >= CALLBACK_SIZE)
44       return false;
45     list[next_index] = triple;
46     ++next_index;
47     return true;
48   }
49 
invoke_prepare()50   void invoke_prepare() {
51     cpp::lock_guard lock(mtx);
52     for (size_t i = 0; i < next_index; ++i) {
53       auto prepare = list[i].prepare;
54       if (prepare)
55         prepare();
56     }
57   }
58 
invoke_parent()59   void invoke_parent() {
60     cpp::lock_guard lock(mtx);
61     for (size_t i = 0; i < next_index; ++i) {
62       auto parent = list[i].parent;
63       if (parent)
64         parent();
65     }
66   }
67 
invoke_child()68   void invoke_child() {
69     cpp::lock_guard lock(mtx);
70     for (size_t i = 0; i < next_index; ++i) {
71       auto child = list[i].child;
72       if (child)
73         child();
74     }
75   }
76 };
77 
78 AtForkCallbackManager cb_manager;
79 
80 } // Anonymous namespace
81 
register_atfork_callbacks(ForkCallback * prepare_cb,ForkCallback * parent_cb,ForkCallback * child_cb)82 bool register_atfork_callbacks(ForkCallback *prepare_cb,
83                                ForkCallback *parent_cb,
84                                ForkCallback *child_cb) {
85   return cb_manager.register_triple({prepare_cb, parent_cb, child_cb});
86 }
87 
invoke_child_callbacks()88 void invoke_child_callbacks() { cb_manager.invoke_child(); }
89 
invoke_prepare_callbacks()90 void invoke_prepare_callbacks() { cb_manager.invoke_prepare(); }
91 
invoke_parent_callbacks()92 void invoke_parent_callbacks() { cb_manager.invoke_parent(); }
93 
94 } // namespace LIBC_NAMESPACE
95