2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/Log.h"
4#include "pedigree/kernel/machine/Machine.h"
5#include "pedigree/kernel/machine/Timer.h"
6#include "pedigree/kernel/process/ConditionVariable.h"
7#include "pedigree/kernel/process/Mutex.h"
8#include "pedigree/kernel/process/Thread.h"
9#include "pedigree/kernel/processor/Processor.h"
10#include "pedigree/kernel/processor/ProcessorInformation.h"
11#include "pedigree/kernel/syscallError.h"
12#include "pedigree/kernel/time/Time.h"
17#include "PosixSubsystem.h"
18#include "clock-syscalls.h"
19#include "linux-wait-abi.h"
20#include "mqueue-syscalls.h"
21#include "posix-timer-syscalls.h"
22#include "pthread-syscalls.h"
23#include "system-syscalls.h"
24#include "timerfd-syscalls.h"
25#include "user-namespace.h"
32constexpr Time::Timestamp MaximumLinuxSleepNanoseconds = 0x7FFFFFFFFFFFFFFFULL;
35uint64_t clockChangeGeneration = 0;
37bool supportedSleepClock(clockid_t clockId) {
38 return clockId == CLOCK_REALTIME || clockId == CLOCK_MONOTONIC;
41bool supportedReadClock(clockid_t clockId) {
42 return supportedSleepClock(clockId) || clockId == CLOCK_MONOTONIC_RAW;
45Time::Timestamp sleepClockNanoseconds(clockid_t clockId) {
46 return clockId == CLOCK_REALTIME ? Time::getTimeNanoseconds() : Time::getTicks();
49bool validTimespec(int64_t seconds, int64_t nanoseconds) {
50 return seconds >= 0 && nanoseconds >= 0 && nanoseconds < 1000000000;
53Time::Timestamp timespecToNanoseconds(int64_t secondsValue, int64_t nanosecondsValue) {
54 const Time::Timestamp seconds =
static_cast<Time::Timestamp
>(secondsValue);
55 const Time::Timestamp nanoseconds =
static_cast<Time::Timestamp
>(nanosecondsValue);
56 if (seconds > (MaximumLinuxSleepNanoseconds - nanoseconds) / Time::Multiplier::Second) {
57 return MaximumLinuxSleepNanoseconds;
60 const Time::Timestamp wholeSeconds = seconds * Time::Multiplier::Second;
61 return wholeSeconds + nanoseconds;
64Time::Timestamp nanosleepAlarmDuration(Time::Timestamp requested) {
65 const Time::Timestamp remainder = requested % Time::Multiplier::Microsecond;
72 return requested + (Time::Multiplier::Microsecond - remainder);
75bool waitForRealtimeSleep(Time::Timestamp deadline) {
78 const Time::Timestamp now = Time::getTimeNanoseconds();
79 if (now >= deadline) {
82 Time::Timestamp duration = nanosleepAlarmDuration(deadline - now);
83 ConditionVariable::Error error = ConditionVariable::NoError;
84 if (clockChanged.
wait(clockChangeLock, duration, error) ||
85 error == ConditionVariable::TimedOut) {
89 thread->clearInterruption();
90 return Time::getTimeNanoseconds() >= deadline;
94bool waitForClockSleep(clockid_t clockId,
bool absolute, Time::Timestamp requested,
95 Time::Timestamp& remaining) {
97 if (absolute && clockId == CLOCK_REALTIME) {
98 return waitForRealtimeSleep(requested);
100 const Time::Timestamp monotonicStart = Time::getTicks();
103 Time::Timestamp duration = requested;
105 const Time::Timestamp now = sleepClockNanoseconds(clockId);
106 if (now >= requested) {
109 duration = requested - now;
110 }
else if (!duration) {
114 const bool completed = Time::delay(nanosleepAlarmDuration(duration));
117 if (!absolute || sleepClockNanoseconds(clockId) >= requested) {
126 if (thread->getInterruptionReason() != Thread::InterruptedBySignal) {
131 const bool deadlineReached = sleepClockNanoseconds(clockId) >= requested;
132 thread->clearInterruption();
133 return deadlineReached;
136 const Time::Timestamp elapsed = Time::getTicks() - monotonicStart;
137 thread->clearInterruption();
138 if (elapsed >= requested) {
142 remaining = requested - elapsed;
150 return {clockChangeGeneration, Time::getTimeNanoseconds(), Time::getTicks()};
153uint64_t posix_clock_change_generation() {
155 return clockChangeGeneration;
158bool posix_clock_step(int64_t nanoseconds) {
162 const Time::Timestamp now = Time::getTimeNanoseconds();
163 const uint64_t magnitude = nanoseconds < 0 ? 0 -
static_cast<uint64_t
>(nanoseconds)
164 : static_cast<uint64_t>(nanoseconds);
165 if (now > MaximumLinuxSleepNanoseconds ||
166 (nanoseconds < 0 ? magnitude > now : magnitude > MaximumLinuxSleepNanoseconds - now)) {
169 const Time::Timestamp target = nanoseconds < 0 ? now - magnitude : now + magnitude;
170 if (!Time::setTimeNanoseconds(target)) {
173 generation = ++clockChangeGeneration;
176 posix_futex_clock_changed();
177 posix_mqueue_clock_changed();
178 posix_timerfd_clock_changed(generation);
179 posix_timer_clock_changed();
183#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
184extern "C" EXPORTED_PUBLIC Time::Timestamp posixNanosleepAlarmDurationForTest(time_t seconds,
186 const struct timespec requested = {seconds, nanoseconds};
187 return nanosleepAlarmDuration(timespecToNanoseconds(requested.tv_sec, requested.tv_nsec));
191int posix_nanosleep(
const struct timespec* rqtp,
struct timespec* rmtp,
bool time32) {
192 struct timespec requested = {};
197 requested.tv_sec = source.tv_sec;
198 requested.tv_nsec = source.tv_nsec;
203 SG_NOTICE(
"nanosleep -> invalid address");
204 SYSCALL_ERROR(BadAddress);
207 if (!validTimespec(requested.tv_sec, requested.tv_nsec)) {
208 SYSCALL_ERROR(InvalidArgument);
212 SG_NOTICE(
"nanosleep(" <<
Dec << requested.tv_sec <<
":" << requested.tv_nsec <<
Hex <<
") - "
213 << Machine::instance().getTimer()->getTickCount() <<
".");
215 const Time::Timestamp duration = timespecToNanoseconds(requested.tv_sec, requested.tv_nsec);
216 Time::Timestamp remaining = 0;
217 if (waitForClockSleep(CLOCK_MONOTONIC,
false, duration, remaining)) {
221 const struct timespec result = {
static_cast<time_t
>(remaining / Time::Multiplier::Second),
222 static_cast<long>(remaining % Time::Multiplier::Second)};
226 static_cast<int32_t
>(result.tv_nsec)};
232 SYSCALL_ERROR(BadAddress);
237 SYSCALL_ERROR(Interrupted);
241int posix_clock_gettime(clockid_t clock_id,
struct timespec* tp) {
242 SG_NOTICE(
"clock_gettime(" <<
Dec << clock_id <<
Hex <<
")");
243 Time::Timestamp nanoseconds = 0;
246 nanoseconds = Time::getTimeNanoseconds();
248 case CLOCK_MONOTONIC:
249 case CLOCK_MONOTONIC_RAW:
251 nanoseconds = Time::getTicks();
254 SYSCALL_ERROR(InvalidArgument);
258 const struct timespec result = {
static_cast<time_t
>(nanoseconds / Time::Multiplier::Second),
259 static_cast<long>(nanoseconds % Time::Multiplier::Second)};
261 SYSCALL_ERROR(BadAddress);
269 if (clockId != CLOCK_REALTIME) {
270 SYSCALL_ERROR(InvalidArgument);
275 SYSCALL_ERROR(BadAddress);
278 if (!validTimespec(requested.tv_sec, requested.tv_nsec) ||
279 static_cast<uint64_t
>(requested.tv_sec) >
280 (MaximumLinuxSleepNanoseconds - requested.tv_nsec) / Time::Multiplier::Second) {
281 SYSCALL_ERROR(InvalidArgument);
285 if (!posix_global_capable(PosixCapabilities::SysTime)) {
286 SYSCALL_ERROR(NotEnoughPermissions);
289 const Time::Timestamp target =
290 static_cast<uint64_t
>(requested.tv_sec) * Time::Multiplier::Second + requested.tv_nsec;
294 if (!Time::setTimeNanoseconds(target)) {
295 SYSCALL_ERROR(InvalidArgument);
298 generation = ++clockChangeGeneration;
301 posix_futex_clock_changed();
302 posix_mqueue_clock_changed();
303 posix_timerfd_clock_changed(generation);
304 posix_timer_clock_changed();
308int posix_clock_getres_native(clockid_t clock_id,
struct timespec* resolution) {
309 if (!supportedReadClock(clock_id)) {
310 SYSCALL_ERROR(InvalidArgument);
318 const struct timespec result = {0, 1};
320 SYSCALL_ERROR(BadAddress);
328 if (!supportedReadClock(clock_id)) {
329 SYSCALL_ERROR(InvalidArgument);
339 SYSCALL_ERROR(BadAddress);
346int posix_clock_nanosleep(clockid_t clock_id,
int flags,
const LinuxKernelTimespec* request,
348 if (!supportedSleepClock(clock_id)) {
349 SYSCALL_ERROR(InvalidArgument);
355 SYSCALL_ERROR(BadAddress);
358 if (!validTimespec(requested.tv_sec, requested.tv_nsec)) {
359 SYSCALL_ERROR(InvalidArgument);
363 const bool absolute = flags & TIMER_ABSTIME;
364 const Time::Timestamp requestedNanoseconds =
365 timespecToNanoseconds(requested.tv_sec, requested.tv_nsec);
366 Time::Timestamp remainingNanoseconds = 0;
367 if (waitForClockSleep(clock_id, absolute, requestedNanoseconds, remainingNanoseconds)) {
371 if (!absolute && remainder) {
373 static_cast<int64_t
>(remainingNanoseconds / Time::Multiplier::Second),
374 static_cast<int64_t
>(remainingNanoseconds % Time::Multiplier::Second)};
376 SYSCALL_ERROR(BadAddress);
381 SYSCALL_ERROR(Interrupted);
MUST_USE_RESULT bool wait(Mutex &mutex, Time::Timestamp &timeout, Error &error, WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
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)
static ProcessorInformation & information()