mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:17:35 +00:00
Kernel+LibC: Allow clock_gettime() to run without syscalls
This patch adds a vDSO-like mechanism for exposing the current time as an array of per-clock-source timestamps. LibC's clock_gettime() calls sys$map_time_page() to map the kernel's "time page" into the process address space (at a random address, ofc.) This is only done on first call, and from then on the timestamps are fetched from the time page. This first patch only adds support for CLOCK_REALTIME, but eventually we should be able to support all clock sources this way and get rid of sys$clock_gettime() in the kernel entirely. :^) Accesses are synchronized using two atomic integers that are incremented at the start and finish of the kernel's time page update cycle.
This commit is contained in:
parent
f02d73db4d
commit
fdfc66db61
7 changed files with 117 additions and 0 deletions
|
@ -7,6 +7,7 @@
|
|||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/Time.h>
|
||||
#include <Kernel/API/TimePage.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
@ -362,8 +363,39 @@ clock_t clock()
|
|||
return tms.tms_utime + tms.tms_stime;
|
||||
}
|
||||
|
||||
static Kernel::TimePage* get_kernel_time_page()
|
||||
{
|
||||
static Kernel::TimePage* s_kernel_time_page;
|
||||
// FIXME: Thread safety
|
||||
if (!s_kernel_time_page) {
|
||||
auto rc = syscall(SC_map_time_page);
|
||||
if ((int)rc < 0 && (int)rc > -EMAXERRNO) {
|
||||
errno = -(int)rc;
|
||||
return nullptr;
|
||||
}
|
||||
s_kernel_time_page = (Kernel::TimePage*)rc;
|
||||
}
|
||||
return s_kernel_time_page;
|
||||
}
|
||||
|
||||
int clock_gettime(clockid_t clock_id, struct timespec* ts)
|
||||
{
|
||||
if (Kernel::time_page_supports(clock_id)) {
|
||||
if (!ts) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (auto* kernel_time_page = get_kernel_time_page()) {
|
||||
u32 update_iteration;
|
||||
do {
|
||||
update_iteration = AK::atomic_load(&kernel_time_page->update1, AK::memory_order_acquire);
|
||||
*ts = kernel_time_page->clocks[clock_id];
|
||||
} while (update_iteration != AK::atomic_load(&kernel_time_page->update2, AK::memory_order_acquire));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rc = syscall(SC_clock_gettime, clock_id, ts);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue