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