20#include "pedigree/kernel/LockGuard.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/compiler.h"
23#include "pedigree/kernel/process/Event.h"
24#include "pedigree/kernel/process/Process.h"
25#include "pedigree/kernel/process/Scheduler.h"
26#include "pedigree/kernel/process/Thread.h"
27#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
28#include "pedigree/kernel/processor/Processor.h"
29#include "pedigree/kernel/processor/ProcessorInformation.h"
30#include "pedigree/kernel/processor/VirtualAddressSpace.h"
31#include "pedigree/kernel/utilities/Iterator.h"
32#include "pedigree/kernel/utilities/utility.h"
34Event::Event(uintptr_t handlerAddress,
bool isDeletable,
size_t specificNestingLevel,
36 : m_HandlerAddress(handlerAddress),
37 m_HandlerPrivilege(handlerPrivilege),
38 m_bIsDeletable(isDeletable),
39 m_NestingLevel(specificNestingLevel),
43 m_DeleteWhenUnused(false),
44 m_DeliveriesClosed(false),
45 m_DrainClaimed(false),
47 m_pFirstActiveDelivery(nullptr),
48 m_DeliveryWaiters() {}
50Event::SendLease::SendLease() : m_pEvent(nullptr) {}
52Event::SendLease::SendLease(
Event* event) : m_pEvent(event) {}
54Event::SendLease::SendLease(SendLease&& other) noexcept : m_pEvent(other.m_pEvent) {
55 other.m_pEvent =
nullptr;
58Event::SendLease::~SendLease() {
65 m_pEvent = other.m_pEvent;
66 other.m_pEvent =
nullptr;
71void Event::SendLease::reset() {
72 Event*
event = m_pEvent;
79Event::Retirement::Retirement() : m_pEvent(nullptr) {}
81Event::Retirement::Retirement(
Event* event) : m_pEvent(event) {}
83Event::Retirement::Retirement(Retirement&& other) noexcept : m_pEvent(other.m_pEvent) {
84 other.m_pEvent =
nullptr;
87Event::Retirement::~Retirement() {
94 m_pEvent = other.m_pEvent;
95 other.m_pEvent =
nullptr;
100void Event::Retirement::reset() {
101 Event*
event = m_pEvent;
104 event->finishRetirement();
108Event::Delivery::Delivery()
111 m_pPreviousActive(nullptr),
112 m_pNextActive(nullptr),
115Event::Delivery::Delivery(
Event* event,
Thread* thread)
118 m_pPreviousActive(nullptr),
119 m_pNextActive(nullptr),
122Event::Delivery::Delivery(Delivery&& other) noexcept
123 : m_pEvent(other.m_pEvent),
124 m_pThread(other.m_pThread),
125 m_pPreviousActive(
nullptr),
126 m_pNextActive(
nullptr),
128 if (other.m_bActive) {
129 FATAL(
"Moving an active Event delivery.");
131 other.m_pEvent =
nullptr;
132 other.m_pThread =
nullptr;
135Event::Delivery::~Delivery() {
139Event::Delivery& Event::Delivery::operator=(Delivery&& other)
noexcept {
140 if (
this != &other) {
141 if (other.m_bActive) {
142 FATAL(
"Moving an active Event delivery.");
145 m_pEvent = other.m_pEvent;
146 m_pThread = other.m_pThread;
147 other.m_pEvent =
nullptr;
148 other.m_pThread =
nullptr;
153void Event::Delivery::beginDispatch() {
155 m_pEvent->beginDispatch(
this);
160 Event*
event = m_pEvent;
161 Thread* thread = m_pThread;
164 event->endDispatch(
this);
168 event->completeDelivery(thread);
175 FATAL(
"Deleting an Event while delivery waiters are live.");
181 FATAL(
"Deleting an Event with admitted senders.");
185 FATAL(
"Deleting an Event with an active kernel delivery.");
189 ERROR(
"UNSAFE EVENT DELETION");
191 ERROR(
" => Pending delivery to thread " << it <<
" (" << it->getParent()->getId() <<
":"
192 << it->getId() <<
").");
194 FATAL(
"Unsafe event deletion: " <<
m_Threads.
count() <<
" threads reference it!");
239 ERROR(
"Event::unserialize is abstract, should never be called.");
244 void* alignedBuffer = ASSUME_ALIGNMENT(pBuffer,
sizeof(
size_t));
245 size_t* pBufferSize_t =
reinterpret_cast<size_t*
>(alignedBuffer);
246 return pBufferSize_t[0];
257 if (
this == &other) {
263 FATAL(
"Cannot replace an Event while deliveries are live.");
266 FATAL(
"Cannot replace an Event while its lifetime is owned.");
290void Event::endSend() {
291 bool drained =
false;
292 bool deleteNow =
false;
322 bool finalDelivery =
false;
323 bool deleteNow =
false;
349 bool deleteNow =
false;
352 bool finalDelivery =
false;
366 FATAL(
"Completing an event delivery with no registration.");
394 return static_cast<bool>(registration);
399 if (delivery->m_bActive || delivery->m_pEvent !=
this) {
400 FATAL(
"Invalid Event delivery activation.");
403 delivery->m_pPreviousActive =
nullptr;
409 delivery->m_bActive =
true;
412void Event::endDispatch(Delivery* delivery) {
414 if (!delivery->m_bActive || delivery->m_pEvent !=
this) {
415 FATAL(
"Invalid Event delivery deactivation.");
418 if (delivery->m_pPreviousActive) {
419 delivery->m_pPreviousActive->m_pNextActive = delivery->m_pNextActive;
424 if (delivery->m_pNextActive) {
425 delivery->m_pNextActive->m_pPreviousActive = delivery->m_pPreviousActive;
428 delivery->m_pPreviousActive =
nullptr;
429 delivery->m_pNextActive =
nullptr;
430 delivery->m_bActive =
false;
440 FATAL(
"Cannot wait on a self-deleting Event.");
443 bool claimed =
false;
451 "Event delivery drain attempted by more than one "
460 delivery = delivery->m_pNextActive) {
461 if (delivery->m_pThread == current) {
463 "Event handler attempted to drain its own active "
464 "delivery; use Event::retire for heap ownership.");
472 const WaitQueue::WakeReason wakeReason =
474 reinterpret_cast<uintptr_t
>(__builtin_return_address(0)));
489 FATAL(
"Explicitly retiring an already self-deleting Event.");
492 FATAL(
"Cannot retire an Event whose drain is already owned.");
502void Event::finishRetirement() {
506 FATAL(
"Completing an Event retirement without ownership.");
static uintptr_t getTrampoline()
WaitQueue m_DeliveryWaiters
virtual bool isDeletable()
static uintptr_t getSecondaryTrampoline()
bool registerThread(Thread *thread)
HandlerPrivilege m_HandlerPrivilege
void completeDelivery(Thread *thread)
static size_t getHandlerBufferSize()
void deregisterThread(Thread *thread)
bool isValidHandlerMapping(size_t mappingFlags) const
void beginDispatch(Delivery *delivery)
virtual void waitForDeliveries()
void beginRetirement(Retirement &retirement)
bool tryAcquireRegistration(SendLease ®istration)
static uintptr_t getLastHandlerBuffer()
static uintptr_t getHandlerBuffer()
static size_t getEventType(uint8_t *pBuffer)
Event(uintptr_t handlerAddress, bool isDeletable, size_t specificNestingLevel=~0UL, HandlerPrivilege handlerPrivilege=HandlerPrivilege::Kernel)
List< Thread * > m_Threads
static bool unserialize(uint8_t *pBuffer, Event &event)
Delivery * m_pFirstActiveDelivery
uintptr_t m_HandlerAddress
::Iterator< T, node_t > Iterator
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()
static const size_t KernelMode
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
static const size_t Execute
virtual uintptr_t getKernelEventBlockStart() const =0
Iterator erase(Iterator &Iter)
void pushBack(const T &value)