summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas De Marchi <lucas.de.marchi@gmail.com>2022-06-03 14:50:45 -0700
committerLucas De Marchi <lucas.de.marchi@gmail.com>2022-06-26 23:23:46 -0700
commit8ab15eceafd46fcaf2f8874af7d52d0622127655 (patch)
treeafc4d840e2e1983382be6e2d049712454faf6bfe
parentba105fafed8ccabc0a427049a14e093b914f7ddc (diff)
downloadkmod-8ab15eceafd46fcaf2f8874af7d52d0622127655.tar.gz
util: Add exponential backoff sleep
Add simple functions to put the current thread to sleep using exponential backoff to split the interval in smaller pieces. Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
-rw-r--r--shared/util.c46
-rw-r--r--shared/util.h5
2 files changed, 51 insertions, 0 deletions
diff --git a/shared/util.c b/shared/util.c
index d4452eb..4b547ff 100644
--- a/shared/util.c
+++ b/shared/util.c
@@ -472,6 +472,52 @@ unsigned long long ts_msec(const struct timespec *ts)
(unsigned long long) ts->tv_nsec / NSEC_PER_MSEC;
}
+static struct timespec msec_ts(unsigned long long msec)
+{
+ struct timespec ts = {
+ .tv_sec = msec / MSEC_PER_SEC,
+ .tv_nsec = (msec % MSEC_PER_SEC) * NSEC_PER_MSEC,
+ };
+
+ return ts;
+}
+
+int sleep_until_msec(unsigned long long msec)
+{
+ struct timespec ts = msec_ts(msec);
+
+ if (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL) < 0 &&
+ errno != EINTR)
+ return -errno;
+
+ return 0;
+}
+
+/*
+ * Exponential retry backoff with tail
+ */
+unsigned long long get_backoff_delta_msec(unsigned long long t0,
+ unsigned long long tend,
+ unsigned long long *delta)
+{
+ unsigned long long t;
+
+ t = now_msec();
+
+ if (!*delta)
+ *delta = 1;
+ else
+ *delta <<= 1;
+
+ while (t + *delta > tend)
+ *delta >>= 1;
+
+ if (!*delta && tend > t)
+ *delta = tend - t;
+
+ return t + *delta;
+}
+
unsigned long long now_usec(void)
{
struct timespec ts;
diff --git a/shared/util.h b/shared/util.h
index bedafa3..7030653 100644
--- a/shared/util.h
+++ b/shared/util.h
@@ -55,6 +55,11 @@ unsigned long long ts_usec(const struct timespec *ts);
unsigned long long ts_msec(const struct timespec *ts);
unsigned long long now_usec(void);
unsigned long long now_msec(void);
+int sleep_until_msec(unsigned long long msec);
+unsigned long long get_backoff_delta_msec(unsigned long long t0,
+ unsigned long long tend,
+ unsigned long long *delta);
+
/* endianess and alignments */
/* ************************************************************************ */