Skip to content

Commit 813d28d

Browse files
rHermesfincs
authored andcommitted
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.
1 parent 82f8211 commit 813d28d

File tree

1 file changed

+62
-1
lines changed

1 file changed

+62
-1
lines changed

libctru/source/system/syscalls.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
#include <sys/lock.h>
44
#include <sys/reent.h>
55
#include <string.h>
6+
#include <time.h>
7+
#include <errno.h>
68

79
#include <3ds/types.h>
810
#include <3ds/svc.h>
911
#include <3ds/env.h>
1012
#include <3ds/os.h>
1113
#include <3ds/synchronization.h>
14+
1215
#include "../internal.h"
1316

1417
void __ctru_exit(int rc);
@@ -28,6 +31,64 @@ struct _reent* __SYSCALL(getreent)()
2831
return tv->reent;
2932
}
3033

34+
int __SYSCALL(clock_gettime)(clockid_t clock_id, struct timespec *tp) {
35+
36+
if (clock_id == CLOCK_REALTIME)
37+
{
38+
if (tp != NULL)
39+
{
40+
// Retrieve current time, adjusting epoch from 1900 to 1970
41+
s64 ms_since_epoch = osGetTime() - 2208988800000ULL;
42+
tp->tv_sec = ms_since_epoch / 1000;
43+
tp->tv_nsec = (ms_since_epoch % 1000) * 1000000;
44+
}
45+
}
46+
else if (clock_id == CLOCK_MONOTONIC)
47+
{
48+
if (tp != NULL)
49+
{
50+
// Use the ticks directly, as it offer the highest precision
51+
u64 ticks_since_boot = svcGetSystemTick();
52+
53+
tp->tv_sec = ticks_since_boot / SYSCLOCK_ARM11;
54+
tp->tv_nsec = ((ticks_since_boot % SYSCLOCK_ARM11) * 1000000000ULL) / SYSCLOCK_ARM11;
55+
}
56+
}
57+
else
58+
{
59+
errno = EINVAL;
60+
return -1;
61+
}
62+
63+
return 0;
64+
}
65+
66+
int __SYSCALL(clock_getres)(clockid_t clock_id, struct timespec *res) {
67+
if (clock_id == CLOCK_REALTIME)
68+
{
69+
if (res != NULL)
70+
{
71+
res->tv_sec = 0;
72+
res->tv_nsec = 1000000;
73+
}
74+
}
75+
else if (clock_id == CLOCK_MONOTONIC)
76+
{
77+
if (res != NULL)
78+
{
79+
res->tv_sec = 0;
80+
res->tv_nsec = 1;
81+
}
82+
}
83+
else
84+
{
85+
errno = EINVAL;
86+
return -1;
87+
}
88+
89+
return 0;
90+
}
91+
3192
//---------------------------------------------------------------------------------
3293
int __SYSCALL(gettod_r)(struct _reent *ptr, struct timeval *tp, struct timezone *tz) {
3394
//---------------------------------------------------------------------------------
@@ -37,7 +98,7 @@ int __SYSCALL(gettod_r)(struct _reent *ptr, struct timeval *tp, struct timezone
3798

3899
// Convert to struct timeval
39100
tp->tv_sec = now / 1000;
40-
tp->tv_usec = (now - 1000*tp->tv_sec) * 1000;
101+
tp->tv_usec = (now % 1000) * 1000;
41102
}
42103

43104
if (tz != NULL) {

0 commit comments

Comments
 (0)