#ifdef HAVE_CONFIG_H #include #endif #include #include #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; (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; }