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