mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-15 08:26:56 +00:00
kern: update for new interrupt event locking scheme
This commit is contained in:
parent
e81025af2e
commit
6ea1955e94
2 changed files with 32 additions and 27 deletions
|
@ -27,11 +27,10 @@ namespace ams::kern {
|
||||||
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
|
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
|
||||||
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
|
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
|
||||||
private:
|
private:
|
||||||
KInterruptEventTask *task;
|
|
||||||
s32 interrupt_id;
|
s32 interrupt_id;
|
||||||
bool is_initialized;
|
bool is_initialized;
|
||||||
public:
|
public:
|
||||||
constexpr KInterruptEvent() : task(nullptr), interrupt_id(-1), is_initialized(false) { /* ... */ }
|
constexpr KInterruptEvent() : interrupt_id(-1), is_initialized(false) { /* ... */ }
|
||||||
virtual ~KInterruptEvent() { /* ... */ }
|
virtual ~KInterruptEvent() { /* ... */ }
|
||||||
|
|
||||||
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
|
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
|
||||||
|
@ -49,17 +48,19 @@ namespace ams::kern {
|
||||||
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
|
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
|
||||||
private:
|
private:
|
||||||
KInterruptEvent *event;
|
KInterruptEvent *event;
|
||||||
s32 interrupt_id;
|
KLightLock lock;
|
||||||
public:
|
public:
|
||||||
constexpr KInterruptEventTask() : event(nullptr), interrupt_id(-1) { /* ... */ }
|
constexpr KInterruptEventTask() : event(nullptr), lock() { /* ... */ }
|
||||||
~KInterruptEventTask() { /* ... */ }
|
~KInterruptEventTask() { /* ... */ }
|
||||||
|
|
||||||
|
KLightLock &GetLock() { return this->lock; }
|
||||||
|
|
||||||
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
|
||||||
virtual void DoTask() override;
|
virtual void DoTask() override;
|
||||||
|
|
||||||
void Unregister();
|
void Unregister(s32 interrupt_id);
|
||||||
public:
|
public:
|
||||||
static Result Register(KInterruptEventTask **out, s32 interrupt_id, bool level, KInterruptEvent *event);
|
static Result Register(s32 interrupt_id, bool level, KInterruptEvent *event);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace ams::kern {
|
||||||
KReadableEvent::Initialize(nullptr);
|
KReadableEvent::Initialize(nullptr);
|
||||||
|
|
||||||
/* Try to register the task. */
|
/* Try to register the task. */
|
||||||
R_TRY(KInterruptEventTask::Register(std::addressof(this->task), this->interrupt_id, type == ams::svc::InterruptType_Level, this));
|
R_TRY(KInterruptEventTask::Register(this->interrupt_id, type == ams::svc::InterruptType_Level, this));
|
||||||
|
|
||||||
/* Mark initialized. */
|
/* Mark initialized. */
|
||||||
this->is_initialized = true;
|
this->is_initialized = true;
|
||||||
|
@ -44,15 +44,17 @@ namespace ams::kern {
|
||||||
void KInterruptEvent::Finalize() {
|
void KInterruptEvent::Finalize() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
MESOSPHERE_ASSERT(this->task != nullptr);
|
g_interrupt_event_task_table[this->interrupt_id]->Unregister(this->interrupt_id);
|
||||||
this->task->Unregister();
|
|
||||||
|
/* Perform inherited finalization. */
|
||||||
|
KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent>::Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KInterruptEvent::Reset() {
|
Result KInterruptEvent::Reset() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Lock the task table. */
|
/* Lock the task. */
|
||||||
KScopedLightLock lk(g_interrupt_event_lock);
|
KScopedLightLock lk(g_interrupt_event_task_table[this->interrupt_id]->GetLock());
|
||||||
|
|
||||||
/* Clear the event. */
|
/* Clear the event. */
|
||||||
R_TRY(KReadableEvent::Reset());
|
R_TRY(KReadableEvent::Reset());
|
||||||
|
@ -63,7 +65,7 @@ namespace ams::kern {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KInterruptEventTask::Register(KInterruptEventTask **out, s32 interrupt_id, bool level, KInterruptEvent *event) {
|
Result KInterruptEventTask::Register(s32 interrupt_id, bool level, KInterruptEvent *event) {
|
||||||
/* Verify the interrupt id is defined and global. */
|
/* Verify the interrupt id is defined and global. */
|
||||||
R_UNLESS(Kernel::GetInterruptManager().IsInterruptDefined(interrupt_id), svc::ResultOutOfRange());
|
R_UNLESS(Kernel::GetInterruptManager().IsInterruptDefined(interrupt_id), svc::ResultOutOfRange());
|
||||||
R_UNLESS(Kernel::GetInterruptManager().IsGlobal(interrupt_id), svc::ResultOutOfRange());
|
R_UNLESS(Kernel::GetInterruptManager().IsGlobal(interrupt_id), svc::ResultOutOfRange());
|
||||||
|
@ -85,45 +87,47 @@ namespace ams::kern {
|
||||||
allocated = true;
|
allocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register/bind the interrupt task. */
|
|
||||||
{
|
|
||||||
/* Ensure that the task is cleaned up if anything goes wrong. */
|
/* Ensure that the task is cleaned up if anything goes wrong. */
|
||||||
auto task_guard = SCOPE_GUARD { if (allocated) { KInterruptEventTask::Free(task); } };
|
auto task_guard = SCOPE_GUARD { if (allocated) { KInterruptEventTask::Free(task); } };
|
||||||
|
|
||||||
|
/* Register/bind the interrupt task. */
|
||||||
|
{
|
||||||
|
/* Acqquire exclusive access to the task. */
|
||||||
|
KScopedLightLock tlk(task->lock);
|
||||||
|
|
||||||
/* Bind the interrupt handler. */
|
/* Bind the interrupt handler. */
|
||||||
R_TRY(Kernel::GetInterruptManager().BindHandler(task, interrupt_id, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, level));
|
R_TRY(Kernel::GetInterruptManager().BindHandler(task, interrupt_id, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, level));
|
||||||
|
|
||||||
/* We successfully registered, so we don't need to free the task. */
|
|
||||||
task_guard.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the event. */
|
/* Set the event. */
|
||||||
task->event = event;
|
task->event = event;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we allocated, set the event in the table. */
|
/* If we allocated, set the event in the table. */
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
task->interrupt_id = interrupt_id;
|
|
||||||
g_interrupt_event_task_table[interrupt_id] = task;
|
g_interrupt_event_task_table[interrupt_id] = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the output. */
|
/* We successfully registered, so we don't need to free the task. */
|
||||||
*out = task;
|
task_guard.Cancel();
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KInterruptEventTask::Unregister() {
|
void KInterruptEventTask::Unregister(s32 interrupt_id) {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Lock the task table. */
|
/* Lock the task table. */
|
||||||
KScopedLightLock lk(g_interrupt_event_lock);
|
KScopedLightLock lk(g_interrupt_event_lock);
|
||||||
|
|
||||||
|
/* Lock the task. */
|
||||||
|
KScopedLightLock tlk(this->lock);
|
||||||
|
|
||||||
/* Ensure we can unregister. */
|
/* Ensure we can unregister. */
|
||||||
MESOSPHERE_ABORT_UNLESS(g_interrupt_event_task_table[this->interrupt_id] == this);
|
MESOSPHERE_ABORT_UNLESS(g_interrupt_event_task_table[interrupt_id] == this);
|
||||||
MESOSPHERE_ABORT_UNLESS(this->event != nullptr);
|
MESOSPHERE_ABORT_UNLESS(this->event != nullptr);
|
||||||
this->event = nullptr;
|
|
||||||
|
|
||||||
/* Unbind the interrupt. */
|
/* Unbind the interrupt. */
|
||||||
Kernel::GetInterruptManager().UnbindHandler(this->interrupt_id, GetCurrentCoreId());
|
this->event = nullptr;
|
||||||
|
Kernel::GetInterruptManager().UnbindHandler(interrupt_id, GetCurrentCoreId());
|
||||||
}
|
}
|
||||||
|
|
||||||
KInterruptTask *KInterruptEventTask::OnInterrupt(s32 interrupt_id) {
|
KInterruptTask *KInterruptEventTask::OnInterrupt(s32 interrupt_id) {
|
||||||
|
@ -136,7 +140,7 @@ namespace ams::kern {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Lock the task table. */
|
/* Lock the task table. */
|
||||||
KScopedLightLock lk(g_interrupt_event_lock);
|
KScopedLightLock lk(this->lock);
|
||||||
|
|
||||||
if (this->event != nullptr) {
|
if (this->event != nullptr) {
|
||||||
this->event->Signal();
|
this->event->Signal();
|
||||||
|
|
Loading…
Reference in a new issue