The Pedigree Project 0.1
RcuReadState.h
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#ifndef PEDIGREE_KERNEL_PROCESS_RCUREADSTATE_H
3#define PEDIGREE_KERNEL_PROCESS_RCUREADSTATE_H
4
5#include "pedigree/kernel/panic.h"
6#include "pedigree/kernel/processor/types.h"
7
9class alignas(64) RcuReadState {
10 public:
11 using Snapshot = uint64_t;
12
13 void enter() {
14 Snapshot state = __atomic_load_n(&m_State, __ATOMIC_RELAXED);
15 do {
16 if ((state & DepthMask) == DepthMask) {
17 panic("RCU reader nesting overflow.");
18 }
19 } while (!__atomic_compare_exchange_n(&m_State, &state, state + 1, true, __ATOMIC_SEQ_CST,
20 __ATOMIC_RELAXED));
21 }
22
23 void leave() {
24 Snapshot state = __atomic_load_n(&m_State, __ATOMIC_RELAXED);
25 Snapshot next;
26 do {
27 const Snapshot depth = state & DepthMask;
28 if (!depth) {
29 panic("RCU reader nesting underflow.");
30 }
31 // A generation advances only after the outermost reader has finished.
32 next = depth == 1 ? state + Generation - 1 : state - 1;
33 } while (!__atomic_compare_exchange_n(&m_State, &state, next, true, __ATOMIC_RELEASE,
34 __ATOMIC_RELAXED));
35 }
36
37 Snapshot snapshot() const {
38 return __atomic_load_n(&m_State, __ATOMIC_SEQ_CST);
39 }
40
41 bool passed(Snapshot before) const {
42 if (!(before & DepthMask)) {
43 return true;
44 }
45 const Snapshot now = __atomic_load_n(&m_State, __ATOMIC_ACQUIRE);
46 return !(now & DepthMask) || (now & ~DepthMask) != (before & ~DepthMask);
47 }
48
49 bool active() const {
50 return (__atomic_load_n(&m_State, __ATOMIC_RELAXED) & DepthMask) != 0;
51 }
52
53 private:
54 static constexpr Snapshot Generation = Snapshot{1} << 32;
55 static constexpr Snapshot DepthMask = Generation - 1;
56 static_assert(__atomic_always_lock_free(sizeof(Snapshot), nullptr));
57 alignas(sizeof(Snapshot)) Snapshot m_State = 0;
58};
59
60#endif
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition panic.cc:117