Make timecounters more resistant to badly behaved SW/HW which locks

out interrupts for too long.  If you still see the "calcru: negative
time..." message you can increase NTIMECOUNTER (see LINT).

Sideeffect is that a timecounter is required to not wrap around in
less than (1 + delta) seconds instead of the (1/hz + delta) required
until now.

Many thanks to: msmith, wpaul, wosch & bde
This commit is contained in:
phk 1998-11-23 09:59:02 +00:00
parent ba9fb96ddb
commit 1ca888b5fd
6 changed files with 65 additions and 24 deletions

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.503 1998/11/11 21:29:09 msmith Exp $
# $Id: LINT,v 1.504 1998/11/15 20:08:49 eivind Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -792,6 +792,14 @@ options "TUNE_1542"
options PPS_SYNC
# If you see the "calcru: negative time of %ld usec for pid %d (%s)\n"
# message you probably have some broken sw/hw which disables interrupts
# for too long. You can make the system more resistant to this by
# choosing a high value for NTIMECOUNTER. The default is 5, there
# is no upper limit but more than a couple of hundred are not productive.
options "NTIMECOUNTER=20"
# Enable PnP support in the kernel. This allows you to automaticly
# attach to PnP cards for drivers that support it and allows you to
# configure cards from USERCONFIG. See pnp(4) for more info.

View File

@ -1,4 +1,4 @@
# $Id: options,v 1.106 1998/10/28 08:37:10 dfr Exp $
# $Id: options,v 1.107 1998/11/05 14:28:17 dg Exp $
#
# On the handling of kernel options
#
@ -54,6 +54,7 @@ KTRACE
MD5
MFS_ROOT opt_mfs.h
MFS_ROOT_SIZE opt_mfs.h
NTIMECOUNTER opt_ntp.h
EXPORTMFS opt_mfs.h
NO_LKM
NSWAPDEV opt_swap.h

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.503 1998/11/11 21:29:09 msmith Exp $
# $Id: LINT,v 1.504 1998/11/15 20:08:49 eivind Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -792,6 +792,14 @@ options "TUNE_1542"
options PPS_SYNC
# If you see the "calcru: negative time of %ld usec for pid %d (%s)\n"
# message you probably have some broken sw/hw which disables interrupts
# for too long. You can make the system more resistant to this by
# choosing a high value for NTIMECOUNTER. The default is 5, there
# is no upper limit but more than a couple of hundred are not productive.
options "NTIMECOUNTER=20"
# Enable PnP support in the kernel. This allows you to automaticly
# attach to PnP cards for drivers that support it and allows you to
# configure cards from USERCONFIG. See pnp(4) for more info.

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.503 1998/11/11 21:29:09 msmith Exp $
# $Id: LINT,v 1.504 1998/11/15 20:08:49 eivind Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -792,6 +792,14 @@ options "TUNE_1542"
options PPS_SYNC
# If you see the "calcru: negative time of %ld usec for pid %d (%s)\n"
# message you probably have some broken sw/hw which disables interrupts
# for too long. You can make the system more resistant to this by
# choosing a high value for NTIMECOUNTER. The default is 5, there
# is no upper limit but more than a couple of hundred are not productive.
options "NTIMECOUNTER=20"
# Enable PnP support in the kernel. This allows you to automaticly
# attach to PnP cards for drivers that support it and allows you to
# configure cards from USERCONFIG. See pnp(4) for more info.

View File

@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
* $Id: kern_clock.c,v 1.83 1998/10/26 06:13:18 bde Exp $
* $Id: kern_clock.c,v 1.84 1998/11/23 09:34:19 sos Exp $
*/
#include <sys/param.h>
@ -67,11 +67,14 @@
#include <machine/smp.h>
#endif
/* This is where the NTIMECOUNTER option hangs out */
#include "opt_ntp.h"
/*
* Number of timecounters used to implement stable storage
*/
#ifndef NTIMECOUNTER
#define NTIMECOUNTER 2
#define NTIMECOUNTER 5
#endif
static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter",
@ -80,7 +83,7 @@ static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter",
static void initclocks __P((void *dummy));
SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
static void tco_forward __P((void));
static void tco_forward __P((int force));
static void tco_setscales __P((struct timecounter *tc));
static __inline unsigned tco_delta __P((struct timecounter *tc));
@ -222,7 +225,7 @@ hardclock(frame)
if (stathz == 0)
statclock(frame);
tco_forward();
tco_forward(0);
ticks++;
/*
@ -624,14 +627,14 @@ microuptime(struct timeval *tv)
}
void
nanouptime(struct timespec *tv)
nanouptime(struct timespec *ts)
{
unsigned count;
u_int64_t delta;
struct timecounter *tc;
tc = (struct timecounter *)timecounter;
tv->tv_sec = tc->tc_offset_sec;
ts->tv_sec = tc->tc_offset_sec;
count = tco_delta(tc);
delta = tc->tc_offset_nano;
delta += ((u_int64_t)count * tc->tc_scale_nano_f);
@ -639,9 +642,9 @@ nanouptime(struct timespec *tv)
delta += ((u_int64_t)count * tc->tc_scale_nano_i);
if (delta >= 1000000000) {
delta -= 1000000000;
tv->tv_sec++;
ts->tv_sec++;
}
tv->tv_nsec = delta;
ts->tv_nsec = delta;
}
static void
@ -709,7 +712,7 @@ set_timecounter(struct timespec *ts)
boottime.tv_sec--;
}
/* fiddle all the little crinkly bits around the fiords... */
tco_forward();
tco_forward(1);
}
@ -757,7 +760,7 @@ sync_other_counter(void)
}
static void
tco_forward(void)
tco_forward(int force)
{
struct timecounter *tc, *tco;
@ -777,6 +780,7 @@ tco_forward(void)
if (timedelta != 0) {
tc->tc_offset_nano += (u_int64_t)(tickdelta * 1000) << 32;
timedelta -= tickdelta;
force++;
}
while (tc->tc_offset_nano >= 1000000000ULL << 32) {
@ -786,8 +790,12 @@ tco_forward(void)
tc->tc_adjustment = tc->tc_tweak->tc_adjustment;
ntp_update_second(tc); /* XXX only needed if xntpd runs */
tco_setscales(tc);
force++;
}
if (!force)
return;
tc->tc_offset_micro = (tc->tc_offset_nano / 1000) >> 32;
/* Figure out the wall-clock time */

View File

@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
* $Id: kern_clock.c,v 1.83 1998/10/26 06:13:18 bde Exp $
* $Id: kern_clock.c,v 1.84 1998/11/23 09:34:19 sos Exp $
*/
#include <sys/param.h>
@ -67,11 +67,14 @@
#include <machine/smp.h>
#endif
/* This is where the NTIMECOUNTER option hangs out */
#include "opt_ntp.h"
/*
* Number of timecounters used to implement stable storage
*/
#ifndef NTIMECOUNTER
#define NTIMECOUNTER 2
#define NTIMECOUNTER 5
#endif
static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter",
@ -80,7 +83,7 @@ static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter",
static void initclocks __P((void *dummy));
SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
static void tco_forward __P((void));
static void tco_forward __P((int force));
static void tco_setscales __P((struct timecounter *tc));
static __inline unsigned tco_delta __P((struct timecounter *tc));
@ -222,7 +225,7 @@ hardclock(frame)
if (stathz == 0)
statclock(frame);
tco_forward();
tco_forward(0);
ticks++;
/*
@ -624,14 +627,14 @@ microuptime(struct timeval *tv)
}
void
nanouptime(struct timespec *tv)
nanouptime(struct timespec *ts)
{
unsigned count;
u_int64_t delta;
struct timecounter *tc;
tc = (struct timecounter *)timecounter;
tv->tv_sec = tc->tc_offset_sec;
ts->tv_sec = tc->tc_offset_sec;
count = tco_delta(tc);
delta = tc->tc_offset_nano;
delta += ((u_int64_t)count * tc->tc_scale_nano_f);
@ -639,9 +642,9 @@ nanouptime(struct timespec *tv)
delta += ((u_int64_t)count * tc->tc_scale_nano_i);
if (delta >= 1000000000) {
delta -= 1000000000;
tv->tv_sec++;
ts->tv_sec++;
}
tv->tv_nsec = delta;
ts->tv_nsec = delta;
}
static void
@ -709,7 +712,7 @@ set_timecounter(struct timespec *ts)
boottime.tv_sec--;
}
/* fiddle all the little crinkly bits around the fiords... */
tco_forward();
tco_forward(1);
}
@ -757,7 +760,7 @@ sync_other_counter(void)
}
static void
tco_forward(void)
tco_forward(int force)
{
struct timecounter *tc, *tco;
@ -777,6 +780,7 @@ tco_forward(void)
if (timedelta != 0) {
tc->tc_offset_nano += (u_int64_t)(tickdelta * 1000) << 32;
timedelta -= tickdelta;
force++;
}
while (tc->tc_offset_nano >= 1000000000ULL << 32) {
@ -786,8 +790,12 @@ tco_forward(void)
tc->tc_adjustment = tc->tc_tweak->tc_adjustment;
ntp_update_second(tc); /* XXX only needed if xntpd runs */
tco_setscales(tc);
force++;
}
if (!force)
return;
tc->tc_offset_micro = (tc->tc_offset_nano / 1000) >> 32;
/* Figure out the wall-clock time */