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
54// Advancing from the previous deadline preserves phase even after many missed
55// periods. The remainder avoids overflowing a period-count multiplication.
56inline uint64_t advance(State& state, Time::Timestamp now) {
57 if (!state.armed || now < state.deadline)
58 return 0;
59 if (!state.interval) {
60 state.armed = false;
61 return 1;
62 }
63 const uint64_t elapsed = now - state.deadline;
64 const uint64_t expirations = elapsed / state.interval + 1;
65 const uint64_t remaining = state.interval - elapsed % state.interval;
66 state.deadline = add(now, remaining);
67 state.armed = state.deadline > now;
68 return expirations;
69}
70
71inline Setting snapshot(const State& state, Time::Timestamp now) {
72 return {encode(state.interval),
73 encode(state.armed && state.deadline > now ? state.deadline - now : 0)};
74}
75} // namespace PosixTimerState
76
77#endif