platform: multiple persistent irq handlers

This commit is contained in:
psucien 2024-05-17 23:30:34 +02:00
parent 9ad7495661
commit 058e728e29
1 changed files with 10 additions and 9 deletions

View File

@ -12,6 +12,7 @@
#include <functional> #include <functional>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <unordered_map>
#include <queue> #include <queue>
namespace Platform { namespace Platform {
@ -38,21 +39,21 @@ struct IrqController {
ctx.one_time_subscribers.emplace(handler); ctx.one_time_subscribers.emplace(handler);
} }
void Register(InterruptId irq, IrqHandler handler) { void Register(InterruptId irq, IrqHandler handler, void* uid) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number");
auto& ctx = irq_contexts[static_cast<u32>(irq)]; auto& ctx = irq_contexts[static_cast<u32>(irq)];
ASSERT_MSG(!ctx.persistent_handler.has_value(),
"Too many persistent handlers"); // Add a slot map if so
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
ctx.persistent_handler.emplace(handler); ASSERT_MSG(ctx.persistent_handlers.find(uid) == ctx.persistent_handlers.cend(),
"The handler is already registered!");
ctx.persistent_handlers.emplace(uid, handler);
} }
void Unregister(InterruptId irq) { void Unregister(InterruptId irq, void* uid) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number");
auto& ctx = irq_contexts[static_cast<u32>(irq)]; auto& ctx = irq_contexts[static_cast<u32>(irq)];
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
ctx.persistent_handler.reset(); ctx.persistent_handlers.erase(uid);
} }
void Signal(InterruptId irq) { void Signal(InterruptId irq) {
@ -62,8 +63,8 @@ struct IrqController {
LOG_TRACE(Core, "IRQ signaled: {}", magic_enum::enum_name(irq)); LOG_TRACE(Core, "IRQ signaled: {}", magic_enum::enum_name(irq));
if (ctx.persistent_handler) { for (auto& [uid, h] : ctx.persistent_handlers) {
ctx.persistent_handler.value()(irq); h(irq);
} }
while (!ctx.one_time_subscribers.empty()) { while (!ctx.one_time_subscribers.empty()) {
@ -76,7 +77,7 @@ struct IrqController {
private: private:
struct IrqContext { struct IrqContext {
std::optional<IrqHandler> persistent_handler{}; std::unordered_map<void*, IrqHandler> persistent_handlers{};
std::queue<IrqHandler> one_time_subscribers{}; std::queue<IrqHandler> one_time_subscribers{};
std::mutex m_lock{}; std::mutex m_lock{};
}; };