[v5,1/2] eal: add thread yield functions

Message ID 20231026142749.1174372-2-thomas@monjalon.net (mailing list archive)
State New
Delegated to: Thomas Monjalon
Headers
Series allow creating thread with real-time priority |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Thomas Monjalon Oct. 26, 2023, 2:19 p.m. UTC
  When running real-time threads, we may need to force scheduling
kernel threads or other real-time threads.
New functions are added to address these cases.

The yield functions should not have any interest for normal threads.
Note: other purposes may be addressed with rte_pause() or rte_delay_*().

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/eal/include/rte_thread.h | 25 +++++++++++++++++++++++++
 lib/eal/unix/rte_thread.c    | 16 ++++++++++++++++
 lib/eal/version.map          |  4 ++++
 lib/eal/windows/rte_thread.c | 15 +++++++++++++++
 4 files changed, 60 insertions(+)
  

Patch

diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8da9d4d3fb..f2581fe152 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -183,6 +183,31 @@  int rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr);
  */
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Allow another thread to run on the same CPU core.
+ *
+ * This is a scheduler request, with minimum latency.
+ * Lower priority threads may not be scheduled.
+ *
+ * Especially useful in real-time thread priority
+ * to schedule other real-time threads.
+ * @see RTE_THREAD_PRIORITY_REALTIME_CRITICAL
+ */
+__rte_experimental
+void rte_thread_yield(void);
+
+/**
+ * Unblock a CPU core running busy in a real-time thread.
+ *
+ * This is a sleep call, giving priority to all other threads.
+ *
+ * Especially useful in real-time thread priority
+ * to avoid a busy loop blocking vital threads on a core.
+ * @see RTE_THREAD_PRIORITY_REALTIME_CRITICAL
+ */
+__rte_experimental
+void rte_thread_yield_realtime(void);
+
 /**
  * Get the id of the calling thread.
  *
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c
index 36a21ab2f9..278d8d342d 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/unix/rte_thread.c
@@ -5,9 +5,11 @@ 
 
 #include <errno.h>
 #include <pthread.h>
+#include <sched.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include <rte_errno.h>
 #include <rte_log.h>
@@ -227,6 +229,20 @@  rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+void
+rte_thread_yield(void)
+{
+	sched_yield();
+}
+
+void
+rte_thread_yield_realtime(void)
+{
+	/* A simple yield may not be enough to schedule kernel threads. */
+	struct timespec wait = {.tv_nsec = 1000000}; /* 1 ms */
+	nanosleep(&wait, NULL);
+}
+
 int
 rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 {
diff --git a/lib/eal/version.map b/lib/eal/version.map
index e00a844805..b81ac3e3af 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -413,6 +413,10 @@  EXPERIMENTAL {
 	# added in 23.07
 	rte_memzone_max_get;
 	rte_memzone_max_set;
+
+	# added in 23.11
+	rte_thread_yield;
+	rte_thread_yield_realtime;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index acf648456c..ea17b5de3d 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -304,6 +304,21 @@  rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+void
+rte_thread_yield(void)
+{
+	SwitchToThread();
+}
+
+void
+rte_thread_yield_realtime(void)
+{
+	/* Real-time threads are not causing problems on Windows.
+	 * A simple sleep should be more than enough.
+	 */
+	Sleep(0);
+}
+
 int
 rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 {