Commit 609862be authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  lockdep: add stack dumps to asserts
  hrtimer: fix rq->lock inversion (again)
parents 12fe32e4 eedeeabd
...@@ -336,6 +336,11 @@ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, ...@@ -336,6 +336,11 @@ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
const enum hrtimer_mode mode); const enum hrtimer_mode mode);
extern int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, extern int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long range_ns, const enum hrtimer_mode mode); unsigned long range_ns, const enum hrtimer_mode mode);
extern int
__hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long delta_ns,
const enum hrtimer_mode mode, int wakeup);
extern int hrtimer_cancel(struct hrtimer *timer); extern int hrtimer_cancel(struct hrtimer *timer);
extern int hrtimer_try_to_cancel(struct hrtimer *timer); extern int hrtimer_try_to_cancel(struct hrtimer *timer);
......
...@@ -299,6 +299,7 @@ extern void softirq_init(void); ...@@ -299,6 +299,7 @@ extern void softirq_init(void);
#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0) #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
extern void raise_softirq_irqoff(unsigned int nr); extern void raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq(unsigned int nr); extern void raise_softirq(unsigned int nr);
extern void wakeup_softirqd(void);
/* This is the worklist that queues up per-cpu softirq work. /* This is the worklist that queues up per-cpu softirq work.
* *
......
...@@ -651,14 +651,20 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer) ...@@ -651,14 +651,20 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
* and expiry check is done in the hrtimer_interrupt or in the softirq. * and expiry check is done in the hrtimer_interrupt or in the softirq.
*/ */
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
struct hrtimer_clock_base *base) struct hrtimer_clock_base *base,
int wakeup)
{ {
if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
spin_unlock(&base->cpu_base->lock); if (wakeup) {
raise_softirq_irqoff(HRTIMER_SOFTIRQ); spin_unlock(&base->cpu_base->lock);
spin_lock(&base->cpu_base->lock); raise_softirq_irqoff(HRTIMER_SOFTIRQ);
spin_lock(&base->cpu_base->lock);
} else
__raise_softirq_irqoff(HRTIMER_SOFTIRQ);
return 1; return 1;
} }
return 0; return 0;
} }
...@@ -703,7 +709,8 @@ static inline int hrtimer_is_hres_enabled(void) { return 0; } ...@@ -703,7 +709,8 @@ static inline int hrtimer_is_hres_enabled(void) { return 0; }
static inline int hrtimer_switch_to_hres(void) { return 0; } static inline int hrtimer_switch_to_hres(void) { return 0; }
static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { } static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
struct hrtimer_clock_base *base) struct hrtimer_clock_base *base,
int wakeup)
{ {
return 0; return 0;
} }
...@@ -886,20 +893,9 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) ...@@ -886,20 +893,9 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
return 0; return 0;
} }
/** int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
* hrtimer_start_range_ns - (re)start an hrtimer on the current CPU unsigned long delta_ns, const enum hrtimer_mode mode,
* @timer: the timer to be added int wakeup)
* @tim: expiry time
* @delta_ns: "slack" range for the timer
* @mode: expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
*
* Returns:
* 0 on success
* 1 when the timer was active
*/
int
hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_ns,
const enum hrtimer_mode mode)
{ {
struct hrtimer_clock_base *base, *new_base; struct hrtimer_clock_base *base, *new_base;
unsigned long flags; unsigned long flags;
...@@ -940,12 +936,29 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n ...@@ -940,12 +936,29 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n
* XXX send_remote_softirq() ? * XXX send_remote_softirq() ?
*/ */
if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)) if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
hrtimer_enqueue_reprogram(timer, new_base); hrtimer_enqueue_reprogram(timer, new_base, wakeup);
unlock_hrtimer_base(timer, &flags); unlock_hrtimer_base(timer, &flags);
return ret; return ret;
} }
/**
* hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
* @timer: the timer to be added
* @tim: expiry time
* @delta_ns: "slack" range for the timer
* @mode: expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
*
* Returns:
* 0 on success
* 1 when the timer was active
*/
int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long delta_ns, const enum hrtimer_mode mode)
{
return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
}
EXPORT_SYMBOL_GPL(hrtimer_start_range_ns); EXPORT_SYMBOL_GPL(hrtimer_start_range_ns);
/** /**
...@@ -961,7 +974,7 @@ EXPORT_SYMBOL_GPL(hrtimer_start_range_ns); ...@@ -961,7 +974,7 @@ EXPORT_SYMBOL_GPL(hrtimer_start_range_ns);
int int
hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
{ {
return hrtimer_start_range_ns(timer, tim, 0, mode); return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
} }
EXPORT_SYMBOL_GPL(hrtimer_start); EXPORT_SYMBOL_GPL(hrtimer_start);
......
...@@ -793,6 +793,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) ...@@ -793,6 +793,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
printk("turning off the locking correctness validator.\n"); printk("turning off the locking correctness validator.\n");
dump_stack();
return NULL; return NULL;
} }
class = lock_classes + nr_lock_classes++; class = lock_classes + nr_lock_classes++;
...@@ -856,6 +857,7 @@ static struct lock_list *alloc_list_entry(void) ...@@ -856,6 +857,7 @@ static struct lock_list *alloc_list_entry(void)
printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n"); printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
printk("turning off the locking correctness validator.\n"); printk("turning off the locking correctness validator.\n");
dump_stack();
return NULL; return NULL;
} }
return list_entries + nr_list_entries++; return list_entries + nr_list_entries++;
...@@ -1682,6 +1684,7 @@ cache_hit: ...@@ -1682,6 +1684,7 @@ cache_hit:
printk("BUG: MAX_LOCKDEP_CHAINS too low!\n"); printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
printk("turning off the locking correctness validator.\n"); printk("turning off the locking correctness validator.\n");
dump_stack();
return 0; return 0;
} }
chain = lock_chains + nr_lock_chains++; chain = lock_chains + nr_lock_chains++;
...@@ -2541,6 +2544,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, ...@@ -2541,6 +2544,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
debug_locks_off(); debug_locks_off();
printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n"); printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n");
printk("turning off the locking correctness validator.\n"); printk("turning off the locking correctness validator.\n");
dump_stack();
return 0; return 0;
} }
...@@ -2637,6 +2641,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, ...@@ -2637,6 +2641,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
debug_locks_off(); debug_locks_off();
printk("BUG: MAX_LOCK_DEPTH too low!\n"); printk("BUG: MAX_LOCK_DEPTH too low!\n");
printk("turning off the locking correctness validator.\n"); printk("turning off the locking correctness validator.\n");
dump_stack();
return 0; return 0;
} }
......
...@@ -231,13 +231,20 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b) ...@@ -231,13 +231,20 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
spin_lock(&rt_b->rt_runtime_lock); spin_lock(&rt_b->rt_runtime_lock);
for (;;) { for (;;) {
unsigned long delta;
ktime_t soft, hard;
if (hrtimer_active(&rt_b->rt_period_timer)) if (hrtimer_active(&rt_b->rt_period_timer))
break; break;
now = hrtimer_cb_get_time(&rt_b->rt_period_timer); now = hrtimer_cb_get_time(&rt_b->rt_period_timer);
hrtimer_forward(&rt_b->rt_period_timer, now, rt_b->rt_period); hrtimer_forward(&rt_b->rt_period_timer, now, rt_b->rt_period);
hrtimer_start_expires(&rt_b->rt_period_timer,
HRTIMER_MODE_ABS); soft = hrtimer_get_softexpires(&rt_b->rt_period_timer);
hard = hrtimer_get_expires(&rt_b->rt_period_timer);
delta = ktime_to_ns(ktime_sub(hard, soft));
__hrtimer_start_range_ns(&rt_b->rt_period_timer, soft, delta,
HRTIMER_MODE_ABS, 0);
} }
spin_unlock(&rt_b->rt_runtime_lock); spin_unlock(&rt_b->rt_runtime_lock);
} }
...@@ -1146,7 +1153,8 @@ static __init void init_hrtick(void) ...@@ -1146,7 +1153,8 @@ static __init void init_hrtick(void)
*/ */
static void hrtick_start(struct rq *rq, u64 delay) static void hrtick_start(struct rq *rq, u64 delay)
{ {
hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), HRTIMER_MODE_REL); __hrtimer_start_range_ns(&rq->hrtick_timer, ns_to_ktime(delay), 0,
HRTIMER_MODE_REL, 0);
} }
static inline void init_hrtick(void) static inline void init_hrtick(void)
......
...@@ -65,7 +65,7 @@ char *softirq_to_name[NR_SOFTIRQS] = { ...@@ -65,7 +65,7 @@ char *softirq_to_name[NR_SOFTIRQS] = {
* to the pending events, so lets the scheduler to balance * to the pending events, so lets the scheduler to balance
* the softirq load for us. * the softirq load for us.
*/ */
static inline void wakeup_softirqd(void) void wakeup_softirqd(void)
{ {
/* Interrupts are disabled: no need to stop preemption */ /* Interrupts are disabled: no need to stop preemption */
struct task_struct *tsk = __get_cpu_var(ksoftirqd); struct task_struct *tsk = __get_cpu_var(ksoftirqd);
......
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