8#include "pedigree/kernel/LockGuard.h"
9#include "pedigree/kernel/machine/Machine.h"
10#include "pedigree/kernel/machine/Timer.h"
11#include "pedigree/kernel/machine/TimerHandler.h"
12#include "pedigree/kernel/panic.h"
13#include "pedigree/kernel/process/Mutex.h"
14#include "pedigree/kernel/process/Process.h"
15#include "pedigree/kernel/process/Scheduler.h"
16#include "pedigree/kernel/process/TerminationDeferral.h"
17#include "pedigree/kernel/process/Thread.h"
18#include "pedigree/kernel/processor/Processor.h"
19#include "pedigree/kernel/processor/ProcessorInformation.h"
20#include "pedigree/kernel/syscallError.h"
21#include "pedigree/kernel/utilities/SharedPointer.h"
23#include "PosixSubsystem.h"
24#include "posix-timer-state.h"
25#include "posix-timer-syscalls.h"
26#include "queued-signal.h"
29constexpr size_t MaximumTimers = 256;
30constexpr size_t MaximumProcessTimers = 64;
31constexpr unsigned MaximumGeneration = 0x7fffff;
32constexpr int ClockRealtime = 0, ClockMonotonic = 1, Absolute = 1;
33constexpr int Signal = 0, None = 1, ThreadId = 4;
40static_assert(
sizeof(EventPrefix) == 16,
"Linux sigevent prefix ABI");
47 int clock = ClockRealtime;
48 EventPrefix
event = {};
55 ~Registry()
override {
56 if (source && !source->unregisterHandler(
this))
57 panic(
"POSIX timer callback could not be drained");
63 Entry& entry = entries[
static_cast<unsigned>(id) % MaximumTimers];
69 void advance(Entry& entry, Time::Timestamp now) {
70 const uint64_t expired = PosixTimerState::advance(entry.state, now);
71 if (entry.event.notification == None || !entry.notification->addExpirations(expired))
77 (entry.target && (!process->
acquireThread(target, entry.target) ||
78 target->getTaskId() != entry.targetId)) ||
79 posix_signal_queue_timer(process.get(), target.get(), entry.event.signal, entry.event.value,
80 entry.notification) < 0)
81 entry.notification->queueFailed();
84 void remove(Entry& entry) {
85 posix_signal_cancel_timer(entry.owner, entry.notification);
89 void armNextLocked() {
90 if (!source || !source->supportsDeadlines())
92 const Time::Timestamp monotonic = Time::getTicks();
93 const Time::Timestamp realtime = Time::getTimeNanoseconds();
94 Time::Timestamp next = 0;
95 for (
const Entry& entry : entries) {
98 const Time::Timestamp deadline =
99 PosixTimerState::monotonicDeadline(entry.state, realtime, monotonic);
100 if (deadline && (!next || deadline < next))
103 if (!source->armHandler(
this, next))
104 panic(
"POSIX timer registry could not arm its callback");
107 void timer(uint64_t)
override {
113 if (source && source->supportsDeadlines())
115 else if (!lock.tryAcquire())
117 const Time::Timestamp monotonic = Time::getTicks();
118 const Time::Timestamp realtime = Time::getTimeNanoseconds();
119 for (Entry& entry : entries)
121 advance(entry, entry.state.realtime ? realtime : monotonic);
127 Timer* source =
nullptr;
128 Entry entries[MaximumTimers];
129 unsigned generations[MaximumTimers] = {};
135int posix_timer_create(
int clock,
const void* event,
int* timerId) {
136 if (clock != ClockRealtime && clock != ClockMonotonic) {
137 SYSCALL_ERROR(InvalidArgument);
140 EventPrefix requested = {0, 14, Signal};
141 int32_t targetId = 0;
146 SYSCALL_ERROR(BadAddress);
149 if (requested.notification == ThreadId &&
151 reinterpret_cast<const uint8_t*
>(event) +
sizeof(requested),
153 SYSCALL_ERROR(BadAddress);
157 if ((requested.notification != Signal && requested.notification != None &&
158 requested.notification != ThreadId) ||
159 (requested.notification != None && (requested.signal < 1 || requested.signal > 64))) {
160 SYSCALL_ERROR(InvalidArgument);
167 if (requested.notification == ThreadId &&
169 !process->acquireThreadByUserspaceId(target, targetId, process->pidNamespace().
get()) ||
171 SYSCALL_ERROR(InvalidArgument);
175 size_t freeSlot = MaximumTimers, owned = 0;
176 for (
size_t i = 0; i < MaximumTimers; ++i) {
177 if (!timers.entries[i].owner && freeSlot == MaximumTimers)
179 if (timers.entries[i].owner == process)
182 if (freeSlot == MaximumTimers || owned == MaximumProcessTimers) {
183 SYSCALL_ERROR(NoMoreProcesses);
186 if (!timers.source) {
188 if (!source || !source->registerHandler(&timers)) {
189 SYSCALL_ERROR(NoMoreProcesses);
192 timers.source = source;
196 if (!posix_signal_reserve_timer(process, notification))
198 unsigned generation = (timers.generations[freeSlot] + 1) & MaximumGeneration;
201 const int id = generation * MaximumTimers + freeSlot;
202 timers.generations[freeSlot] = generation;
203 notification->timerId = id;
205 posix_signal_cancel_timer(process, notification);
206 SYSCALL_ERROR(BadAddress);
210 Entry& entry = timers.entries[freeSlot];
213 entry.event = requested;
215 entry.event.value = id;
216 entry.target = target.get();
217 entry.targetId = target ? target->getTaskId() : 0;
218 entry.notification = notification;
219 entry.owner = process;
223int posix_timer_settime(
int timerId,
int flags,
const void* setting,
void* previous) {
224 if ((flags & ~Absolute) || !setting) {
225 SYSCALL_ERROR(InvalidArgument);
230 SYSCALL_ERROR(BadAddress);
233 Time::Timestamp value, interval;
234 if (!PosixTimerState::decode(requested.value, value) ||
235 !PosixTimerState::decode(requested.interval, interval)) {
236 SYSCALL_ERROR(InvalidArgument);
241 Entry* entry = timers.find(timerId);
243 SYSCALL_ERROR(InvalidArgument);
246 const Time::Timestamp oldNow =
247 entry->state.realtime ? Time::getTimeNanoseconds() : Time::getTicks();
248 timers.advance(*entry, oldNow);
252 timers.armNextLocked();
253 SYSCALL_ERROR(BadAddress);
258 posix_signal_reset_timer(entry->owner, entry->notification);
259 entry->state.realtime = (flags & Absolute) && entry->clock == ClockRealtime;
260 const Time::Timestamp now = entry->state.realtime ? Time::getTimeNanoseconds() : Time::getTicks();
261 entry->state.armed = value != 0;
262 entry->state.interval = value ? interval : 0;
263 entry->state.deadline = flags & Absolute ? value : PosixTimerState::add(now, value);
264 timers.advance(*entry, now);
265 timers.armNextLocked();
269int posix_timer_gettime(
int timerId,
void* setting) {
271 Entry* entry = timers.find(timerId);
273 SYSCALL_ERROR(InvalidArgument);
276 const Time::Timestamp now = entry->state.realtime ? Time::getTimeNanoseconds() : Time::getTicks();
277 timers.advance(*entry, now);
278 timers.armNextLocked();
281 SYSCALL_ERROR(BadAddress);
287int posix_timer_getoverrun(
int timerId) {
289 Entry* entry = timers.find(timerId);
291 SYSCALL_ERROR(InvalidArgument);
294 return entry->notification->getDeliveredOverrun();
297int posix_timer_delete(
int timerId) {
299 Entry* entry = timers.find(timerId);
301 SYSCALL_ERROR(InvalidArgument);
304 timers.remove(*entry);
305 timers.armNextLocked();
309void posix_timer_process_exit(
Process* process) {
313 for (Entry& entry : timers.entries)
314 if (entry.owner == process)
315 timers.remove(entry);
316 timers.armNextLocked();
319void posix_timer_thread_exit(
Thread* thread) {
323 for (Entry& entry : timers.entries)
324 if (entry.owner && entry.target == thread)
325 timers.remove(entry);
326 timers.armNextLocked();
329void posix_timer_clock_changed() {
331 timers.armNextLocked();
virtual Timer * getTimer()=0
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)
MUST_USE_RESULT bool acquireThread(ThreadLease &lease, size_t n)
static ProcessorInformation & information()
static bool inDeviceHardIrq()
static Scheduler & instance()
@ Continue
No unwind necessary, carry on as normal.
UnwindType getUnwindState()
virtual void timer(uint64_t delta)=0
void EXPORTED_PUBLIC panic(const char *msg) NORETURN