summaryrefslogtreecommitdiff
path: root/usr/src/lib/libfakekernel/common/callout.c
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2018-09-22 16:23:42 -0400
committerGordon Ross <gwr@nexenta.com>2019-05-22 22:59:03 -0400
commit8f70e16bf3f533fa0e164d0da06d00cffc63b9bb (patch)
tree55f0a8934cf74ab386f95d5089b90cd1bc7c5ee2 /usr/src/lib/libfakekernel/common/callout.c
parentb210fede5519ffcaa92e5409d891c77b945d73bb (diff)
downloadillumos-gate-8f70e16bf3f533fa0e164d0da06d00cffc63b9bb.tar.gz
10977 Windows 10 SMB client exhausts smbauth sockets
Reviewed by: Matt Barden <matt.barden@nexenta.com> Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/libfakekernel/common/callout.c')
-rw-r--r--usr/src/lib/libfakekernel/common/callout.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/usr/src/lib/libfakekernel/common/callout.c b/usr/src/lib/libfakekernel/common/callout.c
new file mode 100644
index 0000000000..24bb41cdff
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/callout.c
@@ -0,0 +1,96 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Implement timeout(9f), untimeout(9f) on top of
+ * libc timer_create, timer_settime, etc.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <time.h>
+
+typedef void (*sigev_notify_func_t)(union sigval);
+
+/*
+ * We never actually reference anything in this array, using it
+ * just as a collection of addresses mapped from/to int values.
+ * It would be fine to take addresses even beyond the end, but
+ * to avoid confusion it's sized larger than _TIMER_MAX (32).
+ */
+static char timeout_base[100];
+
+timeout_id_t
+timeout(void (*func)(void *), void *arg, clock_t delta)
+{
+ struct sigevent sev;
+ struct itimerspec its;
+ timer_t tid;
+ int err;
+
+ if (delta <= 0)
+ return (NULL);
+
+ bzero(&sev, sizeof (sev));
+ sev.sigev_notify = SIGEV_THREAD;
+ sev.sigev_value.sival_ptr = arg;
+ sev.sigev_notify_function = (sigev_notify_func_t)func;
+ err = timer_create(CLOCK_REALTIME, &sev, &tid);
+ if (err != 0)
+ return (NULL);
+
+ bzero(&its, sizeof (its));
+ TICK_TO_TIMESTRUC(delta, &its.it_value);
+ err = timer_settime(tid, 0, &its, NULL);
+ if (err != 0) {
+ (void) timer_delete(tid);
+ return (NULL);
+ }
+
+ /* Convert return to a (sort of) pointer */
+ return (timeout_base + tid);
+}
+
+clock_t
+untimeout(timeout_id_t id_arg)
+{
+ struct itimerspec its;
+ char *id_cp = id_arg;
+ clock_t delta;
+ timer_t tid;
+ int rc;
+
+ if (id_arg == NULL)
+ return (-1);
+
+ /* Convert id_arg back to small integer. */
+ tid = (int)(id_cp - timeout_base);
+
+ bzero(&its, sizeof (its));
+ rc = timer_settime(tid, 0, &its, &its);
+ if (rc != 0) {
+ delta = 0;
+ } else {
+ delta = TIMESTRUC_TO_TICK(&its.it_value);
+ if (delta < 0)
+ delta = 0;
+ }
+
+ rc = timer_delete(tid);
+ if (rc != 0)
+ delta = -1;
+
+ return (delta);
+}