xref: /illumos-gate/usr/src/lib/libc/port/sys/time_util.c (revision 88b8d9620aed414dab5fb34108dee58556f060f0)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*88b8d962SPatrick Mooney  * Copyright 2016 Joyent, Inc.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <time.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * This function is blatently stolen from the kernel.
347c478bd9Sstevel@tonic-gate  * See the dissertation in the comments preceding the
357c478bd9Sstevel@tonic-gate  * hrt2ts() function in:
367c478bd9Sstevel@tonic-gate  *	uts/common/os/timers.c
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate void
hrt2ts(hrtime_t hrt,timespec_t * tsp)397c478bd9Sstevel@tonic-gate hrt2ts(hrtime_t hrt, timespec_t *tsp)
407c478bd9Sstevel@tonic-gate {
41*88b8d962SPatrick Mooney #if defined(__amd64)
42*88b8d962SPatrick Mooney 	tsp->tv_sec = hrt / NANOSEC;
43*88b8d962SPatrick Mooney 	tsp->tv_nsec = hrt % NANOSEC;
44*88b8d962SPatrick Mooney #else
457c478bd9Sstevel@tonic-gate 	uint32_t sec, nsec, tmp;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 	tmp = (uint32_t)(hrt >> 30);
487c478bd9Sstevel@tonic-gate 	sec = tmp - (tmp >> 2);
497c478bd9Sstevel@tonic-gate 	sec = tmp - (sec >> 5);
507c478bd9Sstevel@tonic-gate 	sec = tmp + (sec >> 1);
517c478bd9Sstevel@tonic-gate 	sec = tmp - (sec >> 6) + 7;
527c478bd9Sstevel@tonic-gate 	sec = tmp - (sec >> 3);
537c478bd9Sstevel@tonic-gate 	sec = tmp + (sec >> 1);
547c478bd9Sstevel@tonic-gate 	sec = tmp + (sec >> 3);
557c478bd9Sstevel@tonic-gate 	sec = tmp + (sec >> 4);
567c478bd9Sstevel@tonic-gate 	tmp = (sec << 7) - sec - sec - sec;
577c478bd9Sstevel@tonic-gate 	tmp = (tmp << 7) - tmp - tmp - tmp;
587c478bd9Sstevel@tonic-gate 	tmp = (tmp << 7) - tmp - tmp - tmp;
597c478bd9Sstevel@tonic-gate 	nsec = (uint32_t)hrt - (tmp << 9);
607c478bd9Sstevel@tonic-gate 	while (nsec >= NANOSEC) {
617c478bd9Sstevel@tonic-gate 		nsec -= NANOSEC;
627c478bd9Sstevel@tonic-gate 		sec++;
637c478bd9Sstevel@tonic-gate 	}
647c478bd9Sstevel@tonic-gate 	tsp->tv_sec = (time_t)sec;
657c478bd9Sstevel@tonic-gate 	tsp->tv_nsec = nsec;
66*88b8d962SPatrick Mooney #endif /* defined(__amd64) */
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Convert absolute time to relative time.
717c478bd9Sstevel@tonic-gate  * All *timedwait() system call traps expect relative time.
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate void
abstime_to_reltime(clockid_t clock_id,const timespec_t * abstime,timespec_t * reltime)74*88b8d962SPatrick Mooney abstime_to_reltime(clockid_t clock_id, const timespec_t *abstime,
75*88b8d962SPatrick Mooney     timespec_t *reltime)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 	extern int __clock_gettime(clockid_t, timespec_t *);
787c478bd9Sstevel@tonic-gate 	timespec_t now;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (clock_id == CLOCK_HIGHRES)
817c478bd9Sstevel@tonic-gate 		hrt2ts(gethrtime(), &now);
827c478bd9Sstevel@tonic-gate 	else
837c478bd9Sstevel@tonic-gate 		(void) __clock_gettime(clock_id, &now);
847c478bd9Sstevel@tonic-gate 	if (abstime->tv_nsec >= now.tv_nsec) {
857c478bd9Sstevel@tonic-gate 		reltime->tv_sec = abstime->tv_sec - now.tv_sec;
867c478bd9Sstevel@tonic-gate 		reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec;
877c478bd9Sstevel@tonic-gate 	} else {
887c478bd9Sstevel@tonic-gate 		reltime->tv_sec = abstime->tv_sec - now.tv_sec - 1;
897c478bd9Sstevel@tonic-gate 		reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec + NANOSEC;
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 	/*
927c478bd9Sstevel@tonic-gate 	 * If the absolute time has already passed,
937c478bd9Sstevel@tonic-gate 	 * just set the relative time to zero.
947c478bd9Sstevel@tonic-gate 	 */
957c478bd9Sstevel@tonic-gate 	if (reltime->tv_sec < 0) {
967c478bd9Sstevel@tonic-gate 		reltime->tv_sec = 0;
977c478bd9Sstevel@tonic-gate 		reltime->tv_nsec = 0;
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	/*
1007c478bd9Sstevel@tonic-gate 	 * If the specified absolute time has a bad nanoseconds value,
1017c478bd9Sstevel@tonic-gate 	 * assign it to the relative time value.  If the interface
1027c478bd9Sstevel@tonic-gate 	 * attempts to sleep, the bad value will be detected then.
1037c478bd9Sstevel@tonic-gate 	 * The SUSV3 Posix spec is very clear that such detection
1047c478bd9Sstevel@tonic-gate 	 * should not happen until an attempt to sleep is made.
1057c478bd9Sstevel@tonic-gate 	 */
1067c478bd9Sstevel@tonic-gate 	if ((ulong_t)abstime->tv_nsec >= NANOSEC)
1077c478bd9Sstevel@tonic-gate 		reltime->tv_nsec = abstime->tv_nsec;
1087c478bd9Sstevel@tonic-gate }
109