2#include "clock-adjust-syscalls.h"
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/process/Mutex.h"
5#include "pedigree/kernel/process/Process.h"
6#include "pedigree/kernel/process/Thread.h"
7#include "pedigree/kernel/processor/Processor.h"
8#include "pedigree/kernel/processor/ProcessorInformation.h"
9#include "pedigree/kernel/syscallError.h"
14#include "PosixSubsystem.h"
15#include "clock-syscalls.h"
16#include "user-namespace.h"
20 uint32_t modes, modesPadding;
21 int64_t offset, frequency, maximumError, estimatedError;
22 int32_t status, statusPadding;
23 int64_t constant, precision, tolerance;
24 int64_t seconds, fraction;
25 int64_t tick, ppsFrequency, jitter;
26 int32_t shift, shiftPadding;
27 int64_t stability, jitterCount, calibrationCount, errorCount, stabilityCount;
28 int32_t tai, padding[11];
30static_assert(
sizeof(LinuxTimex) == 208,
"Linux amd64 timex layout");
31static_assert(offsetof(LinuxTimex, offset) == 8,
"Linux timex offset field");
32static_assert(offsetof(LinuxTimex, status) == 40,
"Linux timex status field");
33static_assert(offsetof(LinuxTimex, seconds) == 72,
"Linux timex timeval field");
34static_assert(offsetof(LinuxTimex, tai) == 160,
"Linux timex TAI field");
36constexpr uint32_t AdjustSetOffset = 0x0100;
37constexpr uint32_t AdjustMicro = 0x1000;
38constexpr uint32_t AdjustNano = 0x2000;
39constexpr uint32_t AdjustSingleShot = 0x8001;
40constexpr uint32_t AdjustSingleShotRead = 0xA001;
41constexpr uint32_t KnownModes = 0xF1BF;
42constexpr uint32_t SupportedModes = AdjustSetOffset | AdjustMicro | AdjustNano;
43constexpr int32_t StatusUnsynchronized = 0x0040;
44constexpr int32_t StatusNano = 0x2000;
45constexpr int TimeError = 5;
46constexpr int64_t MaximumAdjustment = 0x7FFFFFFFFFFFFFFFLL;
49bool nanosecondUnits =
false;
51bool decodeAdjustment(
const LinuxTimex& value, int64_t& nanoseconds) {
52 const int64_t units = value.modes & AdjustNano ? 1000000000 : 1000000;
53 if (value.fraction < 0 || value.fraction >= units) {
56 const int64_t fraction = value.fraction * (1000000000 / units);
57 if (value.seconds >= 0) {
58 if (value.seconds > (MaximumAdjustment - fraction) / 1000000000) {
61 nanoseconds = value.seconds * 1000000000 + fraction;
66 const uint64_t seconds = 0 -
static_cast<uint64_t
>(value.seconds + 1);
67 const uint64_t tail = 1000000000 - fraction;
68 if (seconds > (
static_cast<uint64_t
>(MaximumAdjustment) - tail) / 1000000000) {
71 nanoseconds = -
static_cast<int64_t
>(seconds * 1000000000 + tail);
76int posix_clock_adjtime(
int clockId,
void* value) {
77 LinuxTimex requested = {};
79 SYSCALL_ERROR(BadAddress);
82 if (clockId != CLOCK_REALTIME) {
83 if (clockId == CLOCK_MONOTONIC) {
84 SYSCALL_ERROR(OperationNotSupported);
86 SYSCALL_ERROR(InvalidArgument);
90 const bool readOnly = requested.modes == 0 || requested.modes == AdjustSingleShotRead;
91 if (!readOnly && !posix_global_capable(PosixCapabilities::SysTime)) {
92 SYSCALL_ERROR(NotEnoughPermissions);
95 if ((requested.modes & ~KnownModes) ||
96 ((requested.modes & 0x8000) && requested.modes != AdjustSingleShot &&
97 requested.modes != AdjustSingleShotRead)) {
98 SYSCALL_ERROR(InvalidArgument);
101 if (!readOnly && (requested.modes & ~SupportedModes)) {
102 SYSCALL_ERROR(OperationNotSupported);
105 int64_t adjustment = 0;
106 if ((requested.modes & AdjustSetOffset) && !decodeAdjustment(requested, adjustment)) {
107 SYSCALL_ERROR(InvalidArgument);
111 LinuxTimex result = {};
114 if ((requested.modes & AdjustSetOffset) && !posix_clock_step(adjustment)) {
115 SYSCALL_ERROR(InvalidArgument);
119 if (requested.modes & AdjustNano)
120 nanosecondUnits =
true;
121 if (requested.modes & AdjustMicro)
122 nanosecondUnits =
false;
124 const Time::Timestamp now = Time::getTimeNanoseconds();
125 result.modes = requested.modes;
126 result.status = StatusUnsynchronized | (nanosecondUnits ? StatusNano : 0);
129 result.maximumError = result.estimatedError = MaximumAdjustment;
130 result.precision = 1;
131 result.seconds = now / Time::Multiplier::Second;
133 (now % Time::Multiplier::Second) / (nanosecondUnits ? 1 : Time::Multiplier::Microsecond);
136 SYSCALL_ERROR(BadAddress);
142int posix_adjtimex(
void* value) {
143 return posix_clock_adjtime(CLOCK_REALTIME, value);
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)