83 lines
1.6 KiB
C++
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;
|
|
} |