[PATCH gnumach v1 4/4] tests-task: add test for task/thread priority RPCs

[email protected]
Newsgroups gmane.os.hurd.bugs
Message-ID <e92c5edb76248fab7b43f1e54734745c56f821b0.1778373361.git.dnietoc@gmail.com>
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
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.