From: Diego Nieto Cid <[email protected]>
task_priority_override, which requires a host privileged
port right, sets the task priority, its procesor set max
priotrity and its threads priorite and max priority if
required.
---
include/mach/mach_host.defs | 11 +++++
kern/task.c | 94 +++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/include/mach/mach_host.defs b/include/mach/mach_host.defs
index 70a2e866..ce1f89cb 100644
--- a/include/mach/mach_host.defs
+++ b/include/mach/mach_host.defs
@@ -400,3 +400,14 @@ routine host_get_uptime64(
routine processor_set_processors(
set_name : processor_set_name_t;
out processors_list : processor_name_array_t);
+
+/*
+ * Override the priority of a task, its threads
+ * and processor set, increasing the max priority
+ * if required.
+ * Only available to privileged users.
+ */
+routine task_priority_override(
+ host_priv : host_priv_t;
+ task : task_t;
+ priority : int);
diff --git a/kern/task.c b/kern/task.c
index 061a8fa4..2cfd0dc5 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -1375,3 +1375,97 @@ register_new_task_notification(
new_task_notification = notification;
return KERN_SUCCESS;
}
+
+/*
+ * thread_set_priority:
+ *
+ * Sets the priority of the given threead.
+ * Will adjust max_priority if necessary.
+ */
+static kern_return_t
+thread_set_priority(
+ thread_t thread,
+ int priority)
+{
+ spl_t s;
+
+ s = splsched();
+ thread_lock(thread);
+
+ if (priority < thread->max_priority)
+ thread->max_priority = priority;
+ thread->priority = priority;
+ compute_priority(thread, TRUE);
+
+ thread_unlock(thread);
+ (void) splx(s);
+
+ return KERN_SUCCESS;
+}
+
+/*
+ * Override the priority of a task, its threads
+ * and processor set, increasing the max priority
+ * if required.
+ * Only available to privileged users.
+ */
+kern_return_t
+task_priority_override(
+ const host_t host,
+ const task_t task,
+ int priority)
+{
+ kern_return_t ret = KERN_SUCCESS;
+ processor_set_t pset;
+
+ if ((host == HOST_NULL) ||(task == TASK_NULL) ||
+ invalid_pri(priority))
+ return KERN_INVALID_ARGUMENT;
+
+
+ /*
+ * FIXME? thread_create says that processor set must
+ * be locked first. So we lock the task, get the pset
+ * then unlock the task to accuire the locks in the right order.
+ *
+ * My concerns are:
+ *
+ * 1. What happens if a thread is created and we are holding
+ * the task lock? May it deadlock if we don't accuire them
+ * in the right order?
+ *
+ * 2. Should we call pset_reference just to adjust it's max priority?
+ *
+ * 3. Do all threads run on the same processsor set as the task?
+ * If not, shall we care?
+ *
+ * 4. Should we try to catch up with changed processor sets, like
+ * thread_create does?
+ */
+ task_lock(task);
+ pset = task->processor_set;
+ task_unlock(task);
+
+ pset_lock(pset);
+ task_lock(task);
+
+ task->priority = priority;
+ pset->max_priority = priority;
+
+ {
+ thread_t thread;
+ queue_head_t *list;
+
+ list = &task->thread_list;
+ queue_iterate(list, thread, thread_t, thread_list) {
+ if (thread_set_priority(thread, priority)
+ != KERN_SUCCESS)
+ ret = KERN_FAILURE;
+ }
+ }
+
+ task_unlock(task);
+ pset_unlock(pset);
+
+ return ret;
+}
--
2.53.0