Module Name: src Committed By: martin Date: Fri Oct 11 17:18:05 UTC 2024
Modified Files: src/sys/kern [netbsd-9]: kern_resource.c subr_time.c src/sys/sys [netbsd-9]: resourcevar.h src/tests/lib/libc/sys [netbsd-9]: t_clock_gettime.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #1896): sys/sys/resourcevar.h: revision 1.58 sys/kern/subr_time.c: revision 1.36 sys/kern/subr_time.c: revision 1.37 sys/kern/subr_time.c: revision 1.38 sys/kern/kern_resource.c: revision 1.190 sys/kern/kern_resource.c: revision 1.191 tests/lib/libc/sys/t_clock_gettime.c: revision 1.4 tests/lib/libc/sys/t_clock_gettime.c: revision 1.5 tests/lib/libc/sys/t_clock_gettime.c: revision 1.6 (all via patch) kern: KASSERT(A && B) -> KASSERT(A); KASSERT(B) White space fix. kern_resource.c: Fix brace placement. No functional change intended. t_clock_gettime: Add test for PR kern/57512. clock_gettime(2): Fix CLOCK_PROCESS/THREAD_CPUTIME_ID. Use same calculation as getrusage, not some ad-hoc arithmetic of internal scheduler parameters that are periodically rewound. PR kern/57512 t_clock_gettime: Avoid signed/unsigned comparison. To generate a diff of this commit: cvs rdiff -u -r1.182.4.1 -r1.182.4.2 src/sys/kern/kern_resource.c cvs rdiff -u -r1.20 -r1.20.8.1 src/sys/kern/subr_time.c cvs rdiff -u -r1.57 -r1.57.6.1 src/sys/sys/resourcevar.h cvs rdiff -u -r1.3 -r1.3.16.1 src/tests/lib/libc/sys/t_clock_gettime.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_resource.c diff -u src/sys/kern/kern_resource.c:1.182.4.1 src/sys/kern/kern_resource.c:1.182.4.2 --- src/sys/kern/kern_resource.c:1.182.4.1 Thu Dec 12 20:43:08 2019 +++ src/sys/kern/kern_resource.c Fri Oct 11 17:18:05 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_resource.c,v 1.182.4.1 2019/12/12 20:43:08 martin Exp $ */ +/* $NetBSD: kern_resource.c,v 1.182.4.2 2024/10/11 17:18:05 martin Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.182.4.1 2019/12/12 20:43:08 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.182.4.2 2024/10/11 17:18:05 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -478,6 +478,30 @@ sys_getrlimit(struct lwp *l, const struc return copyout(&rl, SCARG(uap, rlp), sizeof(rl)); } +void +addrulwp(struct lwp *l, struct bintime *tm) +{ + + lwp_lock(l); + bintime_add(tm, &l->l_rtime); + if ((l->l_pflag & LP_RUNNING) != 0 && + (l->l_pflag & (LP_INTR | LP_TIMEINTR)) != LP_INTR) { + struct bintime diff; + /* + * Adjust for the current time slice. This is + * actually fairly important since the error + * here is on the order of a time quantum, + * which is much greater than the sampling + * error. + */ + binuptime(&diff); + membar_consumer(); /* for softint_dispatch() */ + bintime_sub(&diff, &l->l_stime); + bintime_add(tm, &diff); + } + lwp_unlock(l); +} + /* * Transform the running time and tick information in proc p into user, * system, and interrupt time usage. @@ -504,24 +528,7 @@ calcru(struct proc *p, struct timeval *u tm = p->p_rtime; LIST_FOREACH(l, &p->p_lwps, l_sibling) { - lwp_lock(l); - bintime_add(&tm, &l->l_rtime); - if ((l->l_pflag & LP_RUNNING) != 0 && - (l->l_pflag & (LP_INTR | LP_TIMEINTR)) != LP_INTR) { - struct bintime diff; - /* - * Adjust for the current time slice. This is - * actually fairly important since the error - * here is on the order of a time quantum, - * which is much greater than the sampling - * error. - */ - binuptime(&diff); - membar_consumer(); /* for softint_dispatch() */ - bintime_sub(&diff, &l->l_stime); - bintime_add(&tm, &diff); - } - lwp_unlock(l); + addrulwp(l, &tm); } tot = st + ut + it; @@ -601,7 +608,8 @@ sys___getrusage50(struct lwp *l, const s } int -getrusage1(struct proc *p, int who, struct rusage *ru) { +getrusage1(struct proc *p, int who, struct rusage *ru) +{ switch (who) { case RUSAGE_SELF: Index: src/sys/kern/subr_time.c diff -u src/sys/kern/subr_time.c:1.20 src/sys/kern/subr_time.c:1.20.8.1 --- src/sys/kern/subr_time.c:1.20 Fri Dec 8 01:19:29 2017 +++ src/sys/kern/subr_time.c Fri Oct 11 17:18:05 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_time.c,v 1.20 2017/12/08 01:19:29 christos Exp $ */ +/* $NetBSD: subr_time.c,v 1.20.8.1 2024/10/11 17:18:05 martin Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.20 2017/12/08 01:19:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.20.8.1 2024/10/11 17:18:05 martin Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -45,12 +45,6 @@ __KERNEL_RCSID(0, "$NetBSD: subr_time.c, #include <sys/timetc.h> #include <sys/intr.h> -#ifdef DEBUG_STICKS -#define DPRINTF(a) uprintf a -#else -#define DPRINTF(a) -#endif - /* * Compute number of hz until specified time. Used to compute second * argument to callout_reset() from an absolute time. @@ -98,7 +92,8 @@ tvtohz(const struct timeval *tv) sec = tv->tv_sec; usec = tv->tv_usec; - KASSERT(usec >= 0 && usec < 1000000); + KASSERT(usec >= 0); + KASSERT(usec < 1000000); /* catch overflows in conversion time_t->int */ if (tv->tv_sec > INT_MAX) @@ -238,32 +233,16 @@ clock_timeleft(clockid_t clockid, struct *sleepts = sleptts; } -static void -ticks2ts(uint64_t ticks, struct timespec *ts) -{ - ts->tv_sec = ticks / hz; - uint64_t sticks = ticks - ts->tv_sec * hz; - if (sticks > BINTIME_SCALE_MS) /* floor(2^64 / 1000) */ - ts->tv_nsec = sticks / hz * 1000000000LL; - else if (sticks > BINTIME_SCALE_US) /* floor(2^64 / 1000000) */ - ts->tv_nsec = sticks * 1000LL / hz * 1000000LL; - else - ts->tv_nsec = sticks * 1000000000LL / hz; - DPRINTF(("%s: %ju/%ju -> %ju.%ju\n", __func__, - (uintmax_t)ticks, (uintmax_t)sticks, - (uintmax_t)ts->tv_sec, (uintmax_t)ts->tv_nsec)); -} - int clock_gettime1(clockid_t clock_id, struct timespec *ts) { int error; - uint64_t ticks; struct proc *p; #define CPUCLOCK_ID_MASK (~(CLOCK_THREAD_CPUTIME_ID|CLOCK_PROCESS_CPUTIME_ID)) if (clock_id & CLOCK_PROCESS_CPUTIME_ID) { pid_t pid = clock_id & CPUCLOCK_ID_MASK; + struct timeval cputime; mutex_enter(proc_lock); p = pid == 0 ? curproc : proc_find(pid); @@ -271,10 +250,10 @@ clock_gettime1(clockid_t clock_id, struc mutex_exit(proc_lock); return ESRCH; } - ticks = p->p_uticks + p->p_sticks + p->p_iticks; - DPRINTF(("%s: u=%ju, s=%ju, i=%ju\n", __func__, - (uintmax_t)p->p_uticks, (uintmax_t)p->p_sticks, - (uintmax_t)p->p_iticks)); + mutex_enter(p->p_lock); + calcru(p, /*usertime*/NULL, /*systime*/NULL, /*intrtime*/NULL, + &cputime); + mutex_exit(p->p_lock); mutex_exit(proc_lock); // XXX: Perhaps create a special kauth type @@ -283,9 +262,14 @@ clock_gettime1(clockid_t clock_id, struc KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); if (error) return error; + + TIMEVAL_TO_TIMESPEC(&cputime, ts); + return 0; } else if (clock_id & CLOCK_THREAD_CPUTIME_ID) { struct lwp *l; lwpid_t lid = clock_id & CPUCLOCK_ID_MASK; + struct bintime tm = {0, 0}; + p = curproc; mutex_enter(p->p_lock); l = lid == 0 ? curlwp : lwp_find(p, lid); @@ -293,15 +277,10 @@ clock_gettime1(clockid_t clock_id, struc mutex_exit(p->p_lock); return ESRCH; } - ticks = l->l_rticksum + l->l_slpticksum; - DPRINTF(("%s: r=%ju, s=%ju\n", __func__, - (uintmax_t)l->l_rticksum, (uintmax_t)l->l_slpticksum)); + addrulwp(l, &tm); mutex_exit(p->p_lock); - } else - ticks = (uint64_t)-1; - if (ticks != (uint64_t)-1) { - ticks2ts(ticks, ts); + bintime2timespec(&tm, ts); return 0; } Index: src/sys/sys/resourcevar.h diff -u src/sys/sys/resourcevar.h:1.57 src/sys/sys/resourcevar.h:1.57.6.1 --- src/sys/sys/resourcevar.h:1.57 Mon May 7 21:03:45 2018 +++ src/sys/sys/resourcevar.h Fri Oct 11 17:18:05 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: resourcevar.h,v 1.57 2018/05/07 21:03:45 christos Exp $ */ +/* $NetBSD: resourcevar.h,v 1.57.6.1 2024/10/11 17:18:05 martin Exp $ */ /* * Copyright (c) 1991, 1993 @@ -41,6 +41,8 @@ #include <sys/mutex.h> #include <sys/resource.h> +struct bintime; + /* * Kernel per-process accounting / statistics */ @@ -107,6 +109,7 @@ void addupc_intr(struct lwp *, u_long); void addupc_task(struct lwp *, u_long, u_int); void calcru(struct proc *, struct timeval *, struct timeval *, struct timeval *, struct timeval *); +void addrulwp(struct lwp *, struct bintime *); struct plimit *lim_copy(struct plimit *); void lim_addref(struct plimit *); Index: src/tests/lib/libc/sys/t_clock_gettime.c diff -u src/tests/lib/libc/sys/t_clock_gettime.c:1.3 src/tests/lib/libc/sys/t_clock_gettime.c:1.3.16.1 --- src/tests/lib/libc/sys/t_clock_gettime.c:1.3 Fri Jan 13 21:30:41 2017 +++ src/tests/lib/libc/sys/t_clock_gettime.c Fri Oct 11 17:18:05 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: t_clock_gettime.c,v 1.3 2017/01/13 21:30:41 christos Exp $ */ +/* $NetBSD: t_clock_gettime.c,v 1.3.16.1 2024/10/11 17:18:05 martin Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,17 +58,19 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_clock_gettime.c,v 1.3 2017/01/13 21:30:41 christos Exp $"); +__RCSID("$NetBSD: t_clock_gettime.c,v 1.3.16.1 2024/10/11 17:18:05 martin Exp $"); #include <sys/param.h> -#include <sys/sysctl.h> +#include <sys/ioctl.h> +#include <sys/sysctl.h> #include <atf-c.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -204,10 +206,91 @@ ATF_TC_BODY(clock_gettime_real, tc) RL(sysctlbyname(TC_HARDWARE, NULL, 0, save, strlen(save))); } +static void +waste_user_time(void) +{ + static char buf[4*4096]; + + arc4random_buf(buf, sizeof(buf)); +} + +static void __unused +waste_system_time(void) +{ + static char buf[4*4096]; + int fd[2]; + int i, n; + + RL(pipe2(fd, O_NONBLOCK)); + RL(n = ioctl(fd[1], FIONSPACE)); + n = MIN((unsigned)MAX(0, n), sizeof(buf)); + for (i = 0; i < 16; i++) { + RL(write(fd[1], buf, n)); + RL(read(fd[0], buf, n)); + } + RL(close(fd[0])); + RL(close(fd[1])); +} + +static void +check_monotonicity(const char *clockname, clockid_t clockid, + void (*waste_time)(void)) +{ + static const struct timespec maxtime = {5, 0}; + struct timespec mono_t0, t0, mono_d; + + RL(clock_gettime(CLOCK_MONOTONIC, &mono_t0)); + RL(clock_gettime(clockid, &t0)); + + do { + struct timespec t1, mono_t1; + + (*waste_time)(); + + RL(clock_gettime(clockid, &t1)); + ATF_CHECK_MSG(timespeccmp(&t0, &t1, <=), + "clock %s=0x%jx went backwards t0=%jd.%09ld t1=%jd.%09ld", + clockname, (uintmax_t)clockid, + (intmax_t)t0.tv_sec, t0.tv_nsec, + (intmax_t)t1.tv_sec, t1.tv_nsec); + + t0 = t1; + + RL(clock_gettime(CLOCK_MONOTONIC, &mono_t1)); + timespecsub(&mono_t1, &mono_t0, &mono_d); + } while (timespeccmp(&mono_d, &maxtime, <)); +} + +ATF_TC(clock_gettime_process_cputime_is_monotonic); +ATF_TC_HEAD(clock_gettime_process_cputime_is_monotonic, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks that CLOCK_PROCESS_CPUTIME_ID is monotonic"); +} +ATF_TC_BODY(clock_gettime_process_cputime_is_monotonic, tc) +{ + check_monotonicity("CLOCK_PROCESS_CPUTIME_ID", + CLOCK_PROCESS_CPUTIME_ID, &waste_user_time); +} + +ATF_TC(clock_gettime_thread_cputime_is_monotonic); +ATF_TC_HEAD(clock_gettime_thread_cputime_is_monotonic, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks that CLOCK_THREAD_CPUTIME_ID is monotonic"); +} +ATF_TC_BODY(clock_gettime_thread_cputime_is_monotonic, tc) +{ + check_monotonicity("CLOCK_THREAD_CPUTIME_ID", + CLOCK_THREAD_CPUTIME_ID, &waste_user_time); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, clock_gettime_real); + ATF_TP_ADD_TC(tp, clock_gettime_process_cputime_is_monotonic); + ATF_TP_ADD_TC(tp, clock_gettime_thread_cputime_is_monotonic); return atf_no_error(); }