1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:07:35 +00:00

Kernel: Add CLOCK_REALTIME support to the TimerQueue

This allows us to use blocking timeouts with either monotonic or
real time for all blockers. Which means that clock_nanosleep()
now also supports CLOCK_REALTIME.

Also, switch alarm() to use CLOCK_REALTIME as per specification.
This commit is contained in:
Tom 2020-12-01 16:53:47 -07:00 committed by Andreas Kling
parent 4c1e27ec65
commit 12cf6f8650
9 changed files with 182 additions and 97 deletions

View file

@ -43,8 +43,9 @@ class Timer : public RefCounted<Timer>
friend class InlineLinkedListNode<Timer>;
public:
Timer(u64 expires, Function<void()>&& callback)
: m_expires(expires)
Timer(clockid_t clock_id, u64 expires, Function<void()>&& callback)
: m_clock_id(clock_id)
, m_expires(expires)
, m_callback(move(callback))
{
}
@ -57,6 +58,7 @@ public:
private:
TimerId m_id;
clockid_t m_clock_id;
u64 m_expires;
u64 m_remaining { 0 };
Function<void()> m_callback;
@ -78,6 +80,7 @@ private:
}
bool is_queued() const { return m_queued.load(AK::MemoryOrder::memory_order_relaxed); }
void set_queued(bool queued) { m_queued.store(queued, AK::MemoryOrder::memory_order_relaxed); }
u64 now() const;
};
class TimerQueue {
@ -88,8 +91,8 @@ public:
static TimerQueue& the();
TimerId add_timer(NonnullRefPtr<Timer>&&);
RefPtr<Timer> add_timer_without_id(const timespec& timeout, Function<void()>&& callback);
TimerId add_timer(timeval& timeout, Function<void()>&& callback);
RefPtr<Timer> add_timer_without_id(clockid_t, const timespec&, Function<void()>&&);
TimerId add_timer(clockid_t, timeval& timeout, Function<void()>&& callback);
bool cancel_timer(TimerId id);
bool cancel_timer(Timer&);
bool cancel_timer(NonnullRefPtr<Timer>&& timer)
@ -99,17 +102,33 @@ public:
void fire();
private:
void remove_timer_locked(Timer&);
void update_next_timer_due();
struct Queue {
InlineLinkedList<Timer> list;
u64 next_timer_due { 0 };
};
void remove_timer_locked(Queue&, Timer&);
void update_next_timer_due(Queue&);
void add_timer_locked(NonnullRefPtr<Timer>);
timespec ticks_to_time(u64 ticks) const;
u64 time_to_ticks(const timespec&) const;
Queue& queue_for_timer(Timer& timer)
{
switch (timer.m_clock_id) {
case CLOCK_MONOTONIC:
return m_timer_queue_monotonic;
case CLOCK_REALTIME:
return m_timer_queue_realtime;
default:
ASSERT_NOT_REACHED();
}
}
timespec ticks_to_time(clockid_t, u64 ticks) const;
u64 time_to_ticks(clockid_t, const timespec&) const;
u64 m_next_timer_due { 0 };
u64 m_timer_id_count { 0 };
u64 m_ticks_per_second { 0 };
InlineLinkedList<Timer> m_timer_queue;
Queue m_timer_queue_monotonic;
Queue m_timer_queue_realtime;
InlineLinkedList<Timer> m_timers_executing;
};