feat(time): time/clock/mktime/strftime/nanosleep

This commit is contained in:
2026-09-05 22:33:02 -04:00
parent 3eff4c97fd
commit ed996ff4c4
14 changed files with 3037 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <time.h>
#include "../internal/syscall.h"
/*
* struct tms layout for SYS_times: four process-CPU clock-tick counters,
* in kernel order (x86_64: four longs; the kernel ABI names it __kernel_tms).
* It is private to this file; <sys/times.h> (a later todo) will own the
* public definition.
*/
struct tms
{
clock_t tms_utime; /* user CPU time */
clock_t tms_stime; /* system CPU time */
clock_t tms_cutime; /* user CPU time of waited-for children */
clock_t tms_cstime; /* system CPU time of waited-for children */
};
/*
* clock: the calling process's CPU time in CLOCKS_PER_SEC units.
*
* SYS_times reports CPU time in USER_HZ ticks (100 per second on x86_64),
* so the tick counts are scaled by CLOCKS_PER_SEC / 100 == 10000 to the
* 1 MHz clock() unit. On failure SYS_times returns -1 and clock() reports
* (clock_t)-1 with errno set.
*/
clock_t
clock(void)
{
struct tms t;
if (syscall_ret(__syscall1(SYS_times, (long)&t)) < 0)
{
return (clock_t)-1;
}
return (clock_t)((t.tms_utime + t.tms_stime) * (CLOCKS_PER_SEC / 100));
}
/*
* clock_gettime/clock_settime/clock_getres: raw kernel clock reads and
* writes over SYS_clock_gettime(228)/SYS_clock_settime(227)/
* SYS_clock_getres(229). The clock ids (CLOCK_REALTIME and friends) are
* kernel ABI values and pass through unchanged; the struct timespec
* arguments are the kernel's own layout.
*/
int
clock_gettime(clockid_t clockid, struct timespec *tp)
{
return syscall_ret(__syscall2(SYS_clock_gettime, (long)clockid, (long)tp));
}
int
clock_settime(clockid_t clockid, const struct timespec *tp)
{
return syscall_ret(__syscall2(SYS_clock_settime, (long)clockid, (long)tp));
}
int
clock_getres(clockid_t clockid, struct timespec *res)
{
return syscall_ret(__syscall2(SYS_clock_getres, (long)clockid, (long)res));
}
/*
* clock_getcpuclockid: the clock id that measures a given process's CPU
* time.
*
* The calling process (pid 0 or our own pid) is always reported as
* CLOCK_PROCESS_CPUTIME_ID. Any other pid is encoded with the kernel's
* CPUCLOCK_PID scheme — (~pid << 3) | 2 — and validated by probing that
* clock with SYS_clock_getres, which the kernel answers with ESRCH when no
* such process exists. That probe failing is the only errno write this
* file performs on its own; every other path leaves errno to syscall_ret.
*/
int
clock_getcpuclockid(pid_t pid, clockid_t *clock_id)
{
pid_t self = (pid_t)syscall_ret(__syscall0(SYS_getpid));
clockid_t id;
if (pid == 0)
{
pid = self;
}
if (pid == self)
{
*clock_id = CLOCK_PROCESS_CPUTIME_ID;
return 0;
}
/* Linux CPUCLOCK_PID encoding of a process clock id. */
id = (clockid_t)((~(unsigned)pid << 3) | 2u);
/* Probe the encoded id; the kernel rejects unknown pids with ESRCH. */
{
struct timespec res;
if (syscall_ret(__syscall2(SYS_clock_getres, (long)id, (long)&res)) < 0)
{
errno = ESRCH;
return -1;
}
}
*clock_id = id;
return 0;
}