Dear RT folks! I'm pleased to announce the v3.18.9-rt4 patch set. Changes since v3.18.9-rt3 - The patch "rwsem-rt: Do not allow readers to nest" has been reverted. This means cpufreq works again. - A fix in sound/audio to not disable interrupts as part of the locking. (Mike Galbraith) - A fix in NFS which caused " sleeping function called from invalid context" warnings (Mike Galbraith) - Thermal wake ups on X86 are now handled defred into thread context (Daniel Wagner) - A ifdefs in lockdep self-test to avoid long "defined but not used" compiler warnings (Josh Cartwright) - Fixed dead-lock handling of the ww_mutex (Mike Galbraith) - The primary handler of mmc/sdhci is moved into the threaded one to avoid taking sleeping locks in IRQ contet. (Reported by Michal Šmucr) - The IRQ-work handling has been updated to get rid of the warning triggered in FULL_NO_HZ mode (Reported by Carsten Emde & Luis Claudio R. Goncalves) - "rcu torture" now compiles if enabled (Luis Claudio R. Goncalves) - "Simple work queue" now disables interrupts during list handling - The MCE check now uses the "Simple work queue" instead of its own thread for defered work (Daniel Wagner) Known issues: - bcache is disabled. - lazy preempt on x86_64 leads to a crash with some load. - CPU hotplug works in general. Steven's test script however deadlocks usually on the second invocation. - xor / raid_pq I had max latency jumping up to 67563us on one CPU while the next lower max was 58us. I tracked it down to module's init code of xor and raid_pq. Both disable preemption while measuring the measuring the performance of the individual implementation. The delta patch against 3.18.9-rt3 is appended below and can be found here: https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/incr/patch-3.18.9-rt3-rt4.patch.xz The RT patch against 3.18.9 can be found here: https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/patch-3.18.9-rt4.patch.xz The split quilt queue is available at: https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/patches-3.18.9-rt4.tar.xz Sebastian diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 718fc6cc6c64..d7f1c8316f94 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -18,7 +18,6 @@ #include <linux/rcupdate.h> #include <linux/kobject.h> #include <linux/uaccess.h> -#include <linux/kthread.h> #include <linux/kdebug.h> #include <linux/kernel.h> #include <linux/percpu.h> @@ -43,6 +42,7 @@ #include <linux/irq_work.h> #include <linux/export.h> #include <linux/jiffies.h> +#include <linux/work-simple.h> #include <asm/processor.h> #include <asm/mce.h> @@ -1364,7 +1364,7 @@ static void mce_do_trigger(struct work_struct *work) static DECLARE_WORK(mce_trigger_work, mce_do_trigger); -static void __mce_notify_work(void) +static void __mce_notify_work(struct swork_event *event) { /* Not more than two messages every minute */ static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); @@ -1385,43 +1385,31 @@ static void __mce_notify_work(void) } #ifdef CONFIG_PREEMPT_RT_FULL -struct task_struct *mce_notify_helper; - -static int mce_notify_helper_thread(void *unused) -{ - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (kthread_should_stop()) - break; - __mce_notify_work(); - } - return 0; -} +static bool notify_work_ready __read_mostly; +static struct swork_event notify_work; static int mce_notify_work_init(void) { - mce_notify_helper = kthread_run(mce_notify_helper_thread, NULL, - "mce-notify"); - if (!mce_notify_helper) - return -ENOMEM; + int err; + + err = swork_get(); + if (err) + return err; + INIT_SWORK(¬ify_work, __mce_notify_work); + notify_work_ready = true; return 0; } static void mce_notify_work(void) { - if (WARN_ON_ONCE(!mce_notify_helper)) { - pr_info(HW_ERR "Machine check event before MCE init; ignored\n"); - return; - } - - wake_up_process(mce_notify_helper); + if (notify_work_ready) + swork_queue(¬ify_work); } #else static void mce_notify_work(void) { - __mce_notify_work(); + __mce_notify_work(NULL); } static inline int mce_notify_work_init(void) { return 0; } #endif @@ -2497,6 +2485,10 @@ static __init int mcheck_init_device(void) goto err_out; } + err = mce_notify_work_init(); + if (err) + goto err_out; + if (!zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL)) { err = -ENOMEM; goto err_out; @@ -2533,15 +2525,8 @@ static __init int mcheck_init_device(void) if (err) goto err_register; - err = mce_notify_work_init(); - if (err) - goto err_notify; - return 0; -err_notify: - misc_deregister(&mce_chrdev_device); - err_register: unregister_syscore_ops(&mce_syscore_ops); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 023c2010cd75..bcde53774bc9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2565,6 +2565,31 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) return isr ? IRQ_HANDLED : IRQ_NONE; } +#ifdef CONFIG_PREEMPT_RT_BASE +static irqreturn_t sdhci_rt_irq(int irq, void *dev_id) +{ + irqreturn_t ret; + + local_bh_disable(); + ret = sdhci_irq(irq, dev_id); + local_bh_enable(); + if (ret == IRQ_WAKE_THREAD) + ret = sdhci_thread_irq(irq, dev_id); + return ret; +} +#endif + +static int sdhci_req_irq(struct sdhci_host *host) +{ +#ifdef CONFIG_PREEMPT_RT_BASE + return request_threaded_irq(host->irq, NULL, sdhci_rt_irq, + IRQF_SHARED, mmc_hostname(host->mmc), host); +#else + return request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, + IRQF_SHARED, mmc_hostname(host->mmc), host); +#endif +} + /*****************************************************************************\ * * * Suspend/resume * @@ -2632,9 +2657,7 @@ int sdhci_resume_host(struct sdhci_host *host) } if (!device_may_wakeup(mmc_dev(host->mmc))) { - ret = request_threaded_irq(host->irq, sdhci_irq, - sdhci_thread_irq, IRQF_SHARED, - mmc_hostname(host->mmc), host); + ret = sdhci_req_irq(host); if (ret) return ret; } else { @@ -3253,8 +3276,7 @@ int sdhci_add_host(struct sdhci_host *host) sdhci_init(host, 0); - ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, - IRQF_SHARED, mmc_hostname(mmc), host); + ret = sdhci_req_irq(host); if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 9ea3d9d49ffc..e3c2663e0b1f 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -29,6 +29,7 @@ #include <linux/pm.h> #include <linux/thermal.h> #include <linux/debugfs.h> +#include <linux/work-simple.h> #include <asm/cpu_device_id.h> #include <asm/mce.h> @@ -352,7 +353,7 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work) } } -static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) +static void platform_thermal_notify_work(struct swork_event *event) { unsigned long flags; int cpu = smp_processor_id(); @@ -369,7 +370,7 @@ static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) pkg_work_scheduled[phy_id]) { disable_pkg_thres_interrupt(); spin_unlock_irqrestore(&pkg_work_lock, flags); - return -EINVAL; + return; } pkg_work_scheduled[phy_id] = 1; spin_unlock_irqrestore(&pkg_work_lock, flags); @@ -378,9 +379,48 @@ static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) schedule_delayed_work_on(cpu, &per_cpu(pkg_temp_thermal_threshold_work, cpu), msecs_to_jiffies(notify_delay_ms)); +} + +#ifdef CONFIG_PREEMPT_RT_FULL +static struct swork_event notify_work; + +static int thermal_notify_work_init(void) +{ + int err; + + err = swork_get(); + if (err) + return err; + + INIT_SWORK(¬ify_work, platform_thermal_notify_work); return 0; } +static void thermal_notify_work_cleanup(void) +{ + swork_put(); +} + +static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) +{ + swork_queue(¬ify_work); + return 0; +} + +#else /* !CONFIG_PREEMPT_RT_FULL */ + +static int thermal_notify_work_init(void) { return 0; } + +static int thermal_notify_work_cleanup(void) { } + +static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) +{ + platform_thermal_notify_work(NULL); + + return 0; +} +#endif /* CONFIG_PREEMPT_RT_FULL */ + static int find_siblings_cpu(int cpu) { int i; @@ -584,6 +624,9 @@ static int __init pkg_temp_thermal_init(void) if (!x86_match_cpu(pkg_temp_thermal_ids)) return -ENODEV; + if (!thermal_notify_work_init()) + return -ENODEV; + spin_lock_init(&pkg_work_lock); platform_thermal_package_notify = pkg_temp_thermal_platform_thermal_notify; @@ -608,7 +651,7 @@ static int __init pkg_temp_thermal_init(void) kfree(pkg_work_scheduled); platform_thermal_package_notify = NULL; platform_thermal_package_rate_control = NULL; - + thermal_notify_work_cleanup(); return -ENODEV; } @@ -633,6 +676,7 @@ static void __exit pkg_temp_thermal_exit(void) mutex_unlock(&phy_dev_list_mutex); platform_thermal_package_notify = NULL; platform_thermal_package_rate_control = NULL; + thermal_notify_work_cleanup(); for_each_online_cpu(i) cancel_delayed_work_sync( &per_cpu(pkg_temp_thermal_threshold_work, i)); diff --git a/include/linux/rwsem_rt.h b/include/linux/rwsem_rt.h index 0065b08fbb7a..924c2d274ab5 100644 --- a/include/linux/rwsem_rt.h +++ b/include/linux/rwsem_rt.h @@ -20,6 +20,7 @@ struct rw_semaphore { struct rt_mutex lock; + int read_depth; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 19c363a437bd..0c6491228b17 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -71,6 +71,8 @@ void __weak arch_irq_work_raise(void) */ bool irq_work_queue_on(struct irq_work *work, int cpu) { + bool raise_irqwork; + /* All work should have been flushed before going offline */ WARN_ON_ONCE(cpu_is_offline(cpu)); @@ -81,7 +83,19 @@ bool irq_work_queue_on(struct irq_work *work, int cpu) if (!irq_work_claim(work)) return false; - if (llist_add(&work->llnode, &per_cpu(raised_list, cpu))) +#ifdef CONFIG_PREEMPT_RT_FULL + if (work->flags & IRQ_WORK_HARD_IRQ) + raise_irqwork = llist_add(&work->llnode, + &per_cpu(hirq_work_list, cpu)); + else + raise_irqwork = llist_add(&work->llnode, + &per_cpu(lazy_list, cpu)); +#else + raise_irqwork = llist_add(&work->llnode, + &per_cpu(raised_list, cpu)); +#endif + + if (raise_irqwork) arch_send_call_function_single_ipi(cpu); return true; @@ -101,19 +115,14 @@ bool irq_work_queue(struct irq_work *work) #ifdef CONFIG_PREEMPT_RT_FULL if (work->flags & IRQ_WORK_HARD_IRQ) { - if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list))) { - if (work->flags & IRQ_WORK_LAZY) { - if (tick_nohz_tick_stopped()) - arch_irq_work_raise(); - } else { - arch_irq_work_raise(); - } - } - /* If the work is "lazy", handle it from next tick if any */ - } else if (work->flags & IRQ_WORK_LAZY) { + if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list))) + arch_irq_work_raise(); + } else { + if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list))) + arch_irq_work_raise(); + } #else if (work->flags & IRQ_WORK_LAZY) { -#endif if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && tick_nohz_tick_stopped()) arch_irq_work_raise(); @@ -121,6 +130,7 @@ bool irq_work_queue(struct irq_work *work) if (llist_add(&work->llnode, this_cpu_ptr(&raised_list))) arch_irq_work_raise(); } +#endif preempt_enable(); @@ -137,7 +147,8 @@ bool irq_work_needs_cpu(void) if (llist_empty(raised)) if (llist_empty(lazy)) - return false; + if (llist_empty(this_cpu_ptr(&hirq_work_list))) + return false; /* All work should have been flushed before going offline */ WARN_ON_ONCE(cpu_is_offline(smp_processor_id())); diff --git a/kernel/locking/rt.c b/kernel/locking/rt.c index eac2ddea9c45..73c55089fb93 100644 --- a/kernel/locking/rt.c +++ b/kernel/locking/rt.c @@ -322,7 +322,8 @@ EXPORT_SYMBOL(rt_up_write); void rt_up_read(struct rw_semaphore *rwsem) { rwsem_release(&rwsem->dep_map, 1, _RET_IP_); - rt_mutex_unlock(&rwsem->lock); + if (--rwsem->read_depth == 0) + rt_mutex_unlock(&rwsem->lock); } EXPORT_SYMBOL(rt_up_read); @@ -333,6 +334,7 @@ EXPORT_SYMBOL(rt_up_read); void rt_downgrade_write(struct rw_semaphore *rwsem) { BUG_ON(rt_mutex_owner(&rwsem->lock) != current); + rwsem->read_depth = 1; } EXPORT_SYMBOL(rt_downgrade_write); @@ -361,7 +363,7 @@ void rt_down_write_nested(struct rw_semaphore *rwsem, int subclass) EXPORT_SYMBOL(rt_down_write_nested); void rt_down_write_nested_lock(struct rw_semaphore *rwsem, - struct lockdep_map *nest) + struct lockdep_map *nest) { rwsem_acquire_nest(&rwsem->dep_map, 0, 0, nest, _RET_IP_); rt_mutex_lock(&rwsem->lock); @@ -370,20 +372,36 @@ EXPORT_SYMBOL(rt_down_write_nested_lock); int rt_down_read_trylock(struct rw_semaphore *rwsem) { - int ret; + struct rt_mutex *lock = &rwsem->lock; + int ret = 1; - ret = rt_mutex_trylock(&rwsem->lock); - if (ret) - rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); + /* + * recursive read locks succeed when current owns the rwsem, + * but not when read_depth == 0 which means that the rwsem is + * write locked. + */ + if (rt_mutex_owner(lock) != current) + ret = rt_mutex_trylock(&rwsem->lock); + else if (!rwsem->read_depth) + ret = 0; + if (ret) { + rwsem->read_depth++; + rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); + } return ret; } EXPORT_SYMBOL(rt_down_read_trylock); static void __rt_down_read(struct rw_semaphore *rwsem, int subclass) { - rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_); - rt_mutex_lock(&rwsem->lock); + struct rt_mutex *lock = &rwsem->lock; + + rwsem_acquire_read(&rwsem->dep_map, subclass, 0, _RET_IP_); + + if (rt_mutex_owner(lock) != current) + rt_mutex_lock(&rwsem->lock); + rwsem->read_depth++; } void rt_down_read(struct rw_semaphore *rwsem) @@ -408,6 +426,7 @@ void __rt_rwsem_init(struct rw_semaphore *rwsem, const char *name, debug_check_no_locks_freed((void *)rwsem, sizeof(*rwsem)); lockdep_init_map(&rwsem->dep_map, name, key, 0); #endif + rwsem->read_depth = 0; rwsem->lock.save_state = 0; } EXPORT_SYMBOL(__rt_rwsem_init); diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index e257819480a9..397373da53d2 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -1695,15 +1695,21 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, ret = task_blocks_on_rt_mutex(lock, &waiter, current, chwalk); if (likely(!ret)) - ret = __rt_mutex_slowlock(lock, state, timeout, &waiter, - ww_ctx); + ret = __rt_mutex_slowlock(lock, state, timeout, &waiter, ww_ctx); + else if (ww_ctx) { + /* ww_mutex received EDEADLK, let it become EALREADY */ + ret = __mutex_lock_check_stamp(lock, ww_ctx); + BUG_ON(!ret); + } set_current_state(TASK_RUNNING); if (unlikely(ret)) { if (rt_mutex_has_waiters(lock)) remove_waiter(lock, &waiter); - rt_mutex_handle_deadlock(ret, chwalk, &waiter); + /* ww_mutex want to report EDEADLK/EALREADY, let them */ + if (!ww_ctx) + rt_mutex_handle_deadlock(ret, chwalk, &waiter); } else if (ww_ctx) { ww_mutex_account_lock(lock, ww_ctx); } @@ -2244,8 +2250,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ww_c might_sleep(); mutex_acquire_nest(&lock->base.dep_map, 0, 0, &ww_ctx->dep_map, _RET_IP_); - ret = rt_mutex_slowlock(&lock->base.lock, TASK_INTERRUPTIBLE, NULL, - RT_MUTEX_FULL_CHAINWALK, ww_ctx); + ret = rt_mutex_slowlock(&lock->base.lock, TASK_INTERRUPTIBLE, NULL, 0, ww_ctx); if (ret) mutex_release(&lock->base.dep_map, 1, _RET_IP_); else if (!ret && ww_ctx->acquired > 1) @@ -2263,8 +2268,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx) might_sleep(); mutex_acquire_nest(&lock->base.dep_map, 0, 0, &ww_ctx->dep_map, _RET_IP_); - ret = rt_mutex_slowlock(&lock->base.lock, TASK_UNINTERRUPTIBLE, NULL, - RT_MUTEX_FULL_CHAINWALK, ww_ctx); + ret = rt_mutex_slowlock(&lock->base.lock, TASK_UNINTERRUPTIBLE, NULL, 0, ww_ctx); if (ret) mutex_release(&lock->base.dep_map, 1, _RET_IP_); else if (!ret && ww_ctx->acquired > 1) @@ -2276,11 +2280,13 @@ EXPORT_SYMBOL_GPL(__ww_mutex_lock); void __sched ww_mutex_unlock(struct ww_mutex *lock) { + int nest = !!lock->ctx; + /* * The unlocking fastpath is the 0->1 transition from 'locked' * into 'unlocked' state: */ - if (lock->ctx) { + if (nest) { #ifdef CONFIG_DEBUG_MUTEXES DEBUG_LOCKS_WARN_ON(!lock->ctx->acquired); #endif @@ -2289,7 +2295,7 @@ void __sched ww_mutex_unlock(struct ww_mutex *lock) lock->ctx = NULL; } - mutex_release(&lock->base.dep_map, 1, _RET_IP_); + mutex_release(&lock->base.dep_map, nest, _RET_IP_); rt_mutex_unlock(&lock->base.lock); } EXPORT_SYMBOL(ww_mutex_unlock); diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a4e9e258bfe8..6aae258f9f62 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -378,6 +378,12 @@ void rcu_bh_force_quiescent_state(void) force_quiescent_state(&rcu_bh_state); } EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state); + +#else +void rcu_force_quiescent_state(void) +{ +} +EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); #endif /* diff --git a/kernel/sched/work-simple.c b/kernel/sched/work-simple.c index 0b2fa5ac88c8..c996f755dba6 100644 --- a/kernel/sched/work-simple.c +++ b/kernel/sched/work-simple.c @@ -33,9 +33,9 @@ static bool swork_readable(struct sworker *worker) if (kthread_should_stop()) return true; - raw_spin_lock(&worker->lock); + raw_spin_lock_irq(&worker->lock); r = !list_empty(&worker->events); - raw_spin_unlock(&worker->lock); + raw_spin_unlock_irq(&worker->lock); return r; } @@ -44,32 +44,28 @@ static int swork_kthread(void *arg) { struct sworker *worker = arg; - pr_info("swork_kthread enter\n"); - for (;;) { swait_event_interruptible(worker->wq, swork_readable(worker)); if (kthread_should_stop()) break; - raw_spin_lock(&worker->lock); + raw_spin_lock_irq(&worker->lock); while (!list_empty(&worker->events)) { struct swork_event *sev; sev = list_first_entry(&worker->events, struct swork_event, item); list_del(&sev->item); - raw_spin_unlock(&worker->lock); + raw_spin_unlock_irq(&worker->lock); WARN_ON_ONCE(!test_and_clear_bit(SWORK_EVENT_PENDING, &sev->flags)); sev->func(sev); - raw_spin_lock(&worker->lock); + raw_spin_lock_irq(&worker->lock); } - raw_spin_unlock(&worker->lock); + raw_spin_unlock_irq(&worker->lock); } - - pr_info("swork_kthread exit\n"); return 0; } @@ -111,14 +107,14 @@ static void swork_destroy(struct sworker *worker) */ bool swork_queue(struct swork_event *sev) { + unsigned long flags; + if (test_and_set_bit(SWORK_EVENT_PENDING, &sev->flags)) return false; - WARN_ON(irqs_disabled()); - - raw_spin_lock(&glob_worker->lock); + raw_spin_lock_irqsave(&glob_worker->lock, flags); list_add_tail(&sev->item, &glob_worker->events); - raw_spin_unlock(&glob_worker->lock); + raw_spin_unlock_irqrestore(&glob_worker->lock, flags); swait_wake(&glob_worker->wq); return true; diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index 19ae2366a7a9..b93a6103fa4d 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -590,6 +590,8 @@ GENERATE_TESTCASE(init_held_rsem) #include "locking-selftest-spin-hardirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin) +#ifndef CONFIG_PREEMPT_RT_FULL + #include "locking-selftest-rlock-hardirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock) @@ -605,9 +607,12 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock) #include "locking-selftest-wlock-softirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_wlock) +#endif + #undef E1 #undef E2 +#ifndef CONFIG_PREEMPT_RT_FULL /* * Enabling hardirqs with a softirq-safe lock held: */ @@ -640,6 +645,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock) #undef E1 #undef E2 +#endif + /* * Enabling irqs with an irq-safe lock held: */ @@ -663,6 +670,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock) #include "locking-selftest-spin-hardirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin) +#ifndef CONFIG_PREEMPT_RT_FULL + #include "locking-selftest-rlock-hardirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock) @@ -678,6 +687,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock) #include "locking-selftest-wlock-softirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock) +#endif + #undef E1 #undef E2 @@ -709,6 +720,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock) #include "locking-selftest-spin-hardirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin) +#ifndef CONFIG_PREEMPT_RT_FULL + #include "locking-selftest-rlock-hardirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock) @@ -724,6 +737,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock) #include "locking-selftest-wlock-softirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock) +#endif + #undef E1 #undef E2 #undef E3 @@ -757,6 +772,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock) #include "locking-selftest-spin-hardirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin) +#ifndef CONFIG_PREEMPT_RT_FULL + #include "locking-selftest-rlock-hardirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock) @@ -772,10 +789,14 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock) #include "locking-selftest-wlock-softirq.h" GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock) +#endif + #undef E1 #undef E2 #undef E3 +#ifndef CONFIG_PREEMPT_RT_FULL + /* * read-lock / write-lock irq inversion. * @@ -838,6 +859,10 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock) #undef E2 #undef E3 +#endif + +#ifndef CONFIG_PREEMPT_RT_FULL + /* * read-lock / write-lock recursion that is actually safe. */ @@ -876,6 +901,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) #undef E2 #undef E3 +#endif + /* * read-lock / write-lock recursion that is unsafe. */ diff --git a/localversion-rt b/localversion-rt index 1445cd65885c..ad3da1bcab7e 100644 --- a/localversion-rt +++ b/localversion-rt @@ -1 +1 @@ --rt3 +-rt4 diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index c179ca2a5aa4..ac93e74d5515 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -357,7 +357,7 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt) return; } - cpu = get_cpu(); + cpu = get_cpu_light(); pool = svc_pool_for_cpu(xprt->xpt_server, cpu); spin_lock_bh(&pool->sp_lock); @@ -390,7 +390,7 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt) } spin_unlock_bh(&pool->sp_lock); - put_cpu(); + put_cpu_light(); } /* diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 166d59cdc86b..8854164197e5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -104,7 +104,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) { if (!substream->pcm->nonatomic) - local_irq_disable(); + local_irq_disable_nort(); snd_pcm_stream_lock(substream); } EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); @@ -113,7 +113,7 @@ void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) { snd_pcm_stream_unlock(substream); if (!substream->pcm->nonatomic) - local_irq_enable(); + local_irq_enable_nort(); } EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); @@ -121,7 +121,7 @@ unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) { unsigned long flags = 0; if (!substream->pcm->nonatomic) - local_irq_save(flags); + local_irq_save_nort(flags); snd_pcm_stream_lock(substream); return flags; } @@ -132,7 +132,7 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, { snd_pcm_stream_unlock(substream); if (!substream->pcm->nonatomic) - local_irq_restore(flags); + local_irq_restore_nort(flags); } EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html