PatchworkOS
Loading...
Searching...
No Matches
timer.c
Go to the documentation of this file.
1#include <kernel/cpu/cpu.h>
3#include <kernel/cpu/smp.h>
8#include <kernel/log/log.h>
10
11#include <kernel/log/panic.h>
12#include <kernel/sched/thread.h>
13
14#include <stdatomic.h>
15#include <stdbool.h>
16#include <stdint.h>
17#include <sys/math.h>
18
20static bool initialized = false;
21
22static atomic_int8_t accumulatorLock = ATOMIC_VAR_INIT(0);
24
25static void timer_acquire(void)
26{
27 // We cant use the lock_t here becouse in debug mode lock_t will use the timer to check for deadlocks.
30 {
31 asm volatile("pause");
32 }
33}
34
35static void timer_release(void)
36{
39}
40
50
52{
53 cpu_t* self = smp_self_unsafe();
56 lock_init(&ctx->lock);
57 for (uint32_t i = 0; i < TIMER_MAX_CALLBACK; i++)
58 {
59 ctx->callbacks[i] = NULL;
60 }
61 LOG_INFO("cpu%d apic timer ticksPerNs=%lu\n", self->id, self->timer.apicTicksPerNs);
62}
63
64static void timer_init(void)
65{
66 struct tm time;
67 rtc_read(&time);
69
70 initialized = true;
71}
72
85
87{
88 if (!initialized)
89 {
90 timer_init();
91 }
92
94}
95
97{
99
100 LOCK_SCOPE(&self->timer.lock);
102 for (uint32_t i = 0; i < TIMER_MAX_CALLBACK; i++)
103 {
104 if (self->timer.callbacks[i] != NULL)
105 {
106 self->timer.callbacks[i](frame, self);
107 }
108 }
109}
110
112{
113 if (ctx == NULL || callback == NULL)
114 {
115 return;
116 }
117
118 LOCK_SCOPE(&ctx->lock);
119 for (uint32_t i = 0; i < TIMER_MAX_CALLBACK; i++)
120 {
121 if (ctx->callbacks[i] == NULL)
122 {
123 LOG_DEBUG("timer callback subscribed %p in slot %d\n", callback, i);
124 ctx->callbacks[i] = callback;
125 return;
126 }
127 }
128
129 panic(NULL, "Failed to subscribe timer callback, no free slots available");
130}
131
133{
134 if (ctx == NULL || callback == NULL)
135 {
136 return;
137 }
138
139 LOCK_SCOPE(&ctx->lock);
140 for (uint32_t i = 0; i < TIMER_MAX_CALLBACK; i++)
141 {
142 if (ctx->callbacks[i] == callback)
143 {
144 LOG_DEBUG("timer callback unsubscribed %p from slot %d\n", callback, i);
145 ctx->callbacks[i] = NULL;
146 return;
147 }
148 }
149
150 panic(NULL, "Failed to unsubscribe timer callback, not found");
151}
152
154{
155 if (self == NULL || timeout == CLOCKS_NEVER)
156 {
157 return;
158 }
159
160 clock_t deadline = uptime + timeout;
161 if (deadline < self->timer.nextDeadline)
162 {
164 if (ticks > UINT32_MAX)
165 {
166 ticks = UINT32_MAX;
167 }
168 else if (ticks == 0)
169 {
170 ticks = 1;
171 }
172
173 self->timer.nextDeadline = deadline;
175 }
176}
177
182
184{
185 time_t epoch = timer_unix_epoch();
186 if (timePtr != NULL)
187 {
188 if (thread_copy_to_user(sched_thread(), timePtr, &epoch, sizeof(epoch)) == ERR)
189 {
190 return ERR;
191 }
192 }
193
194 return epoch;
195}
196
198{
200}
201
203{
204 asm volatile("int %0" : : "i"(INTERRUPT_TIMER));
205}
#define CLOCKS_NEVER
Definition clock_t.h:16
#define CLOCKS_PER_SEC
Definition clock_t.h:15
void interrupt_disable(void)
Disable interrupts and increment the disableDepth.
Definition interrupt.c:26
void interrupt_enable(void)
Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously en...
Definition interrupt.c:38
@ INTERRUPT_TIMER
The timer subsystem interrupt.
Definition interrupt.h:137
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
#define SYS_UPTIME
Definition syscalls.h:29
#define SYS_UNIX_EPOCH
Definition syscalls.h:30
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscalls.h:100
uint64_t apic_timer_ticks_per_ns(void)
Apic timer ticks per nanosecond.
Definition apic.c:119
void apic_timer_one_shot(interrupt_t vector, uint32_t ticks)
Configure the apic timer in one-shot mode.
Definition apic.c:105
#define APIC_TIMER_TICKS_FIXED_POINT_OFFSET
APIC Timer Ticks Fixed Point Offset.
Definition apic.h:176
void lapic_send_ipi(lapic_id_t id, interrupt_t vector)
Send an Inter-Processor Interrupt (IPI) to a local apic.
Definition apic.c:225
clock_t hpet_nanoseconds_per_tick(void)
Retrieve the number of nanoseconds per HPET tick.
Definition hpet.c:57
void hpet_reset_counter(void)
Reset the HPET main counter to 0 and enable the HPET.
Definition hpet.c:75
uint64_t hpet_read_counter(void)
Read the current value of the HPET main counter.
Definition hpet.c:66
void rtc_read(struct tm *time)
Reads the current time from the RTC.
Definition rtc.c:15
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define LOG_INFO(format,...)
Definition log.h:87
#define LOG_DEBUG(format,...)
Definition log.h:81
uint64_t thread_copy_to_user(thread_t *thread, void *dest, const void *userSrc, uint64_t length)
Safely copy data to user space.
Definition thread.c:248
thread_t * sched_thread(void)
Retrieves the currently running thread.
Definition sched.c:157
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:80
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
void timer_interrupt_handler(interrupt_frame_t *frame, cpu_t *self)
Handle timer interrupt.
Definition timer.c:96
time_t timer_unix_epoch(void)
The unix epoch.
Definition timer.c:86
void(* timer_callback_t)(interrupt_frame_t *frame, cpu_t *self)
Timer callback function type.
Definition timer.h:29
void timer_notify_self(void)
Trigger timer interrupt on self.
Definition timer.c:202
#define TIMER_MAX_CALLBACK
Maximum amount of timer callbacks.
Definition timer.h:24
void timer_one_shot(cpu_t *self, clock_t uptime, clock_t timeout)
Schedule a one-shot timer interrupt.
Definition timer.c:153
void timer_unsubscribe(timer_ctx_t *ctx, timer_callback_t callback)
Unsubscribe from timer interrupts.
Definition timer.c:132
void timer_subscribe(timer_ctx_t *ctx, timer_callback_t callback)
Subscribe to timer interrupts.
Definition timer.c:111
void timer_notify(cpu_t *cpu)
Trigger timer interrupt on cpu.
Definition timer.c:197
clock_t timer_uptime(void)
Time since boot.
Definition timer.c:73
void timer_ctx_init(timer_ctx_t *ctx)
Initialize per-CPU timer context.
Definition timer.c:51
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
#define atomic_store(object, desired)
Definition stdatomic.h:289
#define atomic_compare_exchange_strong(object, expected, desired)
Definition stdatomic.h:278
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
#define UINT32_MAX
Definition stdint.h:70
__INT8_TYPE__ int8_t
Definition stdint.h:10
CPU structure.
Definition cpu.h:42
timer_ctx_t timer
Definition cpu.h:49
cpuid_t id
Definition cpu.h:43
lapic_id_t lapicId
Definition cpu.h:44
Trap Frame Structure.
Definition interrupt.h:42
Per-CPU system time context.
Definition timer.h:35
timer_callback_t callbacks[TIMER_MAX_CALLBACK]
The registered timer callbacks for the owner cpu.
Definition timer.h:49
clock_t nextDeadline
The next time the owner cpus apic timer will fire, specified in nanoseconds since boot,...
Definition timer.h:45
lock_t lock
Definition timer.h:50
uint64_t apicTicksPerNs
The amount of ticks in the owner cpus apic timer that occur every nanosecond, stored using fixed poin...
Definition timer.h:40
Definition time.h:21
_PUBLIC time_t time(time_t *timer)
Definition time.c:5
_PUBLIC time_t mktime(struct tm *timeptr)
Definition mktime.c:5
long long unsigned time_t
Definition time_t.h:4
static void timer_release(void)
Definition timer.c:35
static void timer_init(void)
Definition timer.c:64
static clock_t accumulator
Definition timer.c:23
static void timer_accumulate(void)
Definition timer.c:41
static void timer_acquire(void)
Definition timer.c:25
static time_t bootEpoch
Definition timer.c:19
static atomic_int8_t accumulatorLock
Definition timer.c:22
static bool initialized
Definition timer.c:20