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 * Copyright 2016 Joyent, Inc. 26 */ 27 28 #include <sys/types.h> 29 #include <time.h> 30 #include <errno.h> 31 32 /* 33 * This function is blatently stolen from the kernel. 34 * See the dissertation in the comments preceding the 35 * hrt2ts() function in: 36 * uts/common/os/timers.c 37 */ 38 void 39 hrt2ts(hrtime_t hrt, timespec_t *tsp) 40 { 41 #if defined(__amd64) 42 tsp->tv_sec = hrt / NANOSEC; 43 tsp->tv_nsec = hrt % NANOSEC; 44 #else 45 uint32_t sec, nsec, tmp; 46 47 tmp = (uint32_t)(hrt >> 30); 48 sec = tmp - (tmp >> 2); 49 sec = tmp - (sec >> 5); 50 sec = tmp + (sec >> 1); 51 sec = tmp - (sec >> 6) + 7; 52 sec = tmp - (sec >> 3); 53 sec = tmp + (sec >> 1); 54 sec = tmp + (sec >> 3); 55 sec = tmp + (sec >> 4); 56 tmp = (sec << 7) - sec - sec - sec; 57 tmp = (tmp << 7) - tmp - tmp - tmp; 58 tmp = (tmp << 7) - tmp - tmp - tmp; 59 nsec = (uint32_t)hrt - (tmp << 9); 60 while (nsec >= NANOSEC) { 61 nsec -= NANOSEC; 62 sec++; 63 } 64 tsp->tv_sec = (time_t)sec; 65 tsp->tv_nsec = nsec; 66 #endif /* defined(__amd64) */ 67 } 68 69 /* 70 * Convert absolute time to relative time. 71 * All *timedwait() system call traps expect relative time. 72 */ 73 void 74 abstime_to_reltime(clockid_t clock_id, const timespec_t *abstime, 75 timespec_t *reltime) 76 { 77 extern int __clock_gettime(clockid_t, timespec_t *); 78 timespec_t now; 79 80 if (clock_id == CLOCK_HIGHRES) 81 hrt2ts(gethrtime(), &now); 82 else 83 (void) __clock_gettime(clock_id, &now); 84 if (abstime->tv_nsec >= now.tv_nsec) { 85 reltime->tv_sec = abstime->tv_sec - now.tv_sec; 86 reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec; 87 } else { 88 reltime->tv_sec = abstime->tv_sec - now.tv_sec - 1; 89 reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec + NANOSEC; 90 } 91 /* 92 * If the absolute time has already passed, 93 * just set the relative time to zero. 94 */ 95 if (reltime->tv_sec < 0) { 96 reltime->tv_sec = 0; 97 reltime->tv_nsec = 0; 98 } 99 /* 100 * If the specified absolute time has a bad nanoseconds value, 101 * assign it to the relative time value. If the interface 102 * attempts to sleep, the bad value will be detected then. 103 * The SUSV3 Posix spec is very clear that such detection 104 * should not happen until an attempt to sleep is made. 105 */ 106 if ((ulong_t)abstime->tv_nsec >= NANOSEC) 107 reltime->tv_nsec = abstime->tv_nsec; 108 } 109