mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 01:37:39 +03:00
Kernel: Use TimerQueue for SIGALRM
This commit is contained in:
parent
601a688b6f
commit
4c1e27ec65
Notes:
sideshowbarker
2024-07-19 01:05:49 +09:00
Author: https://github.com/tomuta Commit: https://github.com/SerenityOS/serenity/commit/4c1e27ec656 Pull-request: https://github.com/SerenityOS/serenity/pull/4298
@ -367,6 +367,7 @@ Process::Process(RefPtr<Thread>& first_thread, const String& name, uid_t uid, gi
|
||||
Process::~Process()
|
||||
{
|
||||
ASSERT(thread_count() == 0); // all threads should have been finalized
|
||||
ASSERT(!m_alarm_timer);
|
||||
|
||||
{
|
||||
ScopedSpinLock processses_lock(g_processes_lock);
|
||||
@ -596,6 +597,8 @@ void Process::finalize(Thread& last_thread)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_alarm_timer)
|
||||
TimerQueue::the().cancel_timer(m_alarm_timer.release_nonnull());
|
||||
m_fds.clear();
|
||||
m_tty = nullptr;
|
||||
m_executable = nullptr;
|
||||
|
@ -611,7 +611,7 @@ private:
|
||||
Lock m_big_lock { "Process" };
|
||||
mutable SpinLock<u32> m_lock;
|
||||
|
||||
u64 m_alarm_deadline { 0 };
|
||||
RefPtr<Timer> m_alarm_timer;
|
||||
|
||||
int m_icon_id { -1 };
|
||||
|
||||
|
@ -137,15 +137,6 @@ bool Scheduler::pick_next()
|
||||
current_thread->set_state(Thread::Dying);
|
||||
}
|
||||
|
||||
Process::for_each([&](Process& process) {
|
||||
if (process.m_alarm_deadline && TimeManagement::the().uptime_ms() > process.m_alarm_deadline) {
|
||||
process.m_alarm_deadline = 0;
|
||||
// FIXME: Should we observe this signal somehow?
|
||||
(void)process.send_signal(SIGALRM, nullptr);
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
#ifdef SCHEDULER_RUNNABLE_DEBUG
|
||||
dbg() << "Scheduler[" << Processor::current().id() << "]: Non-runnables:";
|
||||
Scheduler::for_each_nonrunnable([&](Thread& thread) -> IterationDecision {
|
||||
|
@ -33,15 +33,25 @@ unsigned Process::sys$alarm(unsigned seconds)
|
||||
{
|
||||
REQUIRE_PROMISE(stdio);
|
||||
unsigned previous_alarm_remaining = 0;
|
||||
auto uptime = TimeManagement::the().uptime_ms();
|
||||
if (m_alarm_deadline && m_alarm_deadline > uptime) {
|
||||
previous_alarm_remaining = m_alarm_deadline - uptime;
|
||||
if (auto alarm_timer = move(m_alarm_timer)) {
|
||||
if (TimerQueue::the().cancel_timer(*alarm_timer)) {
|
||||
// The timer hasn't fired. Round up the remaining time (if any)
|
||||
timespec remaining;
|
||||
timespec_add(alarm_timer->remaining(), { 0, 1000000000 - 1 }, remaining);
|
||||
previous_alarm_remaining = remaining.tv_sec;
|
||||
}
|
||||
if (!seconds) {
|
||||
m_alarm_deadline = 0;
|
||||
return previous_alarm_remaining;
|
||||
// We had an existing alarm, must return a non-zero value here!
|
||||
if (previous_alarm_remaining == 0)
|
||||
previous_alarm_remaining = 1;
|
||||
}
|
||||
|
||||
if (seconds > 0) {
|
||||
auto deadline = TimeManagement::the().monotonic_time(); // TODO: should be using CLOCK_REALTIME
|
||||
timespec_add(deadline, { seconds, 0 }, deadline);
|
||||
m_alarm_timer = TimerQueue::the().add_timer_without_id(deadline, [this]() {
|
||||
(void)send_signal(SIGALRM, nullptr);
|
||||
});
|
||||
}
|
||||
m_alarm_deadline = uptime + seconds * 1000;
|
||||
return previous_alarm_remaining;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,13 @@ namespace Kernel {
|
||||
static AK::Singleton<TimerQueue> s_the;
|
||||
static SpinLock<u8> g_timerqueue_lock;
|
||||
|
||||
timespec Timer::remaining() const
|
||||
{
|
||||
if (m_remaining == 0)
|
||||
return {};
|
||||
return TimerQueue::the().ticks_to_time(m_remaining);
|
||||
}
|
||||
|
||||
TimerQueue& TimerQueue::the()
|
||||
{
|
||||
return *s_the;
|
||||
@ -164,14 +171,7 @@ bool TimerQueue::cancel_timer(TimerId id)
|
||||
}
|
||||
|
||||
ASSERT(found_timer);
|
||||
bool was_next_timer = (m_timer_queue.head() == found_timer);
|
||||
|
||||
m_timer_queue.remove(found_timer);
|
||||
found_timer->set_queued(false);
|
||||
|
||||
if (was_next_timer)
|
||||
update_next_timer_due();
|
||||
|
||||
remove_timer_locked(*found_timer);
|
||||
lock.unlock();
|
||||
found_timer->unref();
|
||||
return true;
|
||||
@ -199,13 +199,21 @@ bool TimerQueue::cancel_timer(Timer& timer)
|
||||
return false;
|
||||
}
|
||||
|
||||
remove_timer_locked(timer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimerQueue::remove_timer_locked(Timer& timer)
|
||||
{
|
||||
bool was_next_timer = (m_timer_queue.head() == &timer);
|
||||
m_timer_queue.remove(&timer);
|
||||
timer.set_queued(false);
|
||||
auto now = TimeManagement::the().monotonic_ticks();
|
||||
if (timer.m_expires > now)
|
||||
timer.m_remaining = timer.m_expires - now;
|
||||
|
||||
if (was_next_timer)
|
||||
update_next_timer_due();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimerQueue::fire()
|
||||
|
@ -53,9 +53,12 @@ public:
|
||||
ASSERT(!is_queued());
|
||||
}
|
||||
|
||||
timespec remaining() const;
|
||||
|
||||
private:
|
||||
TimerId m_id;
|
||||
u64 m_expires;
|
||||
u64 m_remaining { 0 };
|
||||
Function<void()> m_callback;
|
||||
Timer* m_next { nullptr };
|
||||
Timer* m_prev { nullptr };
|
||||
@ -88,6 +91,7 @@ public:
|
||||
RefPtr<Timer> add_timer_without_id(const timespec& timeout, Function<void()>&& callback);
|
||||
TimerId add_timer(timeval& timeout, Function<void()>&& callback);
|
||||
bool cancel_timer(TimerId id);
|
||||
bool cancel_timer(Timer&);
|
||||
bool cancel_timer(NonnullRefPtr<Timer>&& timer)
|
||||
{
|
||||
return cancel_timer(timer.leak_ref());
|
||||
@ -95,7 +99,7 @@ public:
|
||||
void fire();
|
||||
|
||||
private:
|
||||
bool cancel_timer(Timer&);
|
||||
void remove_timer_locked(Timer&);
|
||||
void update_next_timer_due();
|
||||
void add_timer_locked(NonnullRefPtr<Timer>);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user