NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/59339: heartbeat watchdog fires since 10.99.14
The following reply was made to PR kern/59339; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Thomas Klausner <wiz%NetBSD.org@localhost>, Patrick Welche <prlw1%welche.eu@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: kern/59339: heartbeat watchdog fires since 10.99.14
Date: Mon, 12 May 2025 02:27:35 +0000
This is a multi-part message in MIME format.
--=_9mocicosntHKdkPBqLK6zsx2at0gzuB8
Sixth time's the charm, right? (This time I checked to make sure all
the printfs end with \n! And I have removed the noisy one which is
evidently no longer valuable.)
--=_9mocicosntHKdkPBqLK6zsx2at0gzuB8
Content-Type: text/plain; charset="ISO-8859-1"; name="pr59339-itimercalloutassert-v6"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr59339-itimercalloutassert-v6.patch"
diff -r 55a6ded9e19e -r 3a9986775d9a sys/kern/kern_time.c
--- a/sys/kern/kern_time.c Thu May 08 20:51:40 2025 +0000
+++ b/sys/kern/kern_time.c Sun May 11 23:38:46 2025 +0000
@@ -837,6 +837,91 @@ itimer_arm_real(struct itimer * const it
}
=20
/*
+ * itimer_rearm_real:
+ *
+ * Re-arm a non-virtual timer, given the current clock readout.
+ */
+static void
+itimer_rearm_real(struct itimer * const it, const struct timespec * const =
now,
+ const struct timespec * const last)
+{
+ const struct timespec * const interval =3D &it->it_time.it_interval;
+ const struct timespec * const next =3D &it->it_time.it_value;
+ struct timespec delta;
+ int ticks;
+
+ KASSERT(!it->it_dying);
+ KASSERT(!CLOCK_VIRTUAL_P(it->it_clockid));
+ KASSERT(!callout_pending(&it->it_ch));
+
+ if (__predict_true(timespecisset(next))) {
+ struct timespec now1;
+
+ if (it->it_clockid =3D=3D CLOCK_MONOTONIC) {
+ getnanouptime(&now1);
+ } else {
+ getnanotime(&now1);
+ }
+ if (timespeccmp(next, &now1, <=3D)) {
+ printf("PR kern/59339 (heartbeat watchdog fires"
+ " since 10.99.14) would fire:"
+ " [clock %u]"
+ " [now=3D%lld.%09ld -> %lld.%09ld],"
+ " last=3D%lld.%09ld + interval=3D%lld.%09ld"
+ " -> next=3D%lld.%09ld\n",
+ it->it_clockid,
+ (long long)now->tv_sec, (long)now->tv_nsec,
+ (long long)now1.tv_sec, (long)now1.tv_nsec,
+ (long long)last->tv_sec, (long)last->tv_nsec,
+ (long long)interval->tv_sec,
+ (long)interval->tv_nsec,
+ (long long)next->tv_sec, (long)next->tv_nsec);
+ }
+
+ KASSERTMSG(timespeccmp(now, next, <),
+ "[clock %u]"
+ " now=3D%lld.%09ld,"
+ " last=3D%lld.%09ld + interval=3D%lld.%09ld"
+ " -> next=3D%lld.%09ld",
+ it->it_clockid,
+ (long long)now->tv_sec, (long)now->tv_nsec,
+ (long long)last->tv_sec, (long)last->tv_nsec,
+ (long long)interval->tv_sec, (long)interval->tv_nsec,
+ (long long)next->tv_sec, (long)next->tv_nsec);
+ timespecsub(next, now, &delta);
+ } else {
+ /*
+ * If the arithmetic overflowed, just take the interval
+ * as the time to wait. This is unlikely to happen
+ * unless you are messing with your clock to set it
+ * ahead by hundreds of years.
+ */
+ printf("[clock %u]"
+ " itimer arithmetic overflowed:"
+ " now=3D%lld.%09ld, last=3D%lld.%09ld + interval=3D%lld.%09ld\n",
+ it->it_clockid,
+ (long long)now->tv_sec, (long)now->tv_nsec,
+ (long long)last->tv_sec, (long)last->tv_nsec,
+ (long long)interval->tv_sec, (long)interval->tv_nsec);
+ delta =3D it->it_time.it_interval; /* overflow */
+ }
+ ticks =3D tstohz(&delta);
+ KASSERTMSG(ticks > 0,
+ "[clock %u]"
+ " now=3D%lld.%09ld,"
+ " last=3D%lld.%09ld + interval=3D%lld.%09ld -> next=3D%lld.%09ld;"
+ " delta=3D%lld.%09ld ticks=3D%d",
+ it->it_clockid,
+ (long long)now->tv_sec, (long)now->tv_nsec,
+ (long long)last->tv_sec, (long)last->tv_nsec,
+ (long long)interval->tv_sec, (long)interval->tv_nsec,
+ (long long)next->tv_sec, (long)next->tv_nsec,
+ (long long)delta.tv_sec, (long)delta.tv_nsec,
+ ticks);
+ callout_schedule(&it->it_ch, ticks);
+}
+
+/*
* itimer_callout:
*
* Callout to expire a non-virtual timer. Queue it up for processing,
@@ -848,7 +933,7 @@ itimer_arm_real(struct itimer * const it
static void
itimer_callout(void *arg)
{
- struct timespec now, next;
+ struct timespec last, now, next;
struct itimer * const it =3D arg;
int overruns;
=20
@@ -871,7 +956,20 @@ itimer_callout(void *arg)
* Given the current itimer value and interval and the time
* now, compute the next itimer value and count overruns.
*/
+ last =3D it->it_time.it_value;
itimer_transition(&it->it_time, &now, &next, &overruns);
+ KASSERTMSG(timespeccmp(&now, &next, <),
+ "[clock %u]"
+ " it->it_time.it_value=3D%lld.%09ld"
+ " it->it_time.it_interval=3D%lld.%09ld"
+ " now=3D%lld.%09ld next=3D%lld.%09ld",
+ it->it_clockid,
+ (long long)it->it_time.it_value.tv_sec,
+ (long)it->it_time.it_value.tv_nsec,
+ (long long)it->it_time.it_interval.tv_sec,
+ (long)it->it_time.it_interval.tv_nsec,
+ (long long)now.tv_sec, (long)now.tv_nsec,
+ (long long)next.tv_sec, (long)next.tv_nsec);
it->it_time.it_value =3D next;
it->it_overruns +=3D overruns;
=20
@@ -879,7 +977,7 @@ itimer_callout(void *arg)
* Reset the callout, if it's not going away.
*/
if (!it->it_dying)
- itimer_arm_real(it);
+ itimer_rearm_real(it, &now, &last);
itimer_unlock();
}
=20
diff -r 55a6ded9e19e -r 3a9986775d9a sys/kern/subr_time.c
--- a/sys/kern/subr_time.c Thu May 08 20:51:40 2025 +0000
+++ b/sys/kern/subr_time.c Sun May 11 23:38:46 2025 +0000
@@ -86,17 +86,29 @@ tshztoup(const struct timespec *tsp)
=20
/*
* Compute number of ticks in the specified amount of time.
+ *
+ * Round up, clamped to INT_MAX. Return 0 iff ts <=3D 0.
*/
int
tstohz(const struct timespec *ts)
{
struct timeval tv;
=20
+ KASSERT(ts->tv_nsec >=3D 0);
+ KASSERT(ts->tv_nsec < 1000000000);
+
/*
* usec has great enough resolution for hz, so convert to a
* timeval and use tvtohz() above.
*/
- TIMESPEC_TO_TIMEVAL(&tv, ts);
+ tv.tv_sec =3D ts->tv_sec;
+ tv.tv_usec =3D (ts->tv_nsec + 999)/1000;
+ if (tv.tv_usec >=3D 1000000) {
+ if (__predict_false(tv.tv_sec =3D=3D __type_max(time_t)))
+ return INT_MAX;
+ tv.tv_sec++;
+ tv.tv_usec -=3D 1000000;
+ }
return tvtohz(&tv);
}
=20
@@ -248,7 +260,8 @@ ts2timo(clockid_t clock_id, int flags, s
return ETIMEDOUT;
=20
*timo =3D tstohz(ts);
- KASSERT(*timo > 0);
+ KASSERTMSG(*timo > 0, "ts=3D%lld.%09ld *timo=3D%d",
+ (long long)ts->tv_sec, (long)ts->tv_nsec, *timo);
=20
return 0;
}
--=_9mocicosntHKdkPBqLK6zsx2at0gzuB8--
Home |
Main Index |
Thread Index |
Old Index