The Pedigree Project 0.1
RtcAlarmQueue.h
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#ifndef PEDIGREE_KERNEL_MACHINE_MACH_PC_RTCALARMQUEUE_H
9#define PEDIGREE_KERNEL_MACHINE_MACH_PC_RTCALARMQUEUE_H
10#include "pedigree/kernel/processor/types.h"
11#include "pedigree/kernel/utilities/assert.h"
12
13#include <config.h>
14
24 public:
26 template <typename Context>
27 static void* dispatchOwnerForContext(Context& context) {
28 auto* thread = context.getCurrentThread();
29 return thread ? static_cast<void*>(thread) : static_cast<void*>(&context);
30 }
31
32 class Record {
33 public:
34 Record()
35 : m_pEvent(nullptr),
36 m_Deadline(0),
37 m_pTarget(nullptr),
38 m_pNext(nullptr),
39 m_pDispatchOwner(nullptr),
40 m_bDispatching(false),
41 m_bDeferredRemoval(false) {}
42
43 void prepare(void* event, uint64_t deadline, void* target) {
44 assert(!m_pNext);
45 assert(!m_bDispatching);
46 m_pEvent = event;
47 m_Deadline = deadline;
48 m_pTarget = target;
49 m_pDispatchOwner = nullptr;
50 m_bDeferredRemoval = false;
51 }
52
53 void* event() const {
54 return m_pEvent;
55 }
56
57 uint64_t deadline() const {
58 return m_Deadline;
59 }
60
61 void* target() const {
62 return m_pTarget;
63 }
64
65 Record* next() const {
66 return m_pNext;
67 }
68
69 bool dispatching() const {
70 return m_bDispatching;
71 }
72
73 bool deferredRemoval() const {
74 return m_bDeferredRemoval;
75 }
76
77 private:
78 friend class RtcAlarmQueue;
79
80 void clear() {
81 m_pEvent = nullptr;
82 m_Deadline = 0;
83 m_pTarget = nullptr;
84 m_pDispatchOwner = nullptr;
85 m_bDispatching = false;
86 m_bDeferredRemoval = false;
87 }
88
89 void* m_pEvent;
90 uint64_t m_Deadline;
91 void* m_pTarget;
92 Record* m_pNext;
93 void* m_pDispatchOwner;
94 bool m_bDispatching;
95 bool m_bDeferredRemoval;
96 };
97
98 enum class RemovalDisposition {
99 NotFound,
100 Removed,
101 SelfDeferred,
102 RemoteInFlight,
103 };
104
105 struct Removal {
106 RemovalDisposition disposition;
107 Record* record;
108 uint64_t deadline;
109 };
110
111 RtcAlarmQueue() : m_pFirst(nullptr), m_pLast(nullptr), m_pFree(nullptr) {}
112
113 Record* takeReusable() {
114 Record* record = m_pFree;
115 if (record) {
116 m_pFree = record->m_pNext;
117 record->m_pNext = nullptr;
118 }
119 return record;
120 }
121
122 void add(Record* record) {
123 assert(record);
124 assert(record->m_pEvent);
125 assert(record->m_pTarget);
126 assert(!record->m_pNext);
127 assert(!record->m_bDispatching);
128 if (m_pLast) {
129 m_pLast->m_pNext = record;
130 } else {
131 m_pFirst = record;
132 }
133 m_pLast = record;
134 }
135
136 Record* claimDue(uint64_t now, void* owner) {
137 assert(owner);
138 for (Record* record = m_pFirst; record; record = record->m_pNext) {
139 if (!record->m_bDispatching && record->m_Deadline <= now) {
140 record->m_bDispatching = true;
141 record->m_pDispatchOwner = owner;
142 return record;
143 }
144 }
145 return nullptr;
146 }
147
148 Removal removeFirst(void* event, void* owner) {
149 Record* previous = nullptr;
150 for (Record* record = m_pFirst; record; record = record->m_pNext) {
151 if (record->m_pEvent != event) {
152 previous = record;
153 continue;
154 }
155 if (record->m_bDispatching) {
156 if (record->m_pDispatchOwner == owner) {
157 record->m_bDeferredRemoval = true;
158 return {RemovalDisposition::SelfDeferred, nullptr, record->m_Deadline};
159 }
160 return {RemovalDisposition::RemoteInFlight, nullptr, record->m_Deadline};
161 }
162
163 const uint64_t deadline = record->m_Deadline;
164 unlink(previous, record);
165 return {RemovalDisposition::Removed, record, deadline};
166 }
167 return {RemovalDisposition::NotFound, nullptr, 0};
168 }
169
170 Record* removeAllQueued(void* event, void* owner, bool& remoteInFlight, bool& selfDeferred) {
171 Record* removed = nullptr;
172 Record* removedTail = nullptr;
173 Record* previous = nullptr;
174 Record* record = m_pFirst;
175 while (record) {
176 Record* next = record->m_pNext;
177 if (record->m_pEvent != event) {
178 previous = record;
179 record = next;
180 continue;
181 }
182 if (record->m_bDispatching) {
183 if (record->m_pDispatchOwner == owner) {
184 record->m_bDeferredRemoval = true;
185 selfDeferred = true;
186 } else {
187 remoteInFlight = true;
188 }
189 previous = record;
190 record = next;
191 continue;
192 }
193
194 unlink(previous, record);
195 record->m_pNext = nullptr;
196 if (removedTail) {
197 removedTail->m_pNext = record;
198 } else {
199 removed = record;
200 }
201 removedTail = record;
202 record = next;
203 }
204 return removed;
205 }
206
207 bool hasRemoteInFlight(void* event, void* owner) const {
208 for (Record* record = m_pFirst; record; record = record->m_pNext) {
209 if (record->m_pEvent == event && record->m_bDispatching &&
210 record->m_pDispatchOwner != owner) {
211 return true;
212 }
213 }
214 return false;
215 }
216
217 void completeDispatch(Record* record) {
218 assert(record);
219 assert(record->m_bDispatching);
220 Record* previous = nullptr;
221 Record* candidate = m_pFirst;
222 while (candidate && candidate != record) {
223 previous = candidate;
224 candidate = candidate->m_pNext;
225 }
226 assert(candidate == record);
227 unlink(previous, record);
228 recycle(record);
229 }
230
231 void recycleList(Record* records) {
232 while (records) {
233 Record* next = records->m_pNext;
234 records->m_pNext = nullptr;
235 recycle(records);
236 records = next;
237 }
238 }
239
240 Record* detachActive() {
241 Record* records = m_pFirst;
242 m_pFirst = nullptr;
243 m_pLast = nullptr;
244 return records;
245 }
246
247 Record* detachFree() {
248 Record* records = m_pFree;
249 m_pFree = nullptr;
250 return records;
251 }
252
253 size_t activeCount() const {
254 size_t count = 0;
255 for (Record* record = m_pFirst; record; record = record->m_pNext) {
256 ++count;
257 }
258 return count;
259 }
260
261 size_t freeCount() const {
262 size_t count = 0;
263 for (Record* record = m_pFree; record; record = record->m_pNext) {
264 ++count;
265 }
266 return count;
267 }
268
269 private:
270 void unlink(Record* previous, Record* record) {
271 if (previous) {
272 previous->m_pNext = record->m_pNext;
273 } else {
274 m_pFirst = record->m_pNext;
275 }
276 if (m_pLast == record) {
277 m_pLast = previous;
278 }
279 record->m_pNext = nullptr;
280 }
281
282 void recycle(Record* record) {
283 record->clear();
284 record->m_pNext = m_pFree;
285 m_pFree = record;
286 }
287
288 Record* m_pFirst;
289 Record* m_pLast;
290 Record* m_pFree;
291};
292
293#endif
static void * dispatchOwnerForContext(Context &context)
#define assert(x)
Definition assert.h:39