2020-07-30 21:38:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-07-30 21:38:15 +00:00
|
|
|
*/
|
|
|
|
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
#include <AK/Time.h>
|
2020-07-30 21:38:15 +00:00
|
|
|
#include <Kernel/Process.h>
|
|
|
|
#include <Kernel/Time/TimeManagement.h>
|
|
|
|
|
|
|
|
namespace Kernel {
|
|
|
|
|
2021-06-28 18:59:35 +00:00
|
|
|
KResultOr<FlatPtr> Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
|
2020-07-30 21:38:15 +00:00
|
|
|
{
|
2021-07-18 18:20:12 +00:00
|
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
2020-07-30 21:38:15 +00:00
|
|
|
REQUIRE_PROMISE(stdio);
|
|
|
|
|
2021-05-05 16:51:06 +00:00
|
|
|
if (!TimeManagement::is_valid_clock_id(clock_id))
|
|
|
|
return EINVAL;
|
2020-07-30 21:38:15 +00:00
|
|
|
|
2021-05-05 16:51:06 +00:00
|
|
|
auto ts = TimeManagement::the().current_time(clock_id).to_timespec();
|
2021-02-27 22:56:16 +00:00
|
|
|
if (!copy_to_user(user_ts, &ts))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
2021-05-05 16:51:06 +00:00
|
|
|
|
2020-07-30 21:38:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-28 18:59:35 +00:00
|
|
|
KResultOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts)
|
2020-07-30 21:38:15 +00:00
|
|
|
{
|
2021-07-18 18:20:12 +00:00
|
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
2020-07-30 21:38:15 +00:00
|
|
|
REQUIRE_PROMISE(settime);
|
|
|
|
|
|
|
|
if (!is_superuser())
|
2021-03-01 12:49:16 +00:00
|
|
|
return EPERM;
|
2020-07-30 21:38:15 +00:00
|
|
|
|
2021-02-21 19:28:20 +00:00
|
|
|
auto ts = copy_time_from_user(user_ts);
|
|
|
|
if (!ts.has_value())
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
2020-07-30 21:38:15 +00:00
|
|
|
|
|
|
|
switch (clock_id) {
|
|
|
|
case CLOCK_REALTIME:
|
2021-02-27 22:56:16 +00:00
|
|
|
TimeManagement::the().set_epoch_time(ts.value());
|
2020-07-30 21:38:15 +00:00
|
|
|
break;
|
|
|
|
default:
|
2021-03-01 12:49:16 +00:00
|
|
|
return EINVAL;
|
2020-07-30 21:38:15 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-28 18:59:35 +00:00
|
|
|
KResultOr<FlatPtr> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_params*> user_params)
|
2020-07-30 21:38:15 +00:00
|
|
|
{
|
2021-07-18 18:20:12 +00:00
|
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
2020-07-30 21:38:15 +00:00
|
|
|
REQUIRE_PROMISE(stdio);
|
|
|
|
|
|
|
|
Syscall::SC_clock_nanosleep_params params;
|
2020-09-12 03:11:07 +00:00
|
|
|
if (!copy_from_user(¶ms, user_params))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
2020-07-30 21:38:15 +00:00
|
|
|
|
2021-02-21 19:28:20 +00:00
|
|
|
Optional<Time> requested_sleep = copy_time_from_user(params.requested_sleep);
|
|
|
|
if (!requested_sleep.has_value())
|
2021-03-15 08:04:04 +00:00
|
|
|
return EFAULT;
|
2020-07-30 21:38:15 +00:00
|
|
|
|
2021-02-12 17:49:16 +00:00
|
|
|
bool is_absolute;
|
|
|
|
switch (params.flags) {
|
|
|
|
case 0:
|
|
|
|
is_absolute = false;
|
|
|
|
break;
|
|
|
|
case TIMER_ABSTIME:
|
|
|
|
is_absolute = true;
|
|
|
|
break;
|
|
|
|
default:
|
2021-03-01 12:49:16 +00:00
|
|
|
return EINVAL;
|
2021-02-12 17:49:16 +00:00
|
|
|
}
|
2020-07-30 21:38:15 +00:00
|
|
|
|
2020-12-04 05:12:50 +00:00
|
|
|
if (!TimeManagement::is_valid_clock_id(params.clock_id))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EINVAL;
|
2020-12-04 05:12:50 +00:00
|
|
|
|
|
|
|
bool was_interrupted;
|
|
|
|
if (is_absolute) {
|
2021-02-27 22:56:16 +00:00
|
|
|
was_interrupted = Thread::current()->sleep_until(params.clock_id, requested_sleep.value()).was_interrupted();
|
2020-12-04 05:12:50 +00:00
|
|
|
} else {
|
2021-02-27 22:56:16 +00:00
|
|
|
Time remaining_sleep;
|
|
|
|
was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep.value(), &remaining_sleep).was_interrupted();
|
|
|
|
timespec remaining_sleep_ts = remaining_sleep.to_timespec();
|
|
|
|
if (was_interrupted && params.remaining_sleep && !copy_to_user(params.remaining_sleep, &remaining_sleep_ts))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
2020-07-30 21:38:15 +00:00
|
|
|
}
|
2020-12-04 05:12:50 +00:00
|
|
|
if (was_interrupted)
|
2021-03-01 12:49:16 +00:00
|
|
|
return EINTR;
|
2020-12-04 05:12:50 +00:00
|
|
|
return 0;
|
2020-07-30 21:38:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-28 18:59:35 +00:00
|
|
|
KResultOr<FlatPtr> Process::sys$adjtime(Userspace<const timeval*> user_delta, Userspace<timeval*> user_old_delta)
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
{
|
2021-07-18 18:20:12 +00:00
|
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
if (user_old_delta) {
|
|
|
|
timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment();
|
|
|
|
timeval old_delta;
|
|
|
|
timespec_to_timeval(old_delta_ts, old_delta);
|
|
|
|
if (!copy_to_user(user_old_delta, &old_delta))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (user_delta) {
|
|
|
|
REQUIRE_PROMISE(settime);
|
|
|
|
if (!is_superuser())
|
2021-03-01 12:49:16 +00:00
|
|
|
return EPERM;
|
2021-02-21 19:28:20 +00:00
|
|
|
auto delta = copy_time_from_user(user_delta);
|
|
|
|
if (!delta.has_value())
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
|
2021-02-21 19:28:20 +00:00
|
|
|
// FIXME: Should use AK::Time internally
|
|
|
|
TimeManagement::the().set_remaining_epoch_time_adjustment(delta->to_timespec());
|
Kernel+LibC: Add adjtime(2)
Most systems (Linux, OpenBSD) adjust 0.5 ms per second, or 0.5 us per
1 ms tick. That is, the clock is sped up or slowed down by at most
0.05%. This means adjusting the clock by 1 s takes 2000 s, and the
clock an be adjusted by at most 1.8 s per hour.
FreeBSD adjusts 5 ms per second if the remaining time adjustment is
>= 1 s (0.5%) , else it adjusts by 0.5 ms as well. This allows adjusting
by (almost) 18 s per hour.
Since Serenity OS can lose more than 22 s per hour (#3429), this
picks an adjustment rate up to 1% for now. This allows us to
adjust up to 36s per hour, which should be sufficient to adjust
the clock fast enough to keep up with how much time the clock
currently loses. Once we have a fancier NTP implementation that can
adjust tick rate in addition to offset, we can think about reducing
this.
adjtime is a bit old-school and most current POSIX-y OSs instead
implement adjtimex/ntp_adjtime, but a) we have to start somewhere
b) ntp_adjtime() is a fairly gnarly API. OpenBSD's adjfreq looks
like it might provide similar functionality with a nicer API. But
before worrying about all this, it's probably a good idea to get
to a place where the kernel APIs are (barely) good enough so that
we can write an ntp service, and once we have that we should write
a way to automatically evaluate how well it keeps the time adjusted,
and only then should we add improvements ot the adjustment mechanism.
2020-11-05 21:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-28 18:59:35 +00:00
|
|
|
KResultOr<FlatPtr> Process::sys$gettimeofday(Userspace<timeval*> user_tv)
|
2020-07-30 21:38:15 +00:00
|
|
|
{
|
2021-07-18 18:20:12 +00:00
|
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
2020-07-30 21:38:15 +00:00
|
|
|
REQUIRE_PROMISE(stdio);
|
2021-02-28 01:18:48 +00:00
|
|
|
auto tv = kgettimeofday().to_timeval();
|
2020-09-12 03:11:07 +00:00
|
|
|
if (!copy_to_user(user_tv, &tv))
|
2021-03-01 12:49:16 +00:00
|
|
|
return EFAULT;
|
2020-07-30 21:38:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|