svn commit: r192327 - in user/kmacy/releng_7_2_fcs/sys: kern sys
Kip Macy
kmacy at FreeBSD.org
Mon May 18 19:01:33 UTC 2009
Author: kmacy
Date: Mon May 18 19:01:32 2009
New Revision: 192327
URL: http://svn.freebsd.org/changeset/base/192327
Log:
180608:
Fix a race which could result in some timeout buckets being skipped.
- When a tick occurs on a cpu, iterate from cs_softticks until ticks.
The per-cpu tick processing happens asynchronously with the actual
adjustment of the 'ticks' variable. Sometimes the results may
be visible before the local call and sometimes after. Previously this
could cause a one tick window where we didn't evaluate the bucket.
- In softclock fetch curticks before incrementing cc_softticks so we
don't skip insertions which were made for the current time.
Sponsored by: Nokia
181191
add callout_schedule; besides being useful it also improves
compatibility with other systems
Reviewed by: ed, battlez
184385
After a machine has been up for a bit more than 20 days with HZ=1000,
"ticks" goes negative. This breaks the signed comparison in softclock.
This causes sleep() to never wake up, tcp to stop, etc etc. This is
bad(TM). Use the SEQ_LT() method from tcp's sequence number comparisons.
Modified:
user/kmacy/releng_7_2_fcs/sys/kern/kern_timeout.c
user/kmacy/releng_7_2_fcs/sys/sys/callout.h
Modified: user/kmacy/releng_7_2_fcs/sys/kern/kern_timeout.c
==============================================================================
--- user/kmacy/releng_7_2_fcs/sys/kern/kern_timeout.c Mon May 18 18:54:43 2009 (r192326)
+++ user/kmacy/releng_7_2_fcs/sys/kern/kern_timeout.c Mon May 18 19:01:32 2009 (r192327)
@@ -222,19 +222,24 @@ SYSINIT(start_softclock, SI_SUB_SOFTINTR
void
callout_tick(void)
{
- int need_softclock = 0;
struct callout_cpu *cc;
+ int need_softclock;
+ int bucket;
/*
* Process callouts at a very low cpu priority, so we don't keep the
* relatively high clock interrupt priority any longer than necessary.
*/
+ need_softclock = 0;
cc = CC_SELF();
mtx_lock_spin_flags(&cc->cc_lock, MTX_QUIET);
- if (!TAILQ_EMPTY(&cc->cc_callwheel[ticks & callwheelmask])) {
- need_softclock = 1;
- } else if (cc->cc_softticks + 1 == ticks)
- ++cc->cc_softticks;
+ for (; (cc->cc_softticks - ticks) < 0; cc->cc_softticks++) {
+ bucket = cc->cc_softticks & callwheelmask;
+ if (!TAILQ_EMPTY(&cc->cc_callwheel[bucket])) {
+ need_softclock = 1;
+ break;
+ }
+ }
mtx_unlock_spin_flags(&cc->cc_lock, MTX_QUIET);
/*
* swi_sched acquires the thread lock, so we don't want to call it
@@ -308,12 +313,12 @@ softclock(void *arg)
cc = (struct callout_cpu *)arg;
CC_LOCK(cc);
while (cc->cc_softticks != ticks) {
- cc->cc_softticks++;
/*
* cc_softticks may be modified by hard clock, so cache
* it while we work on a given bucket.
*/
curticks = cc->cc_softticks;
+ cc->cc_softticks++;
bucket = &cc->cc_callwheel[curticks & callwheelmask];
c = TAILQ_FIRST(bucket);
while (c) {
@@ -612,6 +617,21 @@ retry:
return (cancelled);
}
+/*
+ * Common idioms that can be optimized in the future.
+ */
+int
+callout_schedule_on(struct callout *c, int to_ticks, int cpu)
+{
+ return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, cpu);
+}
+
+int
+callout_schedule(struct callout *c, int to_ticks)
+{
+ return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, c->c_cpu);
+}
+
int
_callout_stop_safe(c, safe)
struct callout *c;
Modified: user/kmacy/releng_7_2_fcs/sys/sys/callout.h
==============================================================================
--- user/kmacy/releng_7_2_fcs/sys/sys/callout.h Mon May 18 18:54:43 2009 (r192326)
+++ user/kmacy/releng_7_2_fcs/sys/sys/callout.h Mon May 18 19:01:32 2009 (r192327)
@@ -89,6 +89,10 @@ int callout_reset_on(struct callout *, i
callout_reset_on((c), (on_tick), (fn), (arg), (c)->c_cpu)
#define callout_reset_curcpu(c, on_tick, fn, arg) \
callout_reset_on((c), (on_tick), (fn), (arg), PCPU_GET(cpuid))
+int callout_schedule(struct callout *, int);
+int callout_schedule_on(struct callout *, int, int);
+#define callout_schedule_curcpu(c, on_tick) \
+ callout_schedule_on((c), (on_tick), PCPU_GET(cpuid))
#define callout_stop(c) _callout_stop_safe(c, 0)
int _callout_stop_safe(struct callout *, int);
void callout_tick(void);
More information about the svn-src-user
mailing list