Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <time.h>
     31 #include <errno.h>
     32 
     33 /*
     34  * This function is blatently stolen from the kernel.
     35  * See the dissertation in the comments preceding the
     36  * hrt2ts() function in:
     37  *	uts/common/os/timers.c
     38  */
     39 void
     40 hrt2ts(hrtime_t hrt, timespec_t *tsp)
     41 {
     42 	uint32_t sec, nsec, tmp;
     43 
     44 	tmp = (uint32_t)(hrt >> 30);
     45 	sec = tmp - (tmp >> 2);
     46 	sec = tmp - (sec >> 5);
     47 	sec = tmp + (sec >> 1);
     48 	sec = tmp - (sec >> 6) + 7;
     49 	sec = tmp - (sec >> 3);
     50 	sec = tmp + (sec >> 1);
     51 	sec = tmp + (sec >> 3);
     52 	sec = tmp + (sec >> 4);
     53 	tmp = (sec << 7) - sec - sec - sec;
     54 	tmp = (tmp << 7) - tmp - tmp - tmp;
     55 	tmp = (tmp << 7) - tmp - tmp - tmp;
     56 	nsec = (uint32_t)hrt - (tmp << 9);
     57 	while (nsec >= NANOSEC) {
     58 		nsec -= NANOSEC;
     59 		sec++;
     60 	}
     61 	tsp->tv_sec = (time_t)sec;
     62 	tsp->tv_nsec = nsec;
     63 }
     64 
     65 /*
     66  * Convert absolute time to relative time.
     67  * All *timedwait() system call traps expect relative time.
     68  */
     69 void
     70 abstime_to_reltime(clockid_t clock_id,
     71 	const timespec_t *abstime, timespec_t *reltime)
     72 {
     73 	extern int __clock_gettime(clockid_t, timespec_t *);
     74 	timespec_t now;
     75 
     76 	if (clock_id == CLOCK_HIGHRES)
     77 		hrt2ts(gethrtime(), &now);
     78 	else
     79 		(void) __clock_gettime(clock_id, &now);
     80 	if (abstime->tv_nsec >= now.tv_nsec) {
     81 		reltime->tv_sec = abstime->tv_sec - now.tv_sec;
     82 		reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec;
     83 	} else {
     84 		reltime->tv_sec = abstime->tv_sec - now.tv_sec - 1;
     85 		reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec + NANOSEC;
     86 	}
     87 	/*
     88 	 * If the absolute time has already passed,
     89 	 * just set the relative time to zero.
     90 	 */
     91 	if (reltime->tv_sec < 0) {
     92 		reltime->tv_sec = 0;
     93 		reltime->tv_nsec = 0;
     94 	}
     95 	/*
     96 	 * If the specified absolute time has a bad nanoseconds value,
     97 	 * assign it to the relative time value.  If the interface
     98 	 * attempts to sleep, the bad value will be detected then.
     99 	 * The SUSV3 Posix spec is very clear that such detection
    100 	 * should not happen until an attempt to sleep is made.
    101 	 */
    102 	if ((ulong_t)abstime->tv_nsec >= NANOSEC)
    103 		reltime->tv_nsec = abstime->tv_nsec;
    104 }
    105