[v9,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.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.
On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value: (sched_get_priority_min(SCHED_OTHER) +
sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);
On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL
Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
lib/eal/common/rte_thread.c | 51 ++++++++++
lib/eal/include/rte_thread.h | 17 ++++
lib/eal/include/rte_thread_types.h | 3 -
.../include/rte_windows_thread_types.h | 3 -
lib/eal/windows/rte_thread.c | 92 +++++++++++++++++++
5 files changed, 160 insertions(+), 6 deletions(-)
Comments
2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
[...]
> diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
> index 9e74a538c2..6dc3d575c0 100644
> --- a/lib/eal/windows/rte_thread.c
> +++ b/lib/eal/windows/rte_thread.c
> @@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
> 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);
> +}
> +
It is assumed all DPDK threads are created in current process,
existing code uses GetCurrentProcess(), so this can be dropped.
@@ -48,6 +48,57 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
}
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, int *pol)
+{
+ RTE_VERIFY(os_pri != NULL);
+ RTE_VERIFY(pol != NULL);
+
+ /* Clear the output parameters */
+ *os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+ *pol = -1;
+
+ switch (eal_pri)
+ {
+ case RTE_THREAD_PRIORITY_NORMAL:
+ *pol = SCHED_OTHER;
+
+ /*
+ * Choose the middle of the range to represent
+ * the priority 'normal'.
+ * On Linux, this should be 0, since both
+ * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+ */
+ *os_pri = (sched_get_priority_min(SCHED_OTHER) +
+ sched_get_priority_max(SCHED_OTHER))/2;
+ break;
+ case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+ *pol = SCHED_RR;
+ *os_pri = sched_get_priority_max(SCHED_RR);
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+ return EINVAL;
+ }
+ return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority)
+{
+ int ret;
+ int policy;
+ struct sched_param param;
+
+ ret = thread_map_priority_to_os_value(priority, ¶m.sched_priority, &policy);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return pthread_setschedparam(thread_id.opaque_id, policy, ¶m);
+}
+
int
rte_thread_attr_init(rte_thread_attr_t *attr)
{
@@ -122,6 +122,23 @@ __rte_experimental
int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
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
@@ -7,7 +7,4 @@
#include <pthread.h>
-#define EAL_THREAD_PRIORITY_NORMAL 0
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL 99
-
#endif /* _RTE_THREAD_TYPES_H_ */
@@ -7,7 +7,4 @@
#include <rte_windows.h>
-#define EAL_THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL THREAD_PRIORITY_TIME_CRITICAL
-
#endif /* _RTE_THREAD_TYPES_H_ */
@@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
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);
+}
+
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+ int *os_pri, int *pri_class)
+{
+ RTE_VERIFY(os_pri != NULL);
+ RTE_VERIFY(pri_class != NULL);
+
+ /* Clear the output parameters */
+ *os_pri = -1;
+ *pri_class = -1;
+
+ switch (eal_pri)
+ {
+ case RTE_THREAD_PRIORITY_NORMAL:
+ *pri_class = NORMAL_PRIORITY_CLASS;
+ *os_pri = THREAD_PRIORITY_NORMAL;
+ break;
+ case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+ *pri_class = REALTIME_PRIORITY_CLASS;
+ *os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority)
+{
+ HANDLE thread_handle = NULL;
+ HANDLE process_handle = NULL;
+ int priority_class = NORMAL_PRIORITY_CLASS;
+ int os_priority = THREAD_PRIORITY_NORMAL;
+ int ret = 0;
+
+ thread_handle = OpenThread(THREAD_SET_INFORMATION |
+ THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+ if (thread_handle == NULL) {
+ ret = thread_log_last_error("OpenThread()");
+ goto cleanup;
+ }
+
+ ret = thread_map_priority_to_os_value(priority, &os_priority, &priority_class);
+ if (ret != 0) {
+ return ret;
+ }
+ process_handle = get_process_handle_from_thread_handle(thread_handle);
+ if (process_handle == NULL) {
+ ret = thread_log_last_error("OpenProcess()");
+ goto cleanup;
+ }
+
+ if (!SetPriorityClass(process_handle, priority_class)) {
+ ret = thread_log_last_error("SetPriorityClass()");
+ goto cleanup;
+ }
+
+ if (!SetThreadPriority(thread_handle, os_priority)) {
+ ret = thread_log_last_error("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)
{