From: Thomas Gleixner <tglx@linutronix.de>
To: Andrew Morton <akpm@osdl.org>
Cc: LKML <linux-kernel@vger.kernel.org>, Ingo Molnar <mingo@elte.hu>,
Len Brown <lenb@kernel.org>, John Stultz <johnstul@us.ibm.com>,
Arjan van de Ven <arjan@infradead.org>, Andi Kleen <ak@suse.de>,
Roman Zippel <zippel@linux-m68k.org>
Subject: [patch 01/19] hrtimers: state tracking
Date: Thu, 09 Nov 2006 23:38:17 -0000 [thread overview]
Message-ID: <20061109233034.182462000@cruncher.tec.linutronix.de> (raw)
In-Reply-To: <20061109233030.915859000@cruncher.tec.linutronix.de>
[-- Attachment #1: hrtimers-state-tracking.patch --]
[-- Type: text/plain, Size: 6381 bytes --]
From: Thomas Gleixner <tglx@linutronix.de>
Reintroduce ktimers feature "optimized away" by the ktimers review process:
multiple hrtimer states to enable the running of hrtimers without holding the
cpu-base-lock.
(The "optimized" rbtree hack carried only 2 states worth of information and we
need 4 for high resolution timers and dynamic ticks.)
Build-fixes-from: Andrew Morton <akpm@osdl.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Index: linux-2.6.19-rc5-mm1/include/linux/hrtimer.h
===================================================================
--- linux-2.6.19-rc5-mm1.orig/include/linux/hrtimer.h 2006-11-09 21:06:05.000000000 +0100
+++ linux-2.6.19-rc5-mm1/include/linux/hrtimer.h 2006-11-09 21:06:07.000000000 +0100
@@ -40,6 +40,34 @@ enum hrtimer_restart {
HRTIMER_RESTART, /* Timer must be restarted */
};
+/*
+ * Bit values to track state of the timer
+ *
+ * Possible states:
+ *
+ * 0x00 inactive
+ * 0x01 enqueued into rbtree
+ * 0x02 callback function running
+ * 0x03 callback function running and enqueued
+ * (was requeued on another CPU)
+ *
+ * The "callback function running and enqueued" status is only possible on
+ * SMP. It happens for example when a posix timer expired and the callback
+ * queued a signal. Between dropping the lock which protects the posix timer
+ * and reacquiring the base lock of the hrtimer, another CPU can deliver the
+ * signal and rearm the timer. We have to preserve the callback running state,
+ * as otherwise the timer could be removed before the softirq code finishes the
+ * the handling of the timer.
+ *
+ * The HRTIMER_STATE_ENQUEUE bit is always or'ed to the current state to
+ * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario.
+ *
+ * All state transitions are protected by cpu_base->lock.
+ */
+#define HRTIMER_STATE_INACTIVE 0x00
+#define HRTIMER_STATE_ENQUEUED 0x01
+#define HRTIMER_STATE_CALLBACK 0x02
+
/**
* struct hrtimer - the basic hrtimer structure
* @node: red black tree node for time ordered insertion
@@ -48,6 +76,7 @@ enum hrtimer_restart {
* which the timer is based.
* @function: timer expiry callback function
* @base: pointer to the timer base (per cpu and per clock)
+ * @state: state information (See bit values above)
*
* The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
*/
@@ -56,6 +85,7 @@ struct hrtimer {
ktime_t expires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
+ unsigned long state;
};
/**
@@ -141,9 +171,13 @@ extern int hrtimer_get_res(const clockid
extern ktime_t hrtimer_get_next_event(void);
#endif
+/*
+ * A timer is active, when it is enqueued into the rbtree or the callback
+ * function is running.
+ */
static inline int hrtimer_active(const struct hrtimer *timer)
{
- return rb_parent(&timer->node) != &timer->node;
+ return timer->state != HRTIMER_STATE_INACTIVE;
}
/* Forward a hrtimer so it expires after now: */
Index: linux-2.6.19-rc5-mm1/kernel/hrtimer.c
===================================================================
--- linux-2.6.19-rc5-mm1.orig/kernel/hrtimer.c 2006-11-09 21:06:05.000000000 +0100
+++ linux-2.6.19-rc5-mm1/kernel/hrtimer.c 2006-11-09 21:06:07.000000000 +0100
@@ -235,6 +235,12 @@ lock_hrtimer_base(const struct hrtimer *
#endif /* !CONFIG_SMP */
+static inline int hrtimer_is_queued(struct hrtimer *timer)
+{
+ return timer->state != HRTIMER_STATE_INACTIVE &&
+ timer->state != HRTIMER_STATE_CALLBACK;
+}
+
/*
* Functions for the union type storage format of ktime_t which are
* too large for inlining:
@@ -385,6 +391,11 @@ static void enqueue_hrtimer(struct hrtim
*/
rb_link_node(&timer->node, parent, link);
rb_insert_color(&timer->node, &base->active);
+ /*
+ * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
+ * state of a possibly running callback.
+ */
+ timer->state |= HRTIMER_STATE_ENQUEUED;
if (!base->first || timer->expires.tv64 <
rb_entry(base->first, struct hrtimer, node)->expires.tv64)
@@ -397,7 +408,8 @@ static void enqueue_hrtimer(struct hrtim
* Caller must hold the base lock.
*/
static void __remove_hrtimer(struct hrtimer *timer,
- struct hrtimer_clock_base *base)
+ struct hrtimer_clock_base *base,
+ unsigned long newstate)
{
/*
* Remove the timer from the rbtree and replace the
@@ -406,7 +418,7 @@ static void __remove_hrtimer(struct hrti
if (base->first == &timer->node)
base->first = rb_next(&timer->node);
rb_erase(&timer->node, &base->active);
- rb_set_parent(&timer->node, &timer->node);
+ timer->state = newstate;
}
/*
@@ -415,8 +427,8 @@ static void __remove_hrtimer(struct hrti
static inline int
remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
{
- if (hrtimer_active(timer)) {
- __remove_hrtimer(timer, base);
+ if (hrtimer_is_queued(timer)) {
+ __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE);
return 1;
}
return 0;
@@ -488,7 +500,7 @@ int hrtimer_try_to_cancel(struct hrtimer
base = lock_hrtimer_base(timer, &flags);
- if (base->cpu_base->curr_timer != timer)
+ if (!(timer->state & HRTIMER_STATE_CALLBACK))
ret = remove_hrtimer(timer, base);
unlock_hrtimer_base(timer, &flags);
@@ -593,7 +605,6 @@ void hrtimer_init(struct hrtimer *timer,
clock_id = CLOCK_MONOTONIC;
timer->base = &cpu_base->clock_base[clock_id];
- rb_set_parent(&timer->node, &timer->node);
}
EXPORT_SYMBOL_GPL(hrtimer_init);
@@ -644,13 +655,14 @@ static inline void run_hrtimer_queue(str
fn = timer->function;
set_curr_timer(cpu_base, timer);
- __remove_hrtimer(timer, base);
+ __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK);
spin_unlock_irq(&cpu_base->lock);
restart = fn(timer);
spin_lock_irq(&cpu_base->lock);
+ timer->state &= ~HRTIMER_STATE_CALLBACK;
if (restart != HRTIMER_NORESTART) {
BUG_ON(hrtimer_active(timer));
enqueue_hrtimer(timer, base);
@@ -821,7 +833,8 @@ static void migrate_hrtimer_list(struct
while ((node = rb_first(&old_base->active))) {
timer = rb_entry(node, struct hrtimer, node);
- __remove_hrtimer(timer, old_base);
+ BUG_ON(timer->state & HRTIMER_STATE_CALLBACK);
+ __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE);
timer->base = new_base;
enqueue_hrtimer(timer, new_base);
}
--
next prev parent reply other threads:[~2006-11-09 23:44 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-09 23:38 [patch 00/21] Highres / dynticks drop in replacement for 2.6.19-rc5-mm1 Thomas Gleixner
2006-11-09 23:38 ` Thomas Gleixner [this message]
2006-11-10 9:19 ` [patch 01/19] hrtimers: state tracking Arjan van de Ven
2006-11-10 9:40 ` Andrew Morton
2006-11-10 9:45 ` Thomas Gleixner
2006-11-23 22:26 ` Roman Zippel
2006-11-09 23:38 ` [patch 02/19] hrtimers: clean up callback tracking Thomas Gleixner
2006-11-10 9:20 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 03/19] hrtimers: Move and add documentation Thomas Gleixner
2006-11-09 23:38 ` [patch 04/19] Add a framework to manage clock event devices Thomas Gleixner
2006-11-10 9:47 ` Arjan van de Ven
2006-11-23 22:36 ` Roman Zippel
2006-11-09 23:38 ` [patch 05/19] ACPI: Include apic.h Thomas Gleixner
2006-11-09 23:38 ` [patch 06/19] ACPI: Keep track of timer broadcast Thomas Gleixner
2006-11-10 9:51 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 07/19] ACPI: Add state propagation for dynamic broadcasting Thomas Gleixner
2006-11-10 9:52 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 08/19] i386: cleanup apic code Thomas Gleixner
2006-11-10 10:04 ` Arjan van de Ven
2006-11-10 10:16 ` Thomas Gleixner
2006-11-10 10:16 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 09/19] i386: Convert to clock event devices Thomas Gleixner
2006-11-10 10:10 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 10/19] PM_timer: allow early access and move externs to a header file Thomas Gleixner
2006-11-10 10:12 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 11/19] i386: Rework local APIC calibration Thomas Gleixner
2006-11-10 10:17 ` Arjan van de Ven
2006-11-10 10:23 ` Thomas Gleixner
2006-11-10 11:10 ` Ingo Molnar
2006-11-09 23:38 ` [patch 12/19] high-res timers: core Thomas Gleixner
2006-11-10 10:26 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 13/19] GTOD: Mark TSC unusable for highres timers Thomas Gleixner
2006-11-10 1:10 ` john stultz
2006-11-10 5:10 ` Andi Kleen
2006-11-10 8:10 ` Thomas Gleixner
2006-11-10 8:50 ` Andrew Morton
2006-11-10 8:57 ` Ingo Molnar
2006-11-10 9:13 ` Andrew Morton
2006-11-10 9:29 ` Andi Kleen
2006-11-11 11:14 ` Thomas Gleixner
2006-11-11 13:51 ` Andi Kleen
2006-11-11 13:58 ` Thomas Gleixner
2006-11-11 13:59 ` Andi Kleen
2006-11-11 14:08 ` Thomas Gleixner
2006-11-10 10:35 ` Arjan van de Ven
2006-11-10 10:47 ` Andi Kleen
2006-11-10 10:55 ` Arjan van de Ven
2006-11-10 11:13 ` Ingo Molnar
2006-11-10 11:28 ` Andi Kleen
2006-11-10 9:27 ` Andi Kleen
2006-11-10 10:14 ` Alan Cox
2006-11-10 11:19 ` Ingo Molnar
2006-11-10 15:43 ` Chris Friesen
2006-11-10 11:12 ` Pavel Machek
2006-11-10 11:48 ` Ingo Molnar
2006-11-10 11:56 ` Andi Kleen
2006-11-10 13:12 ` Ingo Molnar
2006-11-10 12:00 ` Pavel Machek
2006-11-10 13:14 ` Ingo Molnar
2006-11-10 11:11 ` Pavel Machek
2006-11-10 10:28 ` Arjan van de Ven
2006-11-10 10:30 ` Andi Kleen
2006-11-10 10:37 ` Arjan van de Ven
2006-11-09 23:38 ` [patch 14/19] dynticks: core code Thomas Gleixner
2006-11-09 23:38 ` [patch 15/19] dyntick: add nohz stats to /proc/stat Thomas Gleixner
2006-11-09 23:38 ` [patch 16/19] dynticks: i386 arch code Thomas Gleixner
2006-11-09 23:38 ` [patch 17/19] dynticks: Fix nmi watchdog Thomas Gleixner
2006-11-09 23:38 ` [patch 18/19] high-res timers, dynticks: enable i386 support Thomas Gleixner
2006-11-09 23:38 ` [patch 19/19] debugging feature: timer stats Thomas Gleixner
2006-11-23 22:24 ` [patch 00/21] Highres / dynticks drop in replacement for 2.6.19-rc5-mm1 Roman Zippel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061109233034.182462000@cruncher.tec.linutronix.de \
--to=tglx@linutronix.de \
--cc=ak@suse.de \
--cc=akpm@osdl.org \
--cc=arjan@infradead.org \
--cc=johnstul@us.ibm.com \
--cc=lenb@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=zippel@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®