summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMåns Rullgård <mru@inprovide.com>2004-11-07 04:06:45 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-07 04:06:45 -0800
commit107e7ba54f5dcd12b5ddbd6a41cf7a9f08b0ea4e (patch)
tree96f4acd1a9498591d446247ceb6e963b6ee0c5a3
parent4b44897435a4e907b87cb14501c04d593f2323d8 (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.c12
-rw-r--r--include/linux/sched.h6
-rw-r--r--kernel/sched.c32
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 */