summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2023-01-06 02:37:04 +0000
committerDamien Miller <djm@mindrot.org>2023-01-06 16:21:38 +1100
commit4adf3817a24efe99b06e62630577d683c7cd8065 (patch)
treeea40b784f3c30ce8862210fdbe5824caf8226113 /misc.c
parent8c7c69d32375d2f3ce9da0109c9bffc560842316 (diff)
downloadopenssh-git-4adf3817a24efe99b06e62630577d683c7cd8065.tar.gz
upstream: add ptimeout API for keeping track of poll/ppoll
timeouts; ok dtucker markus OpenBSD-Commit-ID: 3335268ca135b3ec15a947547d7cfbb8ff929ead
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c91
1 files changed, 90 insertions, 1 deletions
diff --git a/misc.c b/misc.c
index 41244da9..c098dc61 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.179 2022/12/15 18:20:39 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.180 2023/01/06 02:37:04 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@@ -2826,3 +2826,92 @@ lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs)
free(name);
return ret;
}
+
+/*
+ * Helpers for managing poll(2)/ppoll(2) timeouts
+ * Will remember the earliest deadline and return it for use in poll/ppoll.
+ */
+
+/* Initialise a poll/ppoll timeout with an indefinite deadline */
+void
+ptimeout_init(struct timespec *pt)
+{
+ /*
+ * Deliberately invalid for ppoll(2).
+ * Will be converted to NULL in ptimeout_get_tspec() later.
+ */
+ pt->tv_sec = -1;
+ pt->tv_nsec = 0;
+}
+
+/* Specify a poll/ppoll deadline of at most 'sec' seconds */
+void
+ptimeout_deadline_sec(struct timespec *pt, long sec)
+{
+ if (pt->tv_sec == -1 || pt->tv_sec >= sec) {
+ pt->tv_sec = sec;
+ pt->tv_nsec = 0;
+ }
+}
+
+/* Specify a poll/ppoll deadline of at most 'p' (timespec) */
+static void
+ptimeout_deadline_tsp(struct timespec *pt, struct timespec *p)
+{
+ if (pt->tv_sec == -1 || timespeccmp(pt, p, >=))
+ *pt = *p;
+}
+
+/* Specify a poll/ppoll deadline of at most 'ms' milliseconds */
+void
+ptimeout_deadline_ms(struct timespec *pt, long ms)
+{
+ struct timespec p;
+
+ p.tv_sec = ms / 1000;
+ p.tv_nsec = (ms % 1000) * 1000000;
+ ptimeout_deadline_tsp(pt, &p);
+}
+
+/* Specify a poll/ppoll deadline at wall clock monotime 'when' */
+void
+ptimeout_deadline_monotime(struct timespec *pt, time_t when)
+{
+ struct timespec now, t;
+
+ t.tv_sec = when;
+ t.tv_nsec = 0;
+ monotime_ts(&now);
+
+ if (timespeccmp(&now, &t, >=))
+ ptimeout_deadline_sec(pt, 0);
+ else {
+ timespecsub(&t, &now, &t);
+ ptimeout_deadline_tsp(pt, &t);
+ }
+}
+
+/* Get a poll(2) timeout value in milliseconds */
+int
+ptimeout_get_ms(struct timespec *pt)
+{
+ if (pt->tv_sec == -1)
+ return -1;
+ if (pt->tv_sec >= (INT_MAX - (pt->tv_nsec / 1000000)) / 1000)
+ return INT_MAX;
+ return (pt->tv_sec * 1000) + (pt->tv_nsec / 1000000);
+}
+
+/* Get a ppoll(2) timeout value as a timespec pointer */
+struct timespec *
+ptimeout_get_tsp(struct timespec *pt)
+{
+ return pt->tv_sec == -1 ? NULL : pt;
+}
+
+/* Returns non-zero if a timeout has been set (i.e. is not indefinite) */
+int
+ptimeout_isset(struct timespec *pt)
+{
+ return pt->tv_sec != -1;
+}