The Pedigree Project 0.1
posix-timer-state.h
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#ifndef POSIX_TIMER_STATE_H
9#define POSIX_TIMER_STATE_H
10
11#include "pedigree/kernel/time/Time.h"
12
13namespace PosixTimerState {
14constexpr Time::Timestamp MaximumTime = Time::Infinity - 1;
15
16struct Timespec {
17 int64_t seconds;
18 int64_t nanoseconds;
19};
20
21struct Setting {
22 Timespec interval;
23 Timespec value;
24};
25static_assert(sizeof(Setting) == 32, "Linux amd64 itimerspec ABI");
26
27struct State {
28 Time::Timestamp deadline = 0;
29 Time::Timestamp interval = 0;
30 bool armed = false;
31 bool realtime = false;
32};
33
34inline bool decode(const Timespec& source, Time::Timestamp& result) {
35 if (source.seconds < 0 || source.nanoseconds < 0 ||
36 source.nanoseconds >= static_cast<int64_t>(Time::Multiplier::Second))
37 return false;
38 const uint64_t seconds = source.seconds;
39 result = seconds > (MaximumTime - source.nanoseconds) / Time::Multiplier::Second
40 ? MaximumTime
41 : seconds * Time::Multiplier::Second + source.nanoseconds;
42 return true;
43}
44
45inline Timespec encode(Time::Timestamp value) {
46 return {static_cast<int64_t>(value / Time::Multiplier::Second),
47 static_cast<int64_t>(value % Time::Multiplier::Second)};
48}
49
50inline Time::Timestamp add(Time::Timestamp start, Time::Timestamp duration) {
51 return start >= MaximumTime || duration > MaximumTime - start ? MaximumTime : start + duration;
52}
53
54inline Time::Timestamp monotonicDeadline(const State& state, Time::Timestamp realtime,
55 Time::Timestamp monotonic) {
56 if (!state.armed)
57 return 0;
58 if (!state.realtime)
59 return state.deadline;
60 return state.deadline <= realtime ? monotonic : add(monotonic, state.deadline - realtime);
61}
62
63// Advancing from the previous deadline preserves phase even after many missed
64// periods. The remainder avoids overflowing a period-count multiplication.
65inline uint64_t advance(State& state, Time::Timestamp now) {
66 if (!state.armed || now < state.deadline)
67 return 0;
68 if (!state.interval) {
69 state.armed = false;
70 return 1;
71 }
72 const uint64_t elapsed = now - state.deadline;
73 const uint64_t expirations = elapsed / state.interval + 1;
74 const uint64_t remaining = state.interval - elapsed % state.interval;
75 state.deadline = add(now, remaining);
76 state.armed = state.deadline > now;
77 return expirations;
78}
79
80inline Setting snapshot(const State& state, Time::Timestamp now) {
81 return {encode(state.interval),
82 encode(state.armed && state.deadline > now ? state.deadline - now : 0)};
83}
84} // namespace PosixTimerState
85
86#endif