18f70e16bSGordon Ross /*
28f70e16bSGordon Ross * This file and its contents are supplied under the terms of the
38f70e16bSGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
48f70e16bSGordon Ross * You may only use this file in accordance with the terms of version
58f70e16bSGordon Ross * 1.0 of the CDDL.
68f70e16bSGordon Ross *
78f70e16bSGordon Ross * A full copy of the text of the CDDL should have accompanied this
88f70e16bSGordon Ross * source. A copy of the CDDL is also available via the Internet at
98f70e16bSGordon Ross * http://www.illumos.org/license/CDDL.
108f70e16bSGordon Ross */
118f70e16bSGordon Ross
128f70e16bSGordon Ross /*
138f70e16bSGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
148f70e16bSGordon Ross */
158f70e16bSGordon Ross
168f70e16bSGordon Ross /*
178f70e16bSGordon Ross * Implement timeout(9f), untimeout(9f) on top of
188f70e16bSGordon Ross * libc timer_create, timer_settime, etc.
198f70e16bSGordon Ross */
208f70e16bSGordon Ross
218f70e16bSGordon Ross #include <sys/types.h>
228f70e16bSGordon Ross #include <sys/systm.h>
238f70e16bSGordon Ross #include <time.h>
248f70e16bSGordon Ross
258f70e16bSGordon Ross typedef void (*sigev_notify_func_t)(union sigval);
268f70e16bSGordon Ross
278f70e16bSGordon Ross /*
288f70e16bSGordon Ross * We never actually reference anything in this array, using it
298f70e16bSGordon Ross * just as a collection of addresses mapped from/to int values.
308f70e16bSGordon Ross * It would be fine to take addresses even beyond the end, but
318f70e16bSGordon Ross * to avoid confusion it's sized larger than _TIMER_MAX (32).
328f70e16bSGordon Ross */
338f70e16bSGordon Ross static char timeout_base[100];
348f70e16bSGordon Ross
358f70e16bSGordon Ross timeout_id_t
timeout(void (* func)(void *),void * arg,clock_t delta)368f70e16bSGordon Ross timeout(void (*func)(void *), void *arg, clock_t delta)
378f70e16bSGordon Ross {
388f70e16bSGordon Ross struct sigevent sev;
398f70e16bSGordon Ross struct itimerspec its;
408f70e16bSGordon Ross timer_t tid;
418f70e16bSGordon Ross int err;
428f70e16bSGordon Ross
438f70e16bSGordon Ross if (delta <= 0)
448f70e16bSGordon Ross return (NULL);
458f70e16bSGordon Ross
468f70e16bSGordon Ross bzero(&sev, sizeof (sev));
478f70e16bSGordon Ross sev.sigev_notify = SIGEV_THREAD;
488f70e16bSGordon Ross sev.sigev_value.sival_ptr = arg;
49*0cad6fe6SToomas Soome sev.sigev_notify_function = (sigev_notify_func_t)(uintptr_t)func;
508f70e16bSGordon Ross err = timer_create(CLOCK_REALTIME, &sev, &tid);
518f70e16bSGordon Ross if (err != 0)
528f70e16bSGordon Ross return (NULL);
538f70e16bSGordon Ross
548f70e16bSGordon Ross bzero(&its, sizeof (its));
558f70e16bSGordon Ross TICK_TO_TIMESTRUC(delta, &its.it_value);
568f70e16bSGordon Ross err = timer_settime(tid, 0, &its, NULL);
578f70e16bSGordon Ross if (err != 0) {
588f70e16bSGordon Ross (void) timer_delete(tid);
598f70e16bSGordon Ross return (NULL);
608f70e16bSGordon Ross }
618f70e16bSGordon Ross
628f70e16bSGordon Ross /* Convert return to a (sort of) pointer */
638f70e16bSGordon Ross return (timeout_base + tid);
648f70e16bSGordon Ross }
658f70e16bSGordon Ross
668f70e16bSGordon Ross clock_t
untimeout(timeout_id_t id_arg)678f70e16bSGordon Ross untimeout(timeout_id_t id_arg)
688f70e16bSGordon Ross {
696af7a37bSToomas Soome struct itimerspec its, oits;
708f70e16bSGordon Ross char *id_cp = id_arg;
718f70e16bSGordon Ross clock_t delta;
728f70e16bSGordon Ross timer_t tid;
738f70e16bSGordon Ross int rc;
748f70e16bSGordon Ross
758f70e16bSGordon Ross if (id_arg == NULL)
768f70e16bSGordon Ross return (-1);
778f70e16bSGordon Ross
788f70e16bSGordon Ross /* Convert id_arg back to small integer. */
798f70e16bSGordon Ross tid = (int)(id_cp - timeout_base);
808f70e16bSGordon Ross
818f70e16bSGordon Ross bzero(&its, sizeof (its));
826af7a37bSToomas Soome bzero(&oits, sizeof (oits));
836af7a37bSToomas Soome rc = timer_settime(tid, 0, &its, &oits);
848f70e16bSGordon Ross if (rc != 0) {
858f70e16bSGordon Ross delta = 0;
868f70e16bSGordon Ross } else {
876af7a37bSToomas Soome delta = TIMESTRUC_TO_TICK(&oits.it_value);
888f70e16bSGordon Ross if (delta < 0)
898f70e16bSGordon Ross delta = 0;
908f70e16bSGordon Ross }
918f70e16bSGordon Ross
928f70e16bSGordon Ross rc = timer_delete(tid);
938f70e16bSGordon Ross if (rc != 0)
948f70e16bSGordon Ross delta = -1;
958f70e16bSGordon Ross
968f70e16bSGordon Ross return (delta);
978f70e16bSGordon Ross }
98