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


Reply via email to