cpu unplug with PREEMPT_LL
Subsystems (2)
PATCH 1/1 cpu unplug with PREEMPT_LL
With CONFIG_PREEMPT_LL, cpu unplug generates a bunch of
BUG: sleeping function called from invalid context BUG: scheduling while atomic
To reproduce the problem:
echo 0 > /sys/devices/system/cpu/cpu1/online
This patch is:
- UGLY
- lightly tested
- should maybe not be included in the RT patch set
but it may be useful to anyone determined to use cpu hotplug with PREEMPT_LL.
This patch was tested on 3.0.36-rt58 since that release has the latest hotplug patches. I will re-test this on 3.5-rtX when that is available.
Signed-off-by Frank Rowand <[email protected]>
---
include/linux/preempt.h | 4 4 + 0 - 0 ! include/linux/sched.h | 6 3 + 3 - 0 ! kernel/cpu.c | 12 12 + 0 - 0 ! kernel/sched.c | 18 17 + 1 - 0 ! 4 files changed, 36 insertions(+), 4 deletions(-)
include/linux/preempt.h +4 -0
@@ -122,6 +122,10 @@ do { \# define preempt_enable_nort () preempt_enable()# define migrate_disable () preempt_disable()# define migrate_enable () preempt_enable() +#ifdef CONFIG_PREEMPT_LL +extern void __migrate_disable (void ); +extern void __migrate_enable (void ); +#endif #endif #ifdef CONFIG_PREEMPT_NOTIFIERS
kernel/cpu.c +12 -0
@@ -500,11 +500,19 @@ static int __ref _cpu_down(unsigned intcpumask_andnot (cpumask, cpu_online_mask,cpumask_of (cpu));set_cpus_allowed_ptr (current, cpumask);free_cpumask_var (cpumask); +#ifdef CONFIG_PREEMPT_LL +__migrate_disable (); +#else migrate_disable (); +#endif mycpu =smp_processor_id ();if (mycpu == cpu) {printk (KERN_ERR "Yuck! Still on unplug CPU\n!" ); +#ifdef CONFIG_PREEMPT_LL +__migrate_enable (); +#else migrate_enable (); +#endif return -EBUSY ; }
@@ -557,7 +565,11 @@ static int __ref _cpu_down(unsigned int out_release:cpu_unplug_done (cpu); out_cancel: +#ifdef CONFIG_PREEMPT_LL +__migrate_enable (); +#else migrate_enable (); +#endif cpu_hotplug_done ();if (!err)cpu_notify_nofail (CPU_POST_DEAD | mod, hcpu);
kernel/sched.c +17 -1
@@ -4192,7 +4192,7 @@ static inline void schedule_debug(structschedstat_inc (this_rq (), sched_count); } -#if defined(CONFIG_PREEMPT_RT_FULL ) && defined(CONFIG_SMP ) +#if (defined(CONFIG_PREEMPT_RT_FULL ) || defined(CONFIG_PREEMPT_LL )) && defined(CONFIG_SMP )#define MIGRATE_DISABLE_SET_AFFIN (1<<30)/* Can't make a negative */ #define migrate_disabled_updated (p) ((p)->migrate_disable & MIGRATE_DISABLE_SET_AFFIN)#define migrate_disable_count (p) ((p)->migrate_disable & ~MIGRATE_DISABLE_SET_AFFIN)
@@ -4228,7 +4228,11 @@ static inline void update_migrate_disabl p->migrate_disable |=MIGRATE_DISABLE_SET_AFFIN ; } +#ifdef CONFIG_PREEMPT_LL +void __migrate_disable(void) +#else void migrate_disable(void) +#endif {struct task_struct *p = current;
@@ -4254,9 +4258,17 @@ void migrate_disable(void) p->migrate_disable =1 ;preempt_enable (); } +#ifdef CONFIG_PREEMPT_LL +EXPORT_SYMBOL (__migrate_disable); +#else EXPORT_SYMBOL (migrate_disable); +#endif +#ifdef CONFIG_PREEMPT_LL +void __migrate_enable(void) +#else void migrate_enable(void) +#endif {struct task_struct *p = current;const struct cpumask *mask;
@@ -4306,7 +4318,11 @@ void migrate_enable(void)unpin_current_cpu (); preempt_enable(); } +#ifdef CONFIG_PREEMPT_LL +EXPORT_SYMBOL (__migrate_enable); +#else EXPORT_SYMBOL (migrate_enable); +#endif #else static inline void update_migrate_disable (struct task_struct *p) { }#define migrate_disabled_updated (p) 0
include/linux/sched.h +3 -3
@@ -1260,7 +1260,7 @@ struct task_struct {#endif unsigned int policy; -#ifdef CONFIG_PREEMPT_RT_FULL +#if defined(CONFIG_PREEMPT_RT_FULL ) || defined(CONFIG_PREEMPT_LL )int migrate_disable;#ifdef CONFIG_SCHED_DEBUG int migrate_disable_atomic;
@@ -2678,7 +2678,7 @@ static inline void set_task_cpu(struct tstatic inline int __migrate_disabled (struct task_struct *p) { -#ifdef CONFIG_PREEMPT_RT_FULL +#if defined(CONFIG_PREEMPT_RT_FULL ) || defined(CONFIG_PREEMPT_LL )return p->migrate_disable;#else return 0 ;
@@ -2688,7 +2688,7 @@ static inline int __migrate_disabled(str/* Future-safe accessor for struct task_struct's cpus_allowed. */ static inline const struct cpumask *tsk_cpus_allowed (struct task_struct *p) { -#ifdef CONFIG_PREEMPT_RT_FULL +#if defined(CONFIG_PREEMPT_RT_FULL ) || defined(CONFIG_PREEMPT_LL )if (p->migrate_disable)return cpumask_of (task_cpu (p));#endif