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();
 }

Reply via email to