The Pedigree Project 0.1
OperationBarrier.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include "pedigree/kernel/Log.h"
9#include "pedigree/kernel/panic.h"
10#include "pedigree/kernel/process/OperationBarrier.h"
11#include "pedigree/kernel/process/TerminationDeferral.h"
12#include "pedigree/kernel/process/Thread.h"
13
14OperationBarrier::Lease::Lease() : m_Barrier(nullptr) {}
15
16OperationBarrier::Lease::Lease(OperationBarrier* barrier) : m_Barrier(barrier) {}
17
18OperationBarrier::Lease::Lease(Lease&& other) noexcept : m_Barrier(other.m_Barrier) {
19 other.m_Barrier = nullptr;
20}
21
22OperationBarrier::Lease::~Lease() {
23 reset();
24}
25
26OperationBarrier::Lease& OperationBarrier::Lease::operator=(
27 OperationBarrier::Lease&& other) noexcept {
28 if (this != &other) {
29 reset();
30 m_Barrier = other.m_Barrier;
31 other.m_Barrier = nullptr;
32 }
33 return *this;
34}
35
36void OperationBarrier::Lease::reset() {
37 if (m_Barrier) {
38 OperationBarrier* barrier = m_Barrier;
39 m_Barrier = nullptr;
40 barrier->leave();
41 }
42}
43
44OperationBarrier::OperationBarrier() : m_Waiters(), m_Open(true), m_ActiveOperations(0) {}
45
46OperationBarrier::~OperationBarrier() {
47 auto guard = m_Waiters.acquire();
48 if (m_Open || m_ActiveOperations) {
49 panic("OperationBarrier destroyed before close-and-drain completed.");
50 }
51}
52
54 auto guard = m_Waiters.acquire();
55 if (!m_Open) {
56 return false;
57 }
58
59 ++m_ActiveOperations;
60 return true;
61}
62
64 if (!tryEnter()) {
65 lease = Lease();
66 return false;
67 }
68
69 lease = Lease(this);
70 return true;
71}
72
74 auto guard = m_Waiters.acquire();
75 if (!m_ActiveOperations) {
76 panic("OperationBarrier operation count underflow.");
77 }
78 --m_ActiveOperations;
79 if (!m_Open && !m_ActiveOperations) {
80 guard.wakeAll(WaitQueue::WakeReason::Signalled, WaitQueue::Channel(this));
81 }
82}
83
85 auto guard = m_Waiters.acquire();
86 m_Open = false;
87}
88
90 auto guard = m_Waiters.acquire();
91 if (m_ActiveOperations) {
92 return false;
93 }
94 m_Open = false;
95 return true;
96}
97
99 TerminationDeferral terminationDeferral;
100 while (true) {
101 auto guard = m_Waiters.acquire();
102 if (m_Open) {
103 panic("OperationBarrier::wait called before close.");
104 }
105 if (!m_ActiveOperations) {
106 return;
107 }
108
109 const WaitQueue::WakeReason reason =
110 guard.waitForCompletion(WaitQueue::Channel(this), Thread::CallbackDrain,
111 reinterpret_cast<uintptr_t>(__builtin_return_address(0)));
112 (void)reason;
113 }
114}
115
117 close();
118 wait();
119}
120
121bool OperationBarrier::isOpen() {
122 auto guard = m_Waiters.acquire();
123 return m_Open;
124}
125
126bool OperationBarrier::isClosedAndDrained() {
127 auto guard = m_Waiters.acquire();
128 return !m_Open && !m_ActiveOperations;
129}
MUST_USE_RESULT bool tryCloseIfIdle()
MUST_USE_RESULT bool tryAcquire(Lease &lease)
MUST_USE_RESULT bool tryEnter()
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition panic.cc:117