@@ -50,6 +50,103 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
sizeof(*cpuset), cpuset);
}
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+ int *os_pri, int *pol)
+{
+ /* 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;
+}
+
+static int
+thread_map_os_priority_to_eal_priority(int policy, int os_pri,
+ enum rte_thread_priority *eal_pri)
+{
+ switch (policy) {
+ case SCHED_OTHER:
+ if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
+ sched_get_priority_max(SCHED_OTHER))/2) {
+ *eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+ return 0;
+ }
+ break;
+ case SCHED_RR:
+ if (os_pri == sched_get_priority_max(SCHED_RR)) {
+ *eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+ return 0;
+ }
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+ enum rte_thread_priority *priority)
+{
+ int ret;
+ int policy;
+ struct sched_param param;
+
+ ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
+ ¶m);
+ if (ret != 0) {
+ RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
+ goto cleanup;
+ }
+
+ return thread_map_os_priority_to_eal_priority(policy,
+ param.sched_priority, priority);
+
+cleanup:
+ return ret;
+}
+
+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((pthread_t)thread_id.opaque_id,
+ policy, ¶m);
+}
+
int
rte_thread_attr_init(rte_thread_attr_t *attr)
{
@@ -213,6 +213,40 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
#endif /* RTE_HAS_CPUSET */
+/**
+ * Get the priority of a thread.
+ *
+ * @param thread_id
+ * Id of the thread for which to get priority.
+ *
+ * @param priority
+ * Location to store the retrieved priority.
+ *
+ * @return
+ * On success, return 0.
+ * On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_priority(rte_thread_t thread_id,
+ enum rte_thread_priority *priority);
+
+/**
+ * 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);
+
/**
* Create a TLS data key visible to all threads in the process.
* the created key is later used to get/set a value.
@@ -429,6 +429,8 @@ EXPERIMENTAL {
rte_thread_attr_set_priority;
rte_thread_get_affinity_by_id;
rte_thread_set_affinity_by_id;
+ rte_thread_get_priority;
+ rte_thread_set_priority;
};
INTERNAL {
@@ -200,6 +200,133 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
return ret;
}
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+ int *os_pri, int *pri_class)
+{
+ /* 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;
+}
+
+static int
+thread_map_os_priority_to_eal_value(int os_pri, int pri_class,
+ enum rte_thread_priority *eal_pri)
+{
+ switch (pri_class) {
+ case NORMAL_PRIORITY_CLASS:
+ if (os_pri == THREAD_PRIORITY_NORMAL) {
+ *eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+ return 0;
+ }
+ break;
+ case REALTIME_PRIORITY_CLASS:
+ if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
+ *eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+ return 0;
+ }
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+ return EINVAL;
+ }
+ return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+ enum rte_thread_priority *priority)
+{
+ HANDLE thread_handle = NULL;
+ DWORD pri_class;
+ int os_pri;
+ int ret;
+
+ pri_class = GetPriorityClass(GetCurrentProcess());
+ if (pri_class == 0) {
+ ret = thread_log_last_error("GetPriorityClass()");
+ goto cleanup;
+ }
+
+ 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;
+ }
+
+ os_pri = GetThreadPriority(thread_handle);
+ if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
+ ret = thread_log_last_error("GetThreadPriority()");
+ goto cleanup;
+ }
+
+ ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ if (thread_handle != NULL)
+ CloseHandle(thread_handle);
+
+ return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+ enum rte_thread_priority priority)
+{
+ HANDLE thread_handle;
+ int priority_class;
+ int os_priority;
+ 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)
+ goto cleanup;
+
+ if (!SetPriorityClass(GetCurrentProcess(), 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);
+
+ return ret;
+}
+
int
rte_thread_attr_init(rte_thread_attr_t *attr)
{