From 47ede74326d980c0c14abc77025794b105fdcb07 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 11 Dec 2020 13:41:51 -0700 Subject: [PATCH] Kernel: Execute timer handlers outside of irq handler This allows us to do things in timer handlers that involve e.g. scheduling, such as using the Lock class or unblocking threads. --- Kernel/TimerQueue.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Kernel/TimerQueue.cpp b/Kernel/TimerQueue.cpp index 2419386f7f..a14058ebcf 100644 --- a/Kernel/TimerQueue.cpp +++ b/Kernel/TimerQueue.cpp @@ -272,19 +272,24 @@ void TimerQueue::fire() while (timer && timer->now() > timer->m_expires) { queue.list.remove(timer); + timer->set_queued(false); + m_timers_executing.append(timer); update_next_timer_due(queue); lock.unlock(); - timer->m_callback(); + + // Defer executing the timer outside of the irq handler + Processor::current().deferred_call_queue([this, timer]() { + timer->m_callback(); + ScopedSpinLock lock(g_timerqueue_lock); + m_timers_executing.remove(timer); + // Drop the reference we added when queueing the timer + timer->unref(); + }); + lock.lock(); - - m_timers_executing.remove(timer); - timer->set_queued(false); - // Drop the reference we added when queueing the timer - timer->unref(); - timer = queue.list.head(); } };