[v3,05/10] eal: implement thread priority management functions
Checks
Commit Message
From: Narcisa Vasile <navasile@microsoft.com>
Add function for setting the priority for a thread.
Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
lib/librte_eal/common/rte_thread.c | 25 ++++++++++
lib/librte_eal/include/rte_thread.h | 17 +++++++
lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
3 files changed, 118 insertions(+)
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
}
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority)
+{
+ int policy;
+ struct sched_param param = {
+ .sched_priority = 0,
+ };
+
+
+ if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+ policy = SCHED_RR;
+ param.sched_priority = priority;
+ } else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+ policy = SCHED_OTHER;
+ param.sched_priority = priority;
+ } else {
+ RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+ "Defaulting to priority 'normal'.\n");
+ policy = SCHED_OTHER;
+ }
+
+ return pthread_setschedparam(thread_id, policy, ¶m);
+}
+
int
rte_thread_attr_init(rte_thread_attr_t *attr)
{
@@ -114,6 +114,23 @@ __rte_experimental
int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
rte_cpuset_t *cpuset);
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ * Id of the thread for which to set priority.
+ *
+ * @param priority
+ * Priority value to be set.
+ *
+ * @return
+ * On success, return 0.
+ * On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority);
+
/**
* Initialize the attributes of a thread.
* These attributes can be passed to the rte_thread_create() function
@@ -193,6 +193,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
return ret;
}
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+ DWORD process_id = 0;
+
+ process_id = GetProcessIdOfThread(thread_handle);
+ if (process_id == 0) {
+ RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+ return NULL;
+ }
+
+ return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority)
+{
+ HANDLE thread_handle = NULL;
+ HANDLE process_handle = NULL;
+ DWORD priority_class = NORMAL_PRIORITY_CLASS;
+ int ret = 0;
+
+ thread_handle = OpenThread(THREAD_SET_INFORMATION |
+ THREAD_QUERY_INFORMATION, FALSE, thread_id);
+ if (thread_handle == NULL) {
+ ret = rte_thread_translate_win32_error(GetLastError());
+ RTE_LOG_WIN32_ERR("OpenThread()");
+ goto cleanup;
+ }
+
+ switch (priority) {
+
+ case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+ priority_class = REALTIME_PRIORITY_CLASS;
+ break;
+
+ case RTE_THREAD_PRIORITY_NORMAL:
+ /* FALLTHROUGH */
+ default:
+ priority_class = NORMAL_PRIORITY_CLASS;
+ priority = RTE_THREAD_PRIORITY_NORMAL;
+ break;
+ }
+
+ process_handle = get_process_handle_from_thread_handle(thread_handle);
+ if (process_handle == NULL) {
+ ret = rte_thread_translate_win32_error(GetLastError());
+ RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+ goto cleanup;
+ }
+
+ if (!SetPriorityClass(process_handle, priority_class)) {
+ ret = rte_thread_translate_win32_error(GetLastError());
+ RTE_LOG_WIN32_ERR("SetPriorityClass()");
+ goto cleanup;
+ }
+
+ if (!SetThreadPriority(thread_handle, priority)) {
+ ret = rte_thread_translate_win32_error(GetLastError());
+ RTE_LOG_WIN32_ERR("SetThreadPriority()");
+ goto cleanup;
+ }
+
+cleanup:
+ if (thread_handle != NULL) {
+ CloseHandle(thread_handle);
+ thread_handle = NULL;
+ }
+ if (process_handle != NULL) {
+ CloseHandle(process_handle);
+ process_handle = NULL;
+ }
+ return ret;
+}
+
int
rte_thread_attr_init(rte_thread_attr_t *attr)
{