8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / dispadmin / subr.c
blobb2c5c10b4af0699d2d76bf15a13bdbbaf32b2032
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
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"
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <limits.h>
41 #include "dispadmin.h"
45 * Utility functions for dispadmin command.
49 void
50 fatalerr(const char *format, ...)
52 va_list ap;
54 (void) va_start(ap, format);
55 (void) vfprintf(stderr, format, ap);
56 va_end(ap);
57 exit(1);
62 * hrtconvert() returns the interval specified by htp as a single
63 * value in resolution htp->hrt_res. Returns -1 on overflow.
65 long
66 hrtconvert(hrtimer_t *htp)
68 long sum;
69 long product;
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) {
76 return (sum);
79 return (-1);
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
86 * not be hrt'ish.
90 * Convert interval expressed in htp->hrt_res to new_res.
92 * Calculate: (interval * new_res) / htp->hrt_res rounding off as
93 * specified by round.
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)
103 long interval;
104 longlong_t dint;
105 longlong_t dto_res;
106 longlong_t drem;
107 longlong_t dfrom_res;
108 longlong_t prod;
109 longlong_t quot;
110 long numerator;
111 long result;
112 ulong_t modulus;
113 ulong_t twomodulus;
114 long temp;
116 if (htp->hrt_res == 0 || new_res == 0 ||
117 new_res > NANOSEC || htp->hrt_rem < 0)
118 return (-1);
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;
126 if (interval == 0) {
127 htp->hrt_res = new_res;
128 return (0);
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
164 * result above.
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
177 * double precision).
179 if (twomodulus >= htp->hrt_res) {
180 temp = result + 1;
181 if (temp - 1 == result)
182 result++;
183 else
184 return (-1);
186 htp->hrt_res = new_res;
187 htp->hrt_rem = result;
188 return (0);
190 } else if (round == HRT_RNDUP) {
191 if (result * htp->hrt_res != numerator) {
192 temp = result + 1;
193 if (temp - 1 == result)
194 result++;
195 else
196 return (-1);
198 htp->hrt_res = new_res;
199 htp->hrt_rem = result;
200 return (0);
201 } else { /* round == HRT_TRUNC */
202 htp->hrt_res = new_res;
203 htp->hrt_rem = result;
204 return (0);
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
213 * going to.
216 dint = interval;
217 dto_res = new_res;
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;
234 prod = prod + drem;
235 } else if (round == HRT_RNDUP) {
236 drem = htp->hrt_res - 1;
237 prod = prod + drem;
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) {
249 return (-1);
250 } else {
251 htp->hrt_res = new_res;
252 htp->hrt_rem = (int)quot;
253 return (0);