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:
parent
e07d14f4d9
commit
94ff04b536
3 changed files with 18 additions and 27 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue