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

Kernel: Make CLOCK_MONOTONIC respect the system tick frequency

The time returned by sys$clock_gettime() was not aligned with the delay
calculations in sys$clock_nanosleep(). This patch fixes that by taking
the system's ticks_per_second value into account in both functions.

This patch also removes the need for Thread::sleep_until() and uses
Thread::sleep() for both absolute and relative sleeps.

This was causing the nesalizer emulator port to sleep for a negative
amount of time at the end of each frame, making it run way too fast.
This commit is contained in:
Andreas Kling 2020-11-22 17:20:58 +01:00
parent e07d14f4d9
commit 94ff04b536
3 changed files with 18 additions and 27 deletions

View file

@ -37,10 +37,13 @@ int Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
timespec ts = {}; timespec ts = {};
switch (clock_id) { switch (clock_id) {
case CLOCK_MONOTONIC: case CLOCK_MONOTONIC: {
ts.tv_sec = TimeManagement::the().seconds_since_boot(); auto ticks_per_second = TimeManagement::the().ticks_per_second();
ts.tv_nsec = TimeManagement::the().ticks_this_second() * 1000000; auto uptime = g_uptime;
ts.tv_sec = uptime / ticks_per_second;
ts.tv_nsec = (1000000000 * (uptime % ticks_per_second)) / ticks_per_second;
break; break;
}
case CLOCK_REALTIME: case CLOCK_REALTIME:
ts = TimeManagement::the().epoch_time(); ts = TimeManagement::the().epoch_time();
break; break;
@ -88,26 +91,24 @@ int Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_par
bool is_absolute = params.flags & TIMER_ABSTIME; bool is_absolute = params.flags & TIMER_ABSTIME;
auto ticks_per_second = TimeManagement::the().ticks_per_second();
switch (params.clock_id) { switch (params.clock_id) {
case CLOCK_MONOTONIC: { case CLOCK_MONOTONIC: {
u64 wakeup_time; u64 ticks_to_sleep = requested_sleep.tv_sec * ticks_per_second;
if (is_absolute) { ticks_to_sleep += (requested_sleep.tv_nsec * ticks_per_second) / 1000000000;
u64 time_to_wake = (requested_sleep.tv_sec * 1000 + requested_sleep.tv_nsec / 1000000); if (is_absolute)
wakeup_time = Thread::current()->sleep_until(time_to_wake); ticks_to_sleep -= g_uptime;
} else { if (!ticks_to_sleep)
u64 ticks_to_sleep = requested_sleep.tv_sec * TimeManagement::the().ticks_per_second(); return 0;
ticks_to_sleep += requested_sleep.tv_nsec * TimeManagement::the().ticks_per_second() / 1000000000; u64 wakeup_time = Thread::current()->sleep(ticks_to_sleep);
if (!ticks_to_sleep)
return 0;
wakeup_time = Thread::current()->sleep(ticks_to_sleep);
}
if (wakeup_time > g_uptime) { if (wakeup_time > g_uptime) {
u64 ticks_left = wakeup_time - g_uptime; u64 ticks_left = wakeup_time - g_uptime;
if (!is_absolute && params.remaining_sleep) { if (!is_absolute && params.remaining_sleep) {
timespec remaining_sleep = {}; timespec remaining_sleep = {};
remaining_sleep.tv_sec = ticks_left / TimeManagement::the().ticks_per_second(); remaining_sleep.tv_sec = ticks_left / ticks_per_second;
ticks_left -= remaining_sleep.tv_sec * TimeManagement::the().ticks_per_second(); ticks_left -= remaining_sleep.tv_sec * ticks_per_second;
remaining_sleep.tv_nsec = ticks_left * 1000000000 / TimeManagement::the().ticks_per_second(); remaining_sleep.tv_nsec = (ticks_left * 1000000000) / ticks_per_second;
if (!copy_to_user(params.remaining_sleep, &remaining_sleep)) if (!copy_to_user(params.remaining_sleep, &remaining_sleep))
return -EFAULT; return -EFAULT;
} }

View file

@ -258,15 +258,6 @@ u64 Thread::sleep(u64 ticks)
return wakeup_time; return wakeup_time;
} }
u64 Thread::sleep_until(u64 wakeup_time)
{
ASSERT(state() == Thread::Running);
auto ret = Thread::current()->block<Thread::SleepBlocker>(nullptr, wakeup_time);
if (wakeup_time > g_uptime)
ASSERT(ret.was_interrupted());
return wakeup_time;
}
const char* Thread::state_string() const const char* Thread::state_string() const
{ {
switch (state()) { switch (state()) {

View file

@ -377,7 +377,6 @@ public:
size_t thread_specific_region_size() const { return m_thread_specific_region_size; } size_t thread_specific_region_size() const { return m_thread_specific_region_size; }
u64 sleep(u64 ticks); u64 sleep(u64 ticks);
u64 sleep_until(u64 wakeup_time);
class BlockResult { class BlockResult {
public: public: