Subject: sched: Provide realtime priority kthread and workqueue boot options
From: Mike Galbraith <mgalbraith@suse.de>
Date: Tue Oct 8 06:27:03 CEST 2013
Patch-mainline: Never, RT specific
References: SLE Realtime Extension
Nasty hack to allow users to abuse realtime without starving the kernel,
and reaping the consequences thereof.
Boot box nortsched rtkthreads=N and optionally rtworkqueues=N+1, and the
user can slam a box into the saturation wall without starving the kernel
IFF he restricts userspace to priority < N.
Signed-off-by: Mike Galbraith <mgalbraith@suse.de>
---
kernel/kthread.c | 36 ++++++++++++++++++++++++++++++++++--
kernel/workqueue.c | 26 ++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 2 deletions(-)
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -303,6 +303,20 @@ static void create_kthread(struct kthrea
}
}
+static struct sched_param fifo_param, normal_param;
+
+static void kthread_set_sched_params(struct task_struct *kthread)
+{
+ if (!fifo_param.sched_priority)
+ return;
+ sched_setscheduler_nocheck(kthread, SCHED_FIFO, &fifo_param);
+}
+
+static void kthread_clr_sched_params(struct task_struct *kthread)
+{
+ sched_setscheduler_nocheck(kthread, SCHED_NORMAL, &normal_param);
+}
+
static __printf(4, 0)
struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
void *data, int node,
@@ -347,7 +361,6 @@ struct task_struct *__kthread_create_on_
}
task = create->result;
if (!IS_ERR(task)) {
- static const struct sched_param param = { .sched_priority = 0 };
char name[TASK_COMM_LEN];
/*
@@ -360,7 +373,10 @@ struct task_struct *__kthread_create_on_
* root may have changed our (kthreadd's) priority or CPU mask.
* The kernel thread should not inherit these properties.
*/
- sched_setscheduler_nocheck(task, SCHED_NORMAL, ¶m);
+ if (!fifo_param.sched_priority)
+ kthread_clr_sched_params(task);
+ else
+ kthread_set_sched_params(task);
set_cpus_allowed_ptr(task,
housekeeping_cpumask(HK_FLAG_KTHREAD));
}
@@ -570,6 +586,7 @@ int kthread_stop(struct task_struct *k)
kthread = to_kthread(k);
set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
kthread_unpark(k);
+ kthread_clr_sched_params(k);
wake_up_process(k);
wait_for_completion(&kthread->exited);
ret = k->exit_code;
@@ -589,6 +606,7 @@ int kthreadd(void *unused)
ignore_signals(tsk);
set_cpus_allowed_ptr(tsk, housekeeping_cpumask(HK_FLAG_KTHREAD));
set_mems_allowed(node_states[N_MEMORY]);
+ kthread_set_sched_params(current);
current->flags |= PF_NOFREEZE;
cgroup_init_kthreadd();
@@ -1255,3 +1273,17 @@ struct cgroup_subsys_state *kthread_blkc
}
EXPORT_SYMBOL(kthread_blkcg);
#endif
+
+static int __init setup_rtkthreads(char *str)
+{
+ int prio;
+
+ if (kstrtoint(str, 0, &prio) || prio < 1 || prio > 99) {
+ prio = 0;
+ pr_warn("Unable to set kthread default priority\n");
+ }
+ fifo_param.sched_priority = prio;
+
+ return 1;
+}
+__setup("rtkthreads=", setup_rtkthreads);
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -50,6 +50,7 @@
#include <linux/uaccess.h>
#include <linux/sched/isolation.h>
#include <linux/nmi.h>
+#include <uapi/linux/sched/types.h>
#include "workqueue_internal.h"
@@ -1828,6 +1829,15 @@ static struct worker *alloc_worker(int n
return worker;
}
+static struct sched_param fifo_param;
+
+static void kworker_set_sched_params(struct task_struct *worker)
+{
+ if (!fifo_param.sched_priority)
+ return;
+ sched_setscheduler_nocheck(worker, SCHED_FIFO, &fifo_param);
+}
+
/**
* worker_attach_to_pool() - attach a worker to a pool
* @worker: worker to be attached
@@ -1941,6 +1951,7 @@ static struct worker *create_worker(stru
raw_spin_lock_irq(&pool->lock);
worker->pool->nr_workers++;
worker_enter_idle(worker);
+ kworker_set_sched_params(worker->task);
wake_up_process(worker->task);
raw_spin_unlock_irq(&pool->lock);
@@ -4219,6 +4230,7 @@ static int init_rescuer(struct workqueue
wq->rescuer = rescuer;
kthread_bind_mask(rescuer->task, cpu_possible_mask);
+ kworker_set_sched_params(rescuer->task);
wake_up_process(rescuer->task);
return 0;
@@ -6033,3 +6045,17 @@ int __init workqueue_init(void)
return 0;
}
+
+static int __init setup_rtworkqueues(char *str)
+{
+ int prio;
+
+ if (kstrtoint(str, 0, &prio) || prio < 1 || prio > 99) {
+ prio = 0;
+ pr_warn("Unable to set kworker default priority\n");
+ }
+ fifo_param.sched_priority = prio;
+
+ return 1;
+}
+__setup("rtworkqueues=", setup_rtworkqueues);