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
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.
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]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI"
37 #include <sys/types.h>
41 #include "dispadmin.h"
45 * Utility functions for dispadmin command.
50 fatalerr(const char *format
, ...)
54 (void) va_start(ap
, format
);
55 (void) vfprintf(stderr
, format
, ap
);
62 * hrtconvert() returns the interval specified by htp as a single
63 * value in resolution htp->hrt_res. Returns -1 on overflow.
66 hrtconvert(hrtimer_t
*htp
)
71 product
= htp
->hrt_secs
* htp
->hrt_res
;
73 if (product
/ htp
->hrt_res
== htp
->hrt_secs
) {
74 sum
= product
+ htp
->hrt_rem
;
75 if (sum
- htp
->hrt_rem
== product
) {
83 * The following routine was removed from libc (libc/port/gen/hrtnewres.c).
84 * It has also been added to priocntl, so if you fix it here, you should
85 * also probably fix it there. In the long term, this should be recoded to
90 * Convert interval expressed in htp->hrt_res to new_res.
92 * Calculate: (interval * new_res) / htp->hrt_res rounding off as
95 * Note: All args are assumed to be positive. If
96 * the last divide results in something bigger than
97 * a long, then -1 is returned instead.
101 _hrtnewres(hrtimer_t
*htp
, ulong_t new_res
, long round
)
107 longlong_t dfrom_res
;
116 if (htp
->hrt_res
== 0 || new_res
== 0 ||
117 new_res
> NANOSEC
|| htp
->hrt_rem
< 0)
120 if (htp
->hrt_rem
>= htp
->hrt_res
) {
121 htp
->hrt_secs
+= htp
->hrt_rem
/ htp
->hrt_res
;
122 htp
->hrt_rem
= htp
->hrt_rem
% htp
->hrt_res
;
125 interval
= htp
->hrt_rem
;
127 htp
->hrt_res
= new_res
;
132 * Try to do the calculations in single precision first
133 * (for speed). If they overflow, use double precision.
134 * What we want to compute is:
136 * (interval * new_res) / hrt->hrt_res
139 numerator
= interval
* new_res
;
141 if (numerator
/ new_res
== interval
) {
144 * The above multiply didn't give overflow since
145 * the division got back the original number. Go
146 * ahead and compute the result.
149 result
= numerator
/ htp
->hrt_res
;
152 * For HRT_RND, compute the value of:
154 * (interval * new_res) % htp->hrt_res
156 * If it is greater than half of the htp->hrt_res,
157 * then rounding increases the result by 1.
159 * For HRT_RNDUP, we increase the result by 1 if:
161 * result * htp->hrt_res != numerator
163 * because this tells us we truncated when calculating
166 * We also check for overflow when incrementing result
167 * although this is extremely rare.
170 if (round
== HRT_RND
) {
171 modulus
= numerator
- result
* htp
->hrt_res
;
172 if ((twomodulus
= 2 * modulus
) / 2 == modulus
) {
175 * No overflow (if we overflow in calculation
176 * of twomodulus we fall through and use
179 if (twomodulus
>= htp
->hrt_res
) {
181 if (temp
- 1 == result
)
186 htp
->hrt_res
= new_res
;
187 htp
->hrt_rem
= result
;
190 } else if (round
== HRT_RNDUP
) {
191 if (result
* htp
->hrt_res
!= numerator
) {
193 if (temp
- 1 == result
)
198 htp
->hrt_res
= new_res
;
199 htp
->hrt_rem
= result
;
201 } else { /* round == HRT_TRUNC */
202 htp
->hrt_res
= new_res
;
203 htp
->hrt_rem
= result
;
209 * We would get overflow doing the calculation is
210 * single precision so do it the slow but careful way.
212 * Compute the interval times the resolution we are
218 prod
= dint
* dto_res
;
221 * For HRT_RND the result will be equal to:
223 * ((interval * new_res) + htp->hrt_res / 2) / htp->hrt_res
225 * and for HRT_RNDUP we use:
227 * ((interval * new_res) + htp->hrt_res - 1) / htp->hrt_res
229 * This is a different but equivalent way of rounding.
232 if (round
== HRT_RND
) {
233 drem
= htp
->hrt_res
/ 2;
235 } else if (round
== HRT_RNDUP
) {
236 drem
= htp
->hrt_res
- 1;
240 dfrom_res
= htp
->hrt_res
;
241 quot
= prod
/ dfrom_res
;
244 * If the quotient won't fit in a long, then we have
245 * overflow. Otherwise, return the result.
248 if (quot
> UINT_MAX
) {
251 htp
->hrt_res
= new_res
;
252 htp
->hrt_rem
= (int)quot
;