tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Bug fix for PR 26470 for review
Hi all,
attached patch fixes a problem that settimeofday with short period
timers will loop in the kernel for a long time. The attached patch
differs from the version in the PR slightly as it will do the sanest
possible thing if the time ever goes back. I am not sure if that can
happen at that point, but better be correct.
Any comments?
Joerg
Index: kern_time.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/kern/kern_time.c,v
retrieving revision 1.147
diff -u -p -r1.147 kern_time.c
--- kern_time.c 8 May 2008 18:56:58 -0000 1.147
+++ kern_time.c 24 May 2008 16:35:18 -0000
@@ -923,8 +923,10 @@ sys_timer_getoverrun(struct lwp *l, cons
void
realtimerexpire(void *arg)
{
+ uint64_t last_val, next_val, interval, now_ms;
struct timeval now;
struct ptimer *pt;
+ int backwards;
pt = arg;
@@ -936,24 +938,33 @@ realtimerexpire(void *arg)
mutex_spin_exit(&timer_lock);
return;
}
- for (;;) {
- timeradd(&pt->pt_time.it_value,
- &pt->pt_time.it_interval, &pt->pt_time.it_value);
- getmicrotime(&now);
- if (timercmp(&pt->pt_time.it_value, &now, >)) {
- /*
- * Don't need to check hzto() return value, here.
- * callout_reset() does it for us.
- */
- callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
- realtimerexpire, pt);
- mutex_spin_exit(&timer_lock);
- return;
- }
- mutex_spin_exit(&timer_lock);
- pt->pt_overruns++;
- mutex_spin_enter(&timer_lock);
- }
+
+ getmicrotime(&now);
+ backwards = (timercmp(&pt->pt_time.it_value, &now, >));
+#define TV2MS(x) (((uint64_t)(x)->tv_sec) * 1000000 + (x)->tv_usec)
+ now_ms = TV2MS(&now);
+ last_val = TV2MS(&pt->pt_time.it_value);
+ interval = TV2MS(&pt->pt_time.it_interval);
+#undef TV2MS
+
+ next_val = now_ms +
+ (now_ms - last_val + interval - 1) % interval;
+
+ if (backwards)
+ next_val += interval;
+ else
+ pt->pt_overruns = (now_ms - last_val) / interval;
+
+ pt->pt_time.it_value.tv_sec = next_val / 1000000;
+ pt->pt_time.it_value.tv_usec = next_val % 1000000;
+
+ /*
+ * Don't need to check hzto() return value, here.
+ * callout_reset() does it for us.
+ */
+ callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
+ realtimerexpire, pt);
+ mutex_spin_exit(&timer_lock);
}
/* BSD routine to get the value of an interval timer. */
Home |
Main Index |
Thread Index |
Old Index