Luna/kernel/src/sys/clock.cpp

83 lines
1.6 KiB
C++

#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 <sys/types.h>
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;
}