Parcourir la source

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.
Andreas Kling il y a 4 ans
Parent
commit
94ff04b536
3 fichiers modifiés avec 18 ajouts et 27 suppressions
  1. 18 17
      Kernel/Syscalls/clock.cpp
  2. 0 9
      Kernel/Thread.cpp
  3. 0 1
      Kernel/Thread.h

+ 18 - 17
Kernel/Syscalls/clock.cpp

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

+ 0 - 9
Kernel/Thread.cpp

@@ -258,15 +258,6 @@ u64 Thread::sleep(u64 ticks)
     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
 {
     switch (state()) {

+ 0 - 1
Kernel/Thread.h

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