-
Notifications
You must be signed in to change notification settings - Fork 0
/
RobustList.h
83 lines (71 loc) · 1.89 KB
/
RobustList.h
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
#pragma once
#include <linux/futex.h>
#include <spdlog/spdlog.h>
#include <unistd.h>
#include <atomic>
#include <cstring>
#include <iostream>
namespace libfutex {
// forward declaration
class Futex;
std::ostream& operator<<(std::ostream& os, const Futex& f);
static constexpr int FUTEX_OFFSET = 16;
/**
* A thread-local list of futexes owned by the thread.
*/
class RobustList {
/**
* Per-thread list head
*/
robust_list_head head = {
/**
* The head of the list. Points back to itself if empty.
*/
.list = {.next = &head.list},
/**
* Relative offset to the futex value.
*/
.futex_offset = FUTEX_OFFSET,
/**
* The address of the to-be-taken lock used to avoid race condition.
*/
.list_op_pending = nullptr,
};
/**
* Call `set_robust_list` to register the robust list to the kernel, so the
* kernel can clean up the futexes owned by the thread when the thread
* exits.
*/
RobustList() {
int rc = (int)syscall(SYS_set_robust_list, &head.list, sizeof(head));
if (rc == 0) {
SPDLOG_DEBUG("set_robust_list({})", (void*)&head.list);
} else {
SPDLOG_ERROR("set_robust_list failed: {}", strerror(rc));
}
}
public:
/**
* @return the number of futexes in the robust list.
*/
[[nodiscard]] size_t size() const {
size_t size = 0;
for (auto* p = head.list.next; p != &head.list; p = p->next) size++;
return size;
}
friend std::ostream& operator<<(std::ostream& os, const RobustList& rl) {
os << "RobustList (" << &rl << ") ";
if (rl.head.list.next == &rl.head.list) {
os << "{}";
} else {
os << "{\n";
for (auto* p = rl.head.list.next; p != &rl.head.list; p = p->next) {
os << "\t" << p << ": " << *reinterpret_cast<Futex*>(p) << ", \n";
}
os << "}";
}
return os;
}
friend class Futex;
};
} // namespace libfutex