PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
clock.c
Go to the documentation of this file.
2
3#include <kernel/cpu/cpu.h>
6#include <kernel/log/log.h>
7#include <kernel/log/panic.h>
10#include <kernel/sched/timer.h>
11
12#include <kernel/sync/rwlock.h>
13#include <stdatomic.h>
14#include <stdbool.h>
15#include <stdint.h>
16#include <sys/math.h>
17
23
24#ifdef DEBUG
25static _Atomic(clock_t) lastNsTime = ATOMIC_VAR_INIT(0);
26#endif
27
29{
32
33 for (uint32_t i = 0; i < sourceCount; i++)
34 {
35 const clock_source_t* source = sources[i];
37 {
39 }
41 {
43 }
44 }
45}
46
48{
49 if (source == NULL || (source->read_ns == NULL && source->read_epoch == NULL) || source->precision == 0)
50 {
51 errno = EINVAL;
52 return ERR;
53 }
54
57 {
59 errno = ENOSPC;
60 return ERR;
61 }
62
65
67
68 LOG_INFO("registered system timer source '%s' with precision %lu ns\n", source->name, source->precision);
69 return 0;
70}
71
73{
74 if (source == NULL)
75 {
76 return;
77 }
78
80 for (uint32_t i = 0; i < sourceCount; i++)
81 {
82 if (sources[i] != source)
83 {
84 continue;
85 }
86
87 memmove(&sources[i], &sources[i + 1], (sourceCount - i - 1) * sizeof(clock_source_t*));
89
92 return;
93 }
94
96 panic(NULL, "Failed to unregister system timer source '%s', not found", source->name);
97}
98
100{
102 if (bestNsSource == NULL)
103 {
104 return 0;
105 }
106
108#ifdef DEBUG
109 clock_t lastTime = atomic_exchange(&lastNsTime, time);
110 if (time < lastTime)
111 {
112 panic(NULL, "system time source '%s' returned non-monotonic time value %lu ns (last %lu ns)",
113 bestNsSource->name, time, lastTime);
114 }
115#endif
116 return time;
117}
118
120{
122 if (bestEpochSource == NULL)
123 {
124 return 0;
125 }
126
127 return bestEpochSource->read_epoch();
128}
129
130void clock_wait(clock_t nanoseconds)
131{
132 if (nanoseconds == 0)
133 {
134 return;
135 }
136
138 if (start == 0)
139 {
140 panic(NULL, "clock_wait called before timer system initialized");
141 }
142
143 while (clock_uptime() - start < nanoseconds)
144 {
145 asm volatile("pause");
146 }
147}
148
153
155{
156 time_t epoch = clock_epoch();
157 if (timePtr != NULL)
158 {
159 if (thread_copy_to_user(sched_thread(), timePtr, &epoch, sizeof(epoch)) == ERR)
160 {
161 return ERR;
162 }
163 }
164
165 return epoch;
166}
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscall.h:163
@ SYS_UNIX_EPOCH
Definition syscall.h:73
@ SYS_UPTIME
Definition syscall.h:72
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:266
#define LOG_INFO(format,...)
Definition log.h:106
#define CLOCK_MAX_SOURCES
Maximum amount of system timer sources.
Definition clock.h:26
time_t clock_epoch(void)
Retrieve the seconds since the unix epoch.
Definition clock.c:119
void clock_wait(clock_t nanoseconds)
Wait for a specified number of nanoseconds.
Definition clock.c:130
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
Definition clock.c:99
uint64_t clock_source_register(const clock_source_t *source)
Register a system timer source.
Definition clock.c:47
void clock_source_unregister(const clock_source_t *source)
Unregister a system timer source.
Definition clock.c:72
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:200
thread_t * sched_thread(void)
Retrieves the currently running thread.
Definition sched.c:612
void rwlock_write_acquire(rwlock_t *lock)
Acquires a rwlock for writing, blocking until it is available.
Definition rwlock.c:62
#define RWLOCK_READ_SCOPE(lock)
Acquires a rwlock for reading for the reminder of the current scope.
Definition rwlock.h:29
void rwlock_write_release(rwlock_t *lock)
Releases a rwlock from writing.
Definition rwlock.c:109
#define RWLOCK_CREATE()
Create a rwlock initializer.
Definition rwlock.h:47
#define ENOSPC
No space left on device.
Definition errno.h:172
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#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
static clock_source_t source
Structure to describe the HPET to the sys time subsystem.
Definition hpet.c:192
static rwlock_t sourcesLock
Definition clock.c:22
static const clock_source_t * bestEpochSource
Definition clock.c:21
static const clock_source_t * sources[CLOCK_MAX_SOURCES]
Definition clock.c:18
static const clock_source_t * bestNsSource
Definition clock.c:20
static uint32_t sourceCount
Definition clock.c:19
static void clock_update_best_sources(void)
Definition clock.c:28
static void start()
Definition main.c:542
#define atomic_exchange(object, desired)
Definition stdatomic.h:282
#define _Atomic(T)
Definition stdatomic.h:59
#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
_PUBLIC void * memmove(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Clock source structure.
Definition clock.h:33
const char * name
Definition clock.h:34
clock_t precision
Definition clock.h:35
clock_t(* read_ns)(void)
Definition clock.h:36
time_t(* read_epoch)(void)
Definition clock.h:37
Read-Write Ticket Lock structure.
Definition rwlock.h:61
_PUBLIC time_t time(time_t *timer)
Definition time.c:5
long long unsigned time_t
Definition time_t.h:4