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