From: Diego Nieto Cid <[email protected]>

---
 tests/test-task.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)

diff --git a/tests/test-task.c b/tests/test-task.c
index cbc75e23..235ea40e 100644
--- a/tests/test-task.c
+++ b/tests/test-task.c
@@ -27,6 +27,7 @@
 
 #include <gnumach.user.h>
 #include <mach.user.h>
+#include <mach_host.user.h>
 
 
 void test_task()
@@ -160,6 +161,324 @@ int test_errors()
     ASSERT(err == MACH_SEND_INVALID_DEST, "task DEAD");
 }
 
+void test_priority()
+{
+/* XXX cannot include <kern/sched.h> */
+#define BASEPRI_USER   25
+#define BASEPRI_SYSTEM 6
+
+       int                             count;
+       kern_return_t                   err;
+       processor_set_t                 pset;
+       processor_set_name_t            psetn;
+       struct processor_set_sched_info pset_sched;
+       struct task_basic_info          tk_basic;
+       struct thread_sched_info        th_sched;
+       task_t                          new_task;
+       thread_t                        new_thread;
+       host_t                          host;
+
+       /*
+        *      Here are short notes on what behaviour this test
+        *      is attempting to guarantee and document how things
+        *      should work.
+        *
+        *      1. The default processor set max priority
+        *         should be set to BASEPRI_SYSTEM.
+        */
+       void test_default_pset_max_priority()
+       {
+               err = processor_set_default(mach_host_self(), &psetn);
+               ASSERT_RET(err, "processor_set_default failed");
+
+               count = PROCESSOR_SET_SCHED_INFO_COUNT;
+               err = processor_set_info(psetn, PROCESSOR_SET_SCHED_INFO,
+                               &host, (processor_set_info_t) &pset_sched,
+                               &count);
+               ASSERT_RET(err, "processor_set_info failed");
+
+               printf("[%s:%d] :: (default pset) max_priority: %d\n",
+                       __FILE__, __LINE__, pset_sched.max_priority);
+               ASSERT(pset_sched.max_priority == BASEPRI_SYSTEM,
+                       "expecting max_priority to be BASEPRI_SYSTEM");
+       }
+       /*
+        *      2. New processor sets should also get a max_priority of
+        *         BASEPRI_SYSTEM.
+        */
+       void test_new_pset_max_priority()
+       {
+#if    MACH_HOST
+               err = processor_set_create(mach_host_self(), &pset, &psetn);
+               ASSERT_RET(err, "processor_set_create failed");
+
+               count = PROCESSOR_SET_SCHED_INFO_COUNT;
+               err = processor_set_info(psetn, PROCESSOR_SET_SCHED_INFO,
+                               &host, (processor_info_t) &pset_sched,
+                               &count);
+               ASSERT_RET(err, "processor_set_info failed");
+
+               printf("[%s:%d] :: (new pset) max_priority: %d\n",
+                       __FILE__, __LINE__, pset_sched.max_priority);
+               ASSERT(pset_sched.max_priority == BASEPRI_SYSTEM,
+                       "expecting max_priority to be BASEPRI_SYSTEM");
+
+               err = processor_set_destroy(pset);
+               ASSERT_RET(err, "processor_set_destroy failed");
+#endif
+       }
+       /*
+        *      3. When a new task is assigned to the defualt set, new threads 
must
+        *         get a max_priority of BASEPRI_SYSTEM.
+        */
+       void test_new_thread_in_defpset_max_priority()
+       {       
+               err = task_create(mach_task_self(), FALSE, &new_task);
+               ASSERT_RET(err, "task_create failed");
+#if    MACH_HOST
+               err = task_assign_default(new_task, TRUE);
+               ASSERT_RET(err, "task_assign_default failed");
+#endif
+               err = thread_create(new_task, &new_thread);
+               ASSERT_RET(err, "thread_create failed");
+
+               count = THREAD_SCHED_INFO_COUNT;
+               err = thread_info(new_thread, THREAD_SCHED_INFO,
+                       (thread_info_t) &th_sched, &count);
+               ASSERT_RET(err, "thread_info failed");
+
+               printf("[%s:%d] :: (thread) base_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.base_priority); 
+               printf("[%s:%d] :: (thread) max_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.max_priority); 
+               ASSERT(th_sched.max_priority == BASEPRI_SYSTEM,
+                       "(thread) expected max priority of BASEPRI_SYSTEM");
+               
+               err = thread_terminate(new_thread);
+               ASSERT_RET(err, "thread_terminate failed");
+               err = task_terminate(new_task);
+               ASSERT_RET(err, "task_terminate failed");
+       }
+       /*
+        *      4. A task may lower its own priority. Any thread created
+        *         afterwards shall inherit the max priority of the task.
+        */
+       void test_task_max_priority_inheritance()
+       {
+               /* Set new max priority to something we know will "win" when
+                * compared to the procesor set max_priority and that we also
+                * know it's different from the default.
+                */
+               int new_max_priority = BASEPRI_USER + 5;
+
+               err = task_create(mach_task_self(), FALSE, &new_task);
+               ASSERT_RET(err, "task_create failed");
+
+               err = task_max_priority(mach_host_self(), new_task,
+                       new_max_priority, TRUE, FALSE);
+               ASSERT_RET(err, "task_max_priority");
+
+               err = thread_create(new_task, &new_thread);
+               ASSERT_RET(err, "thread_create failed");
+
+               count = THREAD_SCHED_INFO_COUNT;
+               err = thread_info(new_thread, THREAD_SCHED_INFO,
+                       (thread_info_t) &th_sched, &count);
+               ASSERT_RET(err, "thread_info failed");
+
+               printf("[%s:%d] :: (thread) base_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.base_priority); 
+               printf("[%s:%d] :: (thread) max_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.max_priority); 
+               ASSERT(th_sched.base_priority == new_max_priority,
+                       "(thread) expected base priority of BASEPRI_USER");
+               ASSERT(th_sched.max_priority == new_max_priority,
+                       "(thread) expected max priority of BASEPRI_USER");
+
+               err = thread_terminate(new_thread);
+               ASSERT_RET(err, "thread_terminate failed");
+               err = task_terminate(new_task);
+               ASSERT_RET(err, "task_terminate failed");
+       }
+
+       /*
+        *      5. A child task shall inherit the priority and max priority
+        *         of the parent task.
+        *         The priority may be observed through task_info while the
+        *         max priority is only observable through a thread inheriting
+        *         it on thread create.
+        */
+       void test_task_priority_inheritance()
+       {
+               /* Same rationale as the previous test */
+               int max_priority = BASEPRI_USER + 5;
+               task_t child_task;
+
+               err = task_create(mach_task_self(), FALSE, &new_task);
+               ASSERT_RET(err, "task_create failed");
+
+               err = task_max_priority(mach_host_self(), new_task,
+                       max_priority, TRUE, FALSE);
+               ASSERT_RET(err, "task_max_priority");
+
+               /* Create the child task to check priority inheritance */
+               err = task_create(new_task, FALSE, &child_task);
+               ASSERT_RET(err, "task_create failed");
+
+               /* Create thread as a proxy of max_priority */
+               err = thread_create(new_task, &new_thread);
+               ASSERT_RET(err, "thread_create failed");
+
+               count = TASK_BASIC_INFO_COUNT;
+               err = task_info(child_task, TASK_BASIC_INFO,
+                       (task_info_t) &tk_basic, &count);
+               ASSERT_RET(err, "task_info failed");
+
+               count = THREAD_SCHED_INFO_COUNT;
+               err = thread_info(new_thread, THREAD_SCHED_INFO,
+                       (thread_info_t) &th_sched, &count);
+               ASSERT_RET(err, "thread_info failed");
+
+
+               printf("[%s:%d] :: (task) base_priority: %d\n",
+                       __FILE__, __LINE__, tk_basic.base_priority);
+               printf("[%s:%d] :: (thread) base_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.base_priority);
+               printf("[%s:%d] :: (thread) max_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.max_priority);
+               ASSERT(tk_basic.base_priority == max_priority,
+                       "(task) expected base priority of BASEPRI_USER + 5");
+               ASSERT(th_sched.base_priority == max_priority,
+                       "(thread) expected base priority of BASEPRI_USER + 5");
+               ASSERT(th_sched.max_priority == max_priority,
+                       "(thread) expected max priority of BASEPRI_USER + 5");
+
+               err = thread_terminate(new_thread);
+               ASSERT_RET(err, "thread_terminate failed");
+               err = task_terminate(child_task);
+               ASSERT_RET(err, "task_terminate failed");
+               err = task_terminate(new_task);
+               ASSERT_RET(err, "task_terminate failed");
+       }
+
+       /*
+        *      6. A non-privileged task shall not be able to raise its 
max_priority
+        *         nor its priority above its current max_priority.
+        *         This test works on a task with 'USER' priorities.
+        */
+       void test_task_priority_non_privileged()
+       {
+               task_t child_task;
+               /* Set max_priority to something below the current max */
+               int max_priority = BASEPRI_USER - 10;
+               /* Set priority to something below the current max */
+               int priority = BASEPRI_USER - 5;
+
+               /* Initialize a task with USER priorities in new_task */
+               err = task_create(mach_task_self(), FALSE, &new_task);
+               ASSERT_RET(err, "task_create failed");
+               err = task_max_priority(mach_host_self(), new_task,
+                       BASEPRI_USER, TRUE, FALSE);
+               ASSERT_RET(err, "(task) 'USER' task setup failed");
+
+               /* Prepare a new clean task to test priority permissions */
+               err = task_create(new_task, FALSE, &child_task);
+               ASSERT_RET(err, "task_create failed");
+
+               err = task_priority(child_task, priority, FALSE);
+               ASSERT(err == KERN_NO_ACCESS, "(task) raising priority shall 
fail");
+               err = task_max_priority(mach_host_self(), child_task,
+                       max_priority, TRUE, FALSE);
+               ASSERT(err == KERN_NO_ACCESS, "(task) raising max priority 
shall fail");
+
+               err = task_terminate(child_task);
+               ASSERT_RET(err, "task_terminate failed");
+               err = task_terminate(new_task);
+               ASSERT_RET(err, "task_terminate failed");
+       }
+
+       /*
+        *      7. A privileged task shall be able to raise its max_priority
+        *         above its current max_priority.
+        */
+       void test_task_priority_privileged()
+       {
+               task_t child_task;
+               /* Set max_priority to something below the current max */
+               int max_priority = BASEPRI_USER - 10;
+               /* 
+                * setting priority to this value should succeed after
+                * setting max_priority
+                */
+               int priority = BASEPRI_USER - 5;
+
+               /* Initialize a task with USER priorities in new_task */
+               err = task_create(mach_task_self(), FALSE, &new_task);
+               ASSERT_RET(err, "task_create failed");
+               err = task_max_priority(mach_host_self(), new_task,
+                       BASEPRI_USER, TRUE, FALSE);
+               ASSERT_RET(err, "(task) 'USER' task setup failed");
+
+               /* Prepare a new clean task to test priority permissions */
+               err = task_create(new_task, FALSE, &child_task);
+               ASSERT_RET(err, "task_create failed");
+
+               /* Start testing privileged priority setting */
+               err = task_max_priority(host_priv(), child_task,
+                       max_priority, FALSE, FALSE);
+               ASSERT_RET(err, "(task) raising the max_priority shall 
succeed");
+               err = task_priority(child_task, priority, FALSE);
+               ASSERT_RET(err, "(task) raising priority below max_priority 
shall succeed");
+
+
+               /* Create thread as a proxy of max_priority */
+               err = thread_create(child_task, &new_thread);
+               ASSERT_RET(err, "thread_create failed");
+
+               count = TASK_BASIC_INFO_COUNT;
+               err = task_info(child_task, TASK_BASIC_INFO,
+                       (task_info_t) &tk_basic, &count);
+               ASSERT_RET(err, "task_info failed");
+
+               count = THREAD_SCHED_INFO_COUNT;
+               err = thread_info(new_thread, THREAD_SCHED_INFO,
+                       (thread_info_t) &th_sched, &count);
+               ASSERT_RET(err, "thread_info failed");
+
+               printf("[%s:%d] :: (task) base_priority: %d\n",
+                       __FILE__, __LINE__, tk_basic.base_priority);
+               printf("[%s:%d] :: (thread) base_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.base_priority);
+               printf("[%s:%d] :: (thread) max_priority: %d\n",
+                       __FILE__, __LINE__, th_sched.max_priority);
+               ASSERT(tk_basic.base_priority == priority,
+                       "(task) expected base priority of BASEPRI_USER - 5");
+               ASSERT(th_sched.base_priority == priority,
+                       "(thread) expected base priority of BASEPRI_USER - 5");
+               ASSERT(th_sched.max_priority == max_priority,
+                       "(thread) expected max priority of BASEPRI_USER - 10");
+
+               err = thread_terminate(new_thread);
+               ASSERT_RET(err, "thread_terminate failed");
+               err = task_terminate(child_task);
+               ASSERT_RET(err, "task_terminate failed");
+               err = task_terminate(new_task);
+               ASSERT_RET(err, "task_terminate failed");
+       }
+
+       /*
+        *      Call the tests
+        */
+       test_default_pset_max_priority();
+       test_new_pset_max_priority();
+       test_new_thread_in_defpset_max_priority();
+       test_task_max_priority_inheritance();
+       test_task_priority_inheritance();
+       test_task_priority_non_privileged();
+       test_task_priority_privileged();
+#undef BASEPRI_USER
+#undef BASEPRI_SYSTEM
+}
 
 int main(int argc, char *argv[], int envc, char *envp[])
 {
@@ -167,5 +486,6 @@ int main(int argc, char *argv[], int envc, char *envp[])
   test_task_threads();
   test_new_task();
   test_errors();
+  test_priority();
   return 0;
 }
-- 
2.53.0


Reply via email to