From: Diego Nieto Cid <[email protected]>
* inlcude/man/mach_host.def: add task_max_prioity RPC.
* kern/task.h: add max_priority to task struct.
* kern/task.c: implement task_max_priority RPC and inherit
max_priority from parent task (or default
processor set).
* kern/thread.c: initialize new threads' max_priority from
the task creating the thread.
---
include/mach/mach_host.defs | 21 +++++++
kern/task.c | 109 ++++++++++++++++++++++++++++++++++++
kern/task.h | 1 +
kern/thread.c | 1 +
4 files changed, 132 insertions(+)
diff --git a/include/mach/mach_host.defs b/include/mach/mach_host.defs
index 70a2e866..01fc3758 100644
--- a/include/mach/mach_host.defs
+++ b/include/mach/mach_host.defs
@@ -400,3 +400,24 @@ routine host_get_uptime64(
routine processor_set_processors(
set_name : processor_set_name_t;
out processors_list : processor_name_array_t);
+
+/*
+ * Set the task max priority to max_priority.
+ *
+ * If set_priority is TRUE, the task priority is
+ * also set to follow max_priority.
+ *
+ * Regardless the value of set_priority, if the
+ * max_priority is lower than the current priority
+ * then the task priority is lowered to max_priority.
+ *
+ * If change_threads is TRUE, the resulting parameters
+ * of the task, max_priority and priority, are propagated
+ * to the current threads of the task.
+ */
+routine task_max_priority(
+ host : mach_port_t;
+ task : task_t;
+ max_priority : int;
+ set_priority : boolean_t;
+ change_threads : boolean_t);
diff --git a/kern/task.c b/kern/task.c
index 061a8fa4..61a30502 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -40,6 +40,7 @@
#include <mach_debug/mach_debug_types.h>
#include <ipc/ipc_space.h>
#include <ipc/ipc_types.h>
+#include <kern/assert.h>
#include <kern/debug.h>
#include <kern/task.h>
#include <kern/thread.h>
@@ -171,12 +172,18 @@ task_create_kernel(
pset = &default_pset;
pset_reference(pset);
new_task->priority = parent_task->priority;
+ new_task->max_priority = parent_task->max_priority;
+ /* at this point max_priority/priority must be valid */
+ assert(new_task->priority >= new_task->max_priority);
task_unlock(parent_task);
}
else {
pset = &default_pset;
pset_reference(pset);
new_task->priority = BASEPRI_USER;
+ new_task->max_priority = pset->max_priority;
+ if (new_task->max_priority > new_task->priority)
+ new_task->priority = new_task->max_priority;
}
pset_lock(pset);
pset_add_task(pset, new_task);
@@ -1375,3 +1382,105 @@ register_new_task_notification(
new_task_notification = notification;
return KERN_SUCCESS;
}
+
+/*
+ * thread_override_max_priority:
+ *
+ * Sets the max priority of the given threead.
+ * Will adjust priority if necessary or requested.
+ *
+ * However, it will not rise above the processor set
+ * max priority.
+ */
+static kern_return_t
+thread_override_max_priority(
+ thread_t thread,
+ int max_priority,
+ boolean_t set_priority)
+{
+ spl_t s;
+
+ s = splsched();
+ thread_lock(thread);
+
+ thread->max_priority = max_priority;
+ if (thread->processor_set->max_priority > max_priority)
+ thread->max_priority = thread->processor_set->max_priority;
+ if ((thread->max_priority > thread->priority) || (set_priority == TRUE))
+ thread->priority = thread->max_priority;
+
+ compute_priority(thread, TRUE);
+
+ thread_unlock(thread);
+ (void) splx(s);
+
+ return KERN_SUCCESS;
+}
+
+static
+ipc_kobject_type_t extract_host_type(const ipc_port_t port)
+{
+ ipc_kobject_type_t ikot = IKOT_NONE;
+
+ if (!IP_VALID(port))
+ return IKOT_NONE;
+
+ ip_lock(port);
+ if (ip_active(port))
+ ikot = ip_kotype(port);
+ ip_unlock(port);
+
+ if (ikot != IKOT_HOST && ikot != IKOT_HOST_PRIV)
+ ikot = IKOT_NONE;
+
+ return ikot;
+}
+
+/*
+ * task_max_priority:
+ *
+ * Reset the max priority for a task.
+ */
+kern_return_t
+task_max_priority(
+ const ipc_port_t host,
+ task_t task,
+ int max_priority,
+ boolean_t set_priority,
+ boolean_t change_threads)
+{
+ kern_return_t ret = KERN_SUCCESS;
+ ipc_kobject_type_t ikot_host = extract_host_type(host);
+
+ if ((ikot_host == IKOT_NONE) || (task == TASK_NULL) ||
+ invalid_pri(max_priority))
+ return KERN_INVALID_ARGUMENT;
+
+ task_lock(task);
+
+ if ((max_priority < task->max_priority) &&
+ (ikot_host != IKOT_HOST_PRIV)) {
+ task_unlock(task);
+ return KERN_NO_ACCESS;
+ }
+
+ task->max_priority = max_priority;
+ if ((max_priority > task->priority) || (set_priority == TRUE))
+ task->priority = max_priority;
+
+ if (change_threads == TRUE) {
+ thread_t thread;
+ queue_head_t *list;
+
+ list = &task->thread_list;
+ queue_iterate(list, thread, thread_t, thread_list) {
+ if (thread_override_max_priority(
+ thread, max_priority,
+ set_priority) != KERN_SUCCESS)
+ ret = KERN_FAILURE;
+ }
+ }
+
+ task_unlock(task);
+ return ret;
+}
diff --git a/kern/task.h b/kern/task.h
index 9521e953..a23c2d93 100644
--- a/kern/task.h
+++ b/kern/task.h
@@ -80,6 +80,7 @@ struct task {
/* User-visible scheduling information */
int user_stop_count; /* outstanding stops */
int priority; /* for new threads */
+ int max_priority; /* for task iheritance and new thrads */
/* Statistics */
time_value64_t total_user_time;
diff --git a/kern/thread.c b/kern/thread.c
index 5a0989ae..739b3087 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -503,6 +503,7 @@ kern_return_t thread_create(
*/
new_thread->priority = parent_task->priority;
+ new_thread->max_priority = parent_task->max_priority;
if (pset->max_priority > new_thread->max_priority)
new_thread->max_priority = pset->max_priority;
if (new_thread->max_priority > new_thread->priority)
--
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.