Subject: Re: kern/26470: all process stop for a long time by calling settimeofday() and setitimer()
To: None <karino@da.jp.nec.com>
From: SAITOH Masanobu <masanobu@iij.ad.jp>
List: current-users
Date: 07/29/2004 16:19:25
> >Description:
> All process stops for a long time by calling setitimer() with short interval and then putting the system clock forward long.
>
> Following loop is executed many times.
> (in kern/kern_time.c:realitexpire())
How about this?
# please ignore wdog stuff
===============================================
--- time.h Thu Oct 10 21:10:26 2002
+++ time.h Fri Jul 23 19:57:39 2004
@@ -100,6 +100,27 @@
(vvp)->tv_usec += 1000000; \
} \
} while (/* CONSTCOND */ 0)
+#define timermul(tvp, uvp, m) \
+ do { \
+ (uvp)->tv_sec = (tvp)->tv_sec * (m); \
+ (uvp)->tv_usec = (tvp)->tv_usec * (m); \
+ while ((uvp)->tv_usec >= 1000000) { \
+ (uvp)->tv_sec++; \
+ (uvp)->tv_usec -= 1000000; \
+ } \
+ } while (/* CONSTCOND */ 0)
+#define timerdiv(tvp, uvp, d) /* uvp = tvp / d */ \
+ do { \
+ (uvp)->tv_sec = (tvp)->tv_sec / (d); \
+ (uvp)->tv_usec = ((tvp)->tv_sec % (d)) * 1000000) / (d);\
+ } while (/* CONSTCOND */ 0)
+#define timerdiv2(tvp, uvp, x) /* x = tvp / uvp */ \
+ do { \
+ int64_t _t, _u; \
+ _t = (int64_t)((tvp)->tv_sec) * 1000000 + (tvp)->tv_usec;\
+ _u = (int64_t)((uvp)->tv_sec) * 1000000 + (uvp)->tv_usec;\
+ (x) = _t / _u; \
+ } while (/* CONSTCOND */ 0)
/* Operations on timespecs. */
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
===============================================
--- kern_time.c Thu Oct 10 21:10:16 2002
+++ kern_time.c Fri Jul 23 20:05:04 2004
@@ -100,6 +100,18 @@
#include <machine/cpu.h>
/*
* Time of day and interval timer support.
*
@@ -627,6 +639,8 @@
{
struct proc *p;
int s;
+ struct timeval t;
+ int64_t n;
p = (struct proc *)arg;
psignal(p, SIGALRM);
@@ -634,6 +648,53 @@
timerclear(&p->p_realtimer.it_value);
return;
}
+ s = splclock();
+ timeradd(&p->p_realtimer.it_value,
+ &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
+ if (timercmp(&p->p_realtimer.it_value, &time, <=)) {
+#if 0
+ printf("old time (%ld.%ld)\n",
+ p->p_realtimer.it_value.tv_sec,
+ p->p_realtimer.it_value.tv_usec);
+#endif
+ timersub(&time, &p->p_realtimer.it_value, &t);
+#if 0
+ printf("diff (%ld.%ld)\n", t.tv_sec, t.tv_usec);
+ printf("denom (%ld.%ld)\n",
+ p->p_realtimer.it_interval.tv_sec,
+ p->p_realtimer.it_interval.tv_usec);
+#endif
+ timerdiv2(&t, &p->p_realtimer.it_interval, n);
+#if 0
+ printf("div = %lld\n", n);
+#endif
+ timermul(&p->p_realtimer.it_interval, &t, n+1);
+#if 0
+ printf("new diff (%ld.%ld)\n", t.tv_sec, t.tv_usec);
+#endif
+ timeradd(&p->p_realtimer.it_value, &t,
+ &p->p_realtimer.it_value);
+#if 0
+ printf("new time (%ld.%ld)\n",
+ p->p_realtimer.it_value.tv_sec,
+ p->p_realtimer.it_value.tv_usec);
+#endif
+ if (timercmp(&p->p_realtimer.it_value, &time, <=))
+ panic("miscalculated (%ld.%ld <= %ld.%ld)",
+ p->p_realtimer.it_value.tv_sec,
+ p->p_realtimer.it_value.tv_usec,
+ time.tv_sec, time.tv_usec);
+ }
+ /*
+ * Don't need to check hzto() return value, here.
+ * callout_reset() does it for us.
+ */
+ callout_reset(&p->p_realit_ch,
+ hzto(&p->p_realtimer.it_value), realitexpire, p);
+ splx(s);
+ return;
+
+#if 0
for (;;) {
s = splclock();
timeradd(&p->p_realtimer.it_value,
@@ -649,7 +710,11 @@
return;
}
splx(s);
+#if (NWDOG > 0) || (NEXTWDOG > 0)
+ wdog_reset();
+#endif
}
+#endif
}
/*
----------------------------------------------------------
SAITOH Masanobu (masanobu@iij.ad.jp
msaitoh@netbsd.org)