Implement clock_gettime syscall
This implements the syscalls for `clock_gettime` and `clock_getres`. We support two clocks: CLOCK_REALTIME and CLOCK_MONOTONIC. I've opted to use the existing `osGetTime()` code for the realtime clock, because it's known to work. For CLOCK_MONOTONIC I've used `svcGetSystemTick()` directly, as it has a higher resolution. We can ignore the drift and so on, because it's supposed to be just the number of ticks since last boot.
This commit is contained in:
parent
82f821156a
commit
813d28ddc4
@ -3,12 +3,15 @@
|
|||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/reent.h>
|
#include <sys/reent.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <3ds/types.h>
|
#include <3ds/types.h>
|
||||||
#include <3ds/svc.h>
|
#include <3ds/svc.h>
|
||||||
#include <3ds/env.h>
|
#include <3ds/env.h>
|
||||||
#include <3ds/os.h>
|
#include <3ds/os.h>
|
||||||
#include <3ds/synchronization.h>
|
#include <3ds/synchronization.h>
|
||||||
|
|
||||||
#include "../internal.h"
|
#include "../internal.h"
|
||||||
|
|
||||||
void __ctru_exit(int rc);
|
void __ctru_exit(int rc);
|
||||||
@ -28,6 +31,64 @@ struct _reent* __SYSCALL(getreent)()
|
|||||||
return tv->reent;
|
return tv->reent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __SYSCALL(clock_gettime)(clockid_t clock_id, struct timespec *tp) {
|
||||||
|
|
||||||
|
if (clock_id == CLOCK_REALTIME)
|
||||||
|
{
|
||||||
|
if (tp != NULL)
|
||||||
|
{
|
||||||
|
// Retrieve current time, adjusting epoch from 1900 to 1970
|
||||||
|
s64 ms_since_epoch = osGetTime() - 2208988800000ULL;
|
||||||
|
tp->tv_sec = ms_since_epoch / 1000;
|
||||||
|
tp->tv_nsec = (ms_since_epoch % 1000) * 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (clock_id == CLOCK_MONOTONIC)
|
||||||
|
{
|
||||||
|
if (tp != NULL)
|
||||||
|
{
|
||||||
|
// Use the ticks directly, as it offer the highest precision
|
||||||
|
u64 ticks_since_boot = svcGetSystemTick();
|
||||||
|
|
||||||
|
tp->tv_sec = ticks_since_boot / SYSCLOCK_ARM11;
|
||||||
|
tp->tv_nsec = ((ticks_since_boot % SYSCLOCK_ARM11) * 1000000000ULL) / SYSCLOCK_ARM11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __SYSCALL(clock_getres)(clockid_t clock_id, struct timespec *res) {
|
||||||
|
if (clock_id == CLOCK_REALTIME)
|
||||||
|
{
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
res->tv_sec = 0;
|
||||||
|
res->tv_nsec = 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (clock_id == CLOCK_MONOTONIC)
|
||||||
|
{
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
res->tv_sec = 0;
|
||||||
|
res->tv_nsec = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
int __SYSCALL(gettod_r)(struct _reent *ptr, struct timeval *tp, struct timezone *tz) {
|
int __SYSCALL(gettod_r)(struct _reent *ptr, struct timeval *tp, struct timezone *tz) {
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
@ -37,7 +98,7 @@ int __SYSCALL(gettod_r)(struct _reent *ptr, struct timeval *tp, struct timezone
|
|||||||
|
|
||||||
// Convert to struct timeval
|
// Convert to struct timeval
|
||||||
tp->tv_sec = now / 1000;
|
tp->tv_sec = now / 1000;
|
||||||
tp->tv_usec = (now - 1000*tp->tv_sec) * 1000;
|
tp->tv_usec = (now % 1000) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tz != NULL) {
|
if (tz != NULL) {
|
||||||
|
Loading…
Reference in New Issue
Block a user