#include "bootboot.h" #include "interrupts/Context.h" #include "std/errno.h" #include "sys/UserMemory.h" #include "thread/PIT.h" #include "thread/Scheduler.h" #include "utils/Time.h" #include static uint64_t unix_boot_time; #define CLOCK_REALTIME 0 #define CLOCK_MONOTONIC 1 #define CLOCK_PROCTIME 2 struct timeval { time_t tv_sec; suseconds_t tv_usec; }; struct timespec { time_t tv_sec; long tv_nsec; }; static void ms_to_timespec(long ms, struct timespec* tv) { tv->tv_sec = ms / 1000; tv->tv_nsec = (ms % 1000) * 1000000; } void sys_clock_gettime(Context* context, int clock, struct timespec* tp) { struct timespec* ktp = obtain_user_ref(tp); if (!ktp) { context->rax = -EFAULT; // FIXME: Not sure if clock_gettime can return EFAULT. return; } Task* current_task = Scheduler::current_task(); switch (clock) { case CLOCK_REALTIME: { ms_to_timespec(PIT::ms_since_boot, ktp); ktp->tv_sec += unix_boot_time; break; } case CLOCK_MONOTONIC: { ms_to_timespec(PIT::ms_since_boot, ktp); break; } case CLOCK_PROCTIME: { ms_to_timespec(current_task->cpu_time, ktp); break; } default: release_user_ref(ktp); context->rax = -EINVAL; return; } release_user_ref(ktp); context->rax = 0; return; } extern BOOTBOOT bootboot; void clock_init() { unix_boot_time = unix_boottime(bootboot.datetime); } uint64_t clock_now() { return unix_boot_time + (PIT::ms_since_boot / 1000); } uint64_t clock_boot() { return unix_boot_time; }