aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/odp-linux-generic.conf7
-rw-r--r--platform/linux-generic/odp_schedule_basic.c24
2 files changed, 22 insertions, 9 deletions
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf
index 63ac31fe2..2d27752b2 100644
--- a/config/odp-linux-generic.conf
+++ b/config/odp-linux-generic.conf
@@ -240,8 +240,9 @@ sched_basic: {
# When waiting for events during a schedule call, save power by
# sleeping in the poll loop. First, run schedule loop normally for
# poll_time_nsec nanoseconds. If there are no events to schedule in that
- # time, continue polling, but sleep for sleep_time_nsec nanoseconds on
- # each round.
+ # time, continue polling, but sleep on each round. Sleep time is
+ # sleep_time_nsec nanoseconds, or the time to the next timer expiration,
+ # whichever is smaller. Timer pools are scanned just before sleep.
#
# During sleep, the thread is not polling for packet input or timers.
# Each thread measures time and sleeps independently of other threads.
@@ -257,7 +258,7 @@ sched_basic: {
# Time in nsec to sleep
#
- # Actual sleep time may vary.
+ # Must be less than one second. Actual sleep time may vary.
sleep_time_nsec = 0
}
}
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c
index 7bd8cbfed..3b0a4dce9 100644
--- a/platform/linux-generic/odp_schedule_basic.c
+++ b/platform/linux-generic/odp_schedule_basic.c
@@ -44,6 +44,7 @@
#include <string.h>
#include <time.h>
+#include <inttypes.h>
/* No synchronization context */
#define NO_SYNC_CONTEXT ODP_SCHED_SYNC_PARALLEL
@@ -297,7 +298,7 @@ typedef struct {
struct {
uint32_t poll_time;
- struct timespec sleep_time;
+ uint64_t sleep_time;
} powersave;
/* Scheduler interface config options (not used in fast path) */
@@ -545,8 +546,8 @@ static int read_config_file(sched_global_t *sched)
}
val = _ODP_MAX(0, val);
- sched->powersave.sleep_time.tv_sec = val / 1000000000;
- sched->powersave.sleep_time.tv_nsec = val % 1000000000;
+ val = _ODP_MIN((int)ODP_TIME_SEC_IN_NS - 1, val);
+ sched->powersave.sleep_time = val;
_ODP_PRINT(" %s: %i\n", str, val);
_ODP_PRINT(" dynamic load balance: %s\n", sched->load_balance ? "ON" : "OFF");
@@ -1672,7 +1673,7 @@ static inline int schedule_loop_sleep(odp_queue_t *out_queue, uint64_t wait,
timer_run(2);
break;
}
- timer_run(1);
+ uint64_t next = timer_run(sleep ? TIMER_SCAN_FORCE : 1);
if (first) {
start = odp_time_local();
@@ -1683,8 +1684,19 @@ static inline int schedule_loop_sleep(odp_queue_t *out_queue, uint64_t wait,
continue;
}
- if (sleep)
- nanosleep(&sched->powersave.sleep_time, NULL);
+ if (sleep && next) {
+ uint64_t sleep_nsec = _ODP_MIN(sched->powersave.sleep_time, next);
+
+ if (wait != ODP_SCHED_WAIT) {
+ uint64_t nsec_to_end = odp_time_diff_ns(end, current);
+
+ sleep_nsec = _ODP_MIN(sleep_nsec, nsec_to_end);
+ }
+
+ struct timespec ts = { 0, sleep_nsec };
+
+ nanosleep(&ts, NULL);
+ }
if (wait != ODP_SCHED_WAIT || !sleep) {
current = odp_time_local();