diff options
| author | Måns Rullgård <mru@inprovide.com> | 2004-11-07 04:06:45 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-07 04:06:45 -0800 |
| commit | 107e7ba54f5dcd12b5ddbd6a41cf7a9f08b0ea4e (patch) | |
| tree | 96f4acd1a9498591d446247ceb6e963b6ee0c5a3 | |
| parent | 4b44897435a4e907b87cb14501c04d593f2323d8 (diff) | |
[PATCH] SysRq-n changes RT tasks to normal
Teach sysrq-N to switch all rt-policy tasks to SCHED_OTHER. For recovering
from (and diagnosing) userspace bugs.
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/char/sysrq.c | 12 | ||||
| -rw-r--r-- | include/linux/sched.h | 6 | ||||
| -rw-r--r-- | kernel/sched.c | 32 |
3 files changed, 49 insertions, 1 deletions
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 170ce992e92c..fb4c59faad07 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -216,6 +216,16 @@ static struct sysrq_key_op sysrq_kill_op = { /* END SIGNAL SYSRQ HANDLERS BLOCK */ +static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, + struct tty_struct *tty) +{ + normalize_rt_tasks(); +} +static struct sysrq_key_op sysrq_unrt_op = { + .handler = sysrq_handle_unrt, + .help_msg = "Nice", + .action_msg = "Nice All RT Tasks" +}; /* Key Operations table and lock */ static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED; @@ -250,7 +260,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { #endif /* l */ NULL, /* m */ &sysrq_showmem_op, -/* n */ NULL, +/* n */ &sysrq_unrt_op, /* o */ NULL, /* This will often be registered as 'Off' at init time */ /* p */ &sysrq_showregs_op, diff --git a/include/linux/sched.h b/include/linux/sched.h index 5d4ebb202ea6..0c8262c6d6b8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1105,6 +1105,12 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) extern long sched_setaffinity(pid_t pid, cpumask_t new_mask); extern long sched_getaffinity(pid_t pid, cpumask_t *mask); +#ifdef CONFIG_MAGIC_SYSRQ + +extern void normalize_rt_tasks(void); + +#endif + #endif /* __KERNEL__ */ #endif diff --git a/kernel/sched.c b/kernel/sched.c index 76d8d418eae3..595348452a06 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4607,3 +4607,35 @@ void __might_sleep(char *file, int line) } EXPORT_SYMBOL(__might_sleep); #endif + +#ifdef CONFIG_MAGIC_SYSRQ +void normalize_rt_tasks(void) +{ + struct task_struct *p; + prio_array_t *array; + unsigned long flags; + runqueue_t *rq; + + read_lock_irq(&tasklist_lock); + for_each_process (p) { + if (!rt_task(p)) + continue; + + rq = task_rq_lock(p, &flags); + + array = p->array; + if (array) + deactivate_task(p, task_rq(p)); + __setscheduler(p, SCHED_NORMAL, 0); + if (array) { + __activate_task(p, task_rq(p)); + resched_task(rq->curr); + } + + task_rq_unlock(rq, &flags); + } + read_unlock_irq(&tasklist_lock); +} + +EXPORT_SYMBOL(normalize_rt_tasks); +#endif /* CONFIG_MAGIC_SYSRQ */ |
