Commit ca109491 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

hrtimer: removing all ur callback modes

Impact: cleanup, move all hrtimer processing into hardirq context

This is an attempt at removing some of the hrtimer complexity by
reducing the number of callback modes to 1.

This means that all hrtimer callback functions will be ran from HARD-irq
context.

I went through all the 30 odd hrtimer callback functions in the kernel
and saw only one that I'm not quite sure of, which is the one in
net/can/bcm.c - hence I'm CC-ing the folks responsible for that code.

Furthermore, the hrtimer core now calls callbacks directly with IRQs
disabled in case you try to enqueue an expired timer. If this timer is a
periodic timer (which should use hrtimer_forward() to advance its time)
then it might be possible to end up in an inf. recursive loop due to the
fact that hrtimer_forward() doesn't round up to the next timer
granularity, and therefore keeps on calling the callback - obviously
this needs a fix.

Aside from that, this seems to compile and actually boot on my dual core
test box - although I'm sure there are some bugs in, me not hitting any
makes me certain :-)
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ed313489
...@@ -697,7 +697,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) ...@@ -697,7 +697,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
struct ads7846 *ts = container_of(handle, struct ads7846, timer); struct ads7846 *ts = container_of(handle, struct ads7846, timer);
int status = 0; int status = 0;
spin_lock_irq(&ts->lock); spin_lock(&ts->lock);
if (unlikely(!get_pendown_state(ts) || if (unlikely(!get_pendown_state(ts) ||
device_suspended(&ts->spi->dev))) { device_suspended(&ts->spi->dev))) {
...@@ -728,7 +728,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) ...@@ -728,7 +728,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
dev_err(&ts->spi->dev, "spi_async --> %d\n", status); dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
} }
spin_unlock_irq(&ts->lock); spin_unlock(&ts->lock);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
......
...@@ -42,26 +42,6 @@ enum hrtimer_restart { ...@@ -42,26 +42,6 @@ enum hrtimer_restart {
HRTIMER_RESTART, /* Timer must be restarted */ HRTIMER_RESTART, /* Timer must be restarted */
}; };
/*
* hrtimer callback modes:
*
* HRTIMER_CB_SOFTIRQ: Callback must run in softirq context
* HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context
* Special mode for tick emulation and
* scheduler timer. Such timers are per
* cpu and not allowed to be migrated on
* cpu unplug.
* HRTIMER_CB_IRQSAFE_UNLOCKED: Callback should run in hardirq context
* with timer->base lock unlocked
* used for timers which call wakeup to
* avoid lock order problems with rq->lock
*/
enum hrtimer_cb_mode {
HRTIMER_CB_SOFTIRQ,
HRTIMER_CB_IRQSAFE_PERCPU,
HRTIMER_CB_IRQSAFE_UNLOCKED,
};
/* /*
* Values to track state of the timer * Values to track state of the timer
* *
...@@ -70,7 +50,6 @@ enum hrtimer_cb_mode { ...@@ -70,7 +50,6 @@ enum hrtimer_cb_mode {
* 0x00 inactive * 0x00 inactive
* 0x01 enqueued into rbtree * 0x01 enqueued into rbtree
* 0x02 callback function running * 0x02 callback function running
* 0x04 callback pending (high resolution mode)
* *
* Special cases: * Special cases:
* 0x03 callback function running and enqueued * 0x03 callback function running and enqueued
...@@ -92,8 +71,7 @@ enum hrtimer_cb_mode { ...@@ -92,8 +71,7 @@ enum hrtimer_cb_mode {
#define HRTIMER_STATE_INACTIVE 0x00 #define HRTIMER_STATE_INACTIVE 0x00
#define HRTIMER_STATE_ENQUEUED 0x01 #define HRTIMER_STATE_ENQUEUED 0x01
#define HRTIMER_STATE_CALLBACK 0x02 #define HRTIMER_STATE_CALLBACK 0x02
#define HRTIMER_STATE_PENDING 0x04 #define HRTIMER_STATE_MIGRATE 0x04
#define HRTIMER_STATE_MIGRATE 0x08
/** /**
* struct hrtimer - the basic hrtimer structure * struct hrtimer - the basic hrtimer structure
...@@ -109,8 +87,6 @@ enum hrtimer_cb_mode { ...@@ -109,8 +87,6 @@ enum hrtimer_cb_mode {
* @function: timer expiry callback function * @function: timer expiry callback function
* @base: pointer to the timer base (per cpu and per clock) * @base: pointer to the timer base (per cpu and per clock)
* @state: state information (See bit values above) * @state: state information (See bit values above)
* @cb_mode: high resolution timer feature to select the callback execution
* mode
* @cb_entry: list head to enqueue an expired timer into the callback list * @cb_entry: list head to enqueue an expired timer into the callback list
* @start_site: timer statistics field to store the site where the timer * @start_site: timer statistics field to store the site where the timer
* was started * was started
...@@ -129,7 +105,6 @@ struct hrtimer { ...@@ -129,7 +105,6 @@ struct hrtimer {
struct hrtimer_clock_base *base; struct hrtimer_clock_base *base;
unsigned long state; unsigned long state;
struct list_head cb_entry; struct list_head cb_entry;
enum hrtimer_cb_mode cb_mode;
#ifdef CONFIG_TIMER_STATS #ifdef CONFIG_TIMER_STATS
int start_pid; int start_pid;
void *start_site; void *start_site;
...@@ -188,15 +163,11 @@ struct hrtimer_clock_base { ...@@ -188,15 +163,11 @@ struct hrtimer_clock_base {
* @check_clocks: Indictator, when set evaluate time source and clock * @check_clocks: Indictator, when set evaluate time source and clock
* event devices whether high resolution mode can be * event devices whether high resolution mode can be
* activated. * activated.
* @cb_pending: Expired timers are moved from the rbtree to this
* list in the timer interrupt. The list is processed
* in the softirq.
* @nr_events: Total number of timer interrupt events * @nr_events: Total number of timer interrupt events
*/ */
struct hrtimer_cpu_base { struct hrtimer_cpu_base {
spinlock_t lock; spinlock_t lock;
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
struct list_head cb_pending;
#ifdef CONFIG_HIGH_RES_TIMERS #ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next; ktime_t expires_next;
int hres_active; int hres_active;
...@@ -404,8 +375,7 @@ static inline int hrtimer_active(const struct hrtimer *timer) ...@@ -404,8 +375,7 @@ static inline int hrtimer_active(const struct hrtimer *timer)
*/ */
static inline int hrtimer_is_queued(struct hrtimer *timer) static inline int hrtimer_is_queued(struct hrtimer *timer)
{ {
return timer->state & return timer->state & HRTIMER_STATE_ENQUEUED;
(HRTIMER_STATE_ENQUEUED | HRTIMER_STATE_PENDING);
} }
/* /*
......
...@@ -251,9 +251,6 @@ enum ...@@ -251,9 +251,6 @@ enum
BLOCK_SOFTIRQ, BLOCK_SOFTIRQ,
TASKLET_SOFTIRQ, TASKLET_SOFTIRQ,
SCHED_SOFTIRQ, SCHED_SOFTIRQ,
#ifdef CONFIG_HIGH_RES_TIMERS
HRTIMER_SOFTIRQ,
#endif
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
NR_SOFTIRQS NR_SOFTIRQS
......
This diff is collapsed.
...@@ -203,7 +203,6 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) ...@@ -203,7 +203,6 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
hrtimer_init(&rt_b->rt_period_timer, hrtimer_init(&rt_b->rt_period_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_REL); CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rt_b->rt_period_timer.function = sched_rt_period_timer; rt_b->rt_period_timer.function = sched_rt_period_timer;
rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
} }
static inline int rt_bandwidth_enabled(void) static inline int rt_bandwidth_enabled(void)
...@@ -1139,7 +1138,6 @@ static void init_rq_hrtick(struct rq *rq) ...@@ -1139,7 +1138,6 @@ static void init_rq_hrtick(struct rq *rq)
hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rq->hrtick_timer.function = hrtick; rq->hrtick_timer.function = hrtick;
rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
} }
#else /* CONFIG_SCHED_HRTICK */ #else /* CONFIG_SCHED_HRTICK */
static inline void hrtick_clear(struct rq *rq) static inline void hrtick_clear(struct rq *rq)
......
...@@ -131,7 +131,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) ...@@ -131,7 +131,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
{ {
enum hrtimer_restart res = HRTIMER_NORESTART; enum hrtimer_restart res = HRTIMER_NORESTART;
write_seqlock_irq(&xtime_lock); write_seqlock(&xtime_lock);
switch (time_state) { switch (time_state) {
case TIME_OK: case TIME_OK:
...@@ -164,7 +164,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) ...@@ -164,7 +164,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
} }
update_vsyscall(&xtime, clock); update_vsyscall(&xtime, clock);
write_sequnlock_irq(&xtime_lock); write_sequnlock(&xtime_lock);
return res; return res;
} }
......
...@@ -681,7 +681,6 @@ void tick_setup_sched_timer(void) ...@@ -681,7 +681,6 @@ void tick_setup_sched_timer(void)
*/ */
hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
ts->sched_timer.function = tick_sched_timer; ts->sched_timer.function = tick_sched_timer;
ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
/* Get the next period (per cpu) */ /* Get the next period (per cpu) */
hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update());
......
...@@ -202,7 +202,6 @@ static void start_stack_timer(int cpu) ...@@ -202,7 +202,6 @@ static void start_stack_timer(int cpu)
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = stack_trace_timer_fn; hrtimer->function = stack_trace_timer_fn;
hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL); hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL);
} }
......
...@@ -96,7 +96,6 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) ...@@ -96,7 +96,6 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
return -EINVAL; return -EINVAL;
hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ;
pcsp_chip.timer.function = pcsp_do_timer; pcsp_chip.timer.function = pcsp_do_timer;
card = snd_card_new(index, id, THIS_MODULE, 0); card = snd_card_new(index, id, THIS_MODULE, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment