The Pedigree Project 0.1
TimerHandlerRegistry.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_TIMERHANDLERREGISTRY_H
9#define PEDIGREE_KERNEL_MACHINE_TIMERHANDLERREGISTRY_H
10#include "pedigree/kernel/Spinlock.h"
11#include "pedigree/kernel/compiler.h"
12#include "pedigree/kernel/process/AtomicStateCleanup.h"
13#include "pedigree/kernel/process/WaitQueue.h"
14#include "pedigree/kernel/processor/types.h"
15
16#include <config.h>
17
18class TimerHandler;
19
26class EXPORTED_PUBLIC TimerHandlerRegistry {
27 public:
29
30 bool registerHandler(TimerHandler* handler);
31
33 bool armHandler(TimerHandler* handler, uint64_t deadline, uint64_t now);
34
36 uint64_t nextDeadline() const;
37
47 bool unregisterHandler(TimerHandler* handler);
48
50 bool dispatch(uint64_t delta, TimerHandler* onlyHandler = nullptr);
51
53 bool dispatchDue(uint64_t now);
54
56 void reset();
57
58#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
59 using HandlerPinHook = void (*)(TimerHandler*);
60 using HandlerPrePinHook = void (*)(TimerHandler*);
61 using HandlerHazardClaimHook = void (*)(TimerHandler*);
62 using HandlerAtomicDrainHook = void (*)(TimerHandler*);
63 using MutationLockHook = void (*)();
64
65 void setHandlerPinHook(HandlerPinHook hook);
66 void setHandlerPrePinHook(HandlerPrePinHook hook);
67 void setHandlerHazardClaimHook(HandlerHazardClaimHook hook);
68 void setHandlerAtomicDrainHook(HandlerAtomicDrainHook hook);
69 void withMutationLockForTest(MutationLockHook hook);
70 size_t activeDispatchCountForTest(TimerHandler* handler);
71 size_t claimedDispatchCountForTest();
72#endif
73
74 private:
75 static constexpr size_t MaxHandlerSlots = 32;
76 static constexpr size_t MaxActiveDispatches = 64;
77 static constexpr uint64_t NoDeadline = ~static_cast<uint64_t>(0);
78
79 enum class SlotMode : size_t {
80 Empty = 0,
81 Enabled,
82 Draining,
83 Deferred,
84 Retiring,
85 };
86
87 static constexpr size_t ModeBits = 3;
88 static constexpr size_t ModeMask = (1 << ModeBits) - 1;
89 static constexpr size_t SelfRemovalBit = 1 << ModeBits;
90 static constexpr size_t SynchronousDrainBit = 1 << (ModeBits + 1);
91 static constexpr size_t GenerationShift = ModeBits + 2;
92
93 struct HandlerSlot;
94
96 ActiveDispatch() : token(nullptr), generation(0), owner(nullptr), slot(nullptr) {}
97
98 void* token;
99 size_t generation;
100 void* owner;
101 HandlerSlot* slot;
102 };
103
104 struct HandlerSlot {
106 : handler(nullptr), publication(0), deadline(NoDeadline), lastDispatch(NoDeadline) {}
107
108 TimerHandler* handler;
109 size_t publication;
110 uint64_t deadline;
111 uint64_t lastDispatch;
112 };
113
115 DispatchCleanup(TimerHandlerRegistry* handlerRegistry, HandlerSlot* handlerSlot,
116 void* dispatchOwner, size_t admittedPublication)
117 : registry(handlerRegistry),
118 slot(handlerSlot),
119 owner(dispatchOwner),
120 publication(admittedPublication),
121 activeDispatch(nullptr),
122 cleanup() {}
123
124 TimerHandlerRegistry* registry;
125 HandlerSlot* slot;
126 void* owner;
127 size_t publication;
128 ActiveDispatch* activeDispatch;
130 };
131
132 static size_t makePublication(size_t generation, SlotMode mode, bool selfRemoval = false,
133 bool synchronousDrain = false);
134 static size_t generationOf(size_t publication);
135 static SlotMode modeOf(size_t publication);
136 static bool selfRemovalOf(size_t publication);
137 static bool synchronousDrainOf(size_t publication);
138
139 bool retireSlot(HandlerSlot& slot, size_t expectedPublication, TimerHandler* expectedHandler);
140 bool publishDispatch(DispatchCleanup& cleanup);
141 bool unpublishDispatch(DispatchCleanup& cleanup, bool required);
142 static void abandonDispatch(void* context);
143 bool hasActiveDispatch(HandlerSlot& slot) const;
144 bool findCurrentDispatch(void* owner, HandlerSlot* target, bool& callbackContext) const;
145 static void* currentDispatchOwner();
146 bool dispatchSelected(uint64_t delta, TimerHandler* onlyHandler, bool dueOnly, uint64_t now);
147
148 HandlerSlot m_Handlers[MaxHandlerSlots];
149 ActiveDispatch m_ActiveDispatches[MaxActiveDispatches];
150 WaitQueue m_DispatchWaiters;
151 Spinlock m_HandlerLock;
152
153#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
154 HandlerPinHook m_HandlerPinHook;
155 HandlerPrePinHook m_HandlerPrePinHook;
156 HandlerHazardClaimHook m_HandlerHazardClaimHook;
157 HandlerAtomicDrainHook m_HandlerAtomicDrainHook;
158#endif
159};
160
161#endif