Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / TBBT / trace_play / sfs_c_clk.c
1 #ifndef lint
2 static char sfs_c_clkSid[] = "@(#)sfs_c_clk.c   2.1     97/10/23";
3 #endif
4
5 /*
6  *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
7  *      All rights reserved.
8  *              Standard Performance Evaluation Corporation (SPEC)
9  *              6585 Merchant Place, Suite 100
10  *              Warrenton, VA 20187
11  *
12  *      This product contains benchmarks acquired from several sources who
13  *      understand and agree with SPEC's goal of creating fair and objective
14  *      benchmarks to measure computer performance.
15  *
16  *      This copyright notice is placed here only to protect SPEC in the
17  *      event the source is misused in any manner that is contrary to the
18  *      spirit, the goals and the intent of SPEC.
19  *
20  *      The source code is provided to the user or company under the license
21  *      agreement for the SPEC Benchmark Suite for this product.
22  */
23
24 /*****************************************************************
25  *                                                               *
26  *      Copyright 1991,1992  Legato Systems, Inc.                *
27  *      Copyright 1991,1992  Auspex Systems, Inc.                *
28  *      Copyright 1991,1992  Data General Corporation            *
29  *      Copyright 1991,1992  Digital Equipment Corporation       *
30  *      Copyright 1991,1992  Interphase Corporation              *
31  *      Copyright 1991,1992  Sun Microsystems, Inc.              *
32  *                                                               *
33  *****************************************************************/
34
35 /*
36  * ---------------------- sfs_c_clk.c ---------------------
37  *
38  *      Clock handling.  Routines to read the clock, measure elapsed
39  *      time and sleep for a timed interval.
40  *
41  *.Exported_Routines
42  *      void sfs_gettime(struct ladtime *)
43  *      void sfs_elapsedtime(sfs_op_type *, struct ladtime *,
44  *                              struct ladtime *)
45  *      int msec_sleep(int)
46  *
47  *.Local_Routines
48  *      None.
49  *
50  *.Revision_History
51  *      05-Jan-92       Pawlowski       Added raw data dump hooks.
52  *      16-Dec-91       Wittle          Created.
53  */
54
55
56 /*
57  * -------------------------  Include Files  -------------------------
58  */
59
60 /*
61  * ANSI C headers
62  */
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <errno.h>
67 #include <signal.h>
68 #include <time.h>
69
70 #include <sys/types.h>
71 #include <sys/stat.h> 
72 #include <sys/time.h>
73 #include <sys/times.h>
74  
75 #include <sys/signal.h>
76
77
78 #include <unistd.h>
79
80 #include "sfs_c_def.h"
81
82 #if !(defined(USE_GETTIMEOFDAY) || defined(USE_TIMES))
83 #define USE_GETTIMEOFDAY
84 #endif
85
86 #define CLK_RESOLUTION          10      /* clock resolution in msec */
87
88 /*
89  * -------------------------  Clock Handling  -------------------------
90  */
91
92 #if defined(USE_GETTIMEOFDAY)
93 /*
94  * The time that the test first starts, all times are relative to this
95  * value to prevent integer overflows.
96  */
97 extern struct ladtime   test_start = {0, 0, 0};
98
99 /*
100  * Get the time of day, offset by 'tz_ptr', and return it in 'time_ptr'.
101  * This is a local time of day interface to allow support for system
102  * dependent clock resolution.
103  */
104 void
105 sfs_gettime(
106     struct ladtime      *time_ptr)
107 {
108         time_t          t;
109         struct timeval  tv;
110
111         (void) gettimeofday(&tv, NULL);
112         /*
113          * Use standard time function to get epoch time since 1970 for
114          * setattr/create.
115          */
116         t = time((time_t *)NULL);
117
118         if (test_start.sec == 0 && test_start.usec == 0) {
119                 test_start.sec = tv.tv_sec;
120                 test_start.usec = 0;
121         }
122         time_ptr->sec = tv.tv_sec - test_start.sec;
123         time_ptr->usec = tv.tv_usec;
124
125         time_ptr->esec = (int32_t)t;
126 } /* sfs_gettime */
127 #endif /* USE_GETTIMEOFDAY */
128
129 #if defined(USE_TIMES)
130 static uint32_t test_start = 0;
131
132 void
133 sfs_gettime(
134         struct ladtime  *time_ptr)
135 {
136         time_t          t;
137         uint32_t        clock_ticks;
138         struct tms      tms;
139         int32_t         ticks_per_sec = 100;
140
141         /*
142          * Try use possible conversions from least accurate to most accurate
143          */
144 #if defined(HZ)
145         ticks_per_sec = HZ;
146 #endif /* HZ */
147 #if defined(CLK_TCK)
148         ticks_per_sec = CLK_TCK;
149 #endif /* CLK_TCK */
150 #if defined(_SC_CLK_TCK)
151         ticks_per_sec = sysconf(_SC_CLK_TCK);
152 #endif /* _SC_CLK_TCK */
153
154         if ((clock_ticks = (uint32_t)times(&tms)) == -1) {
155                 (void) fprintf(stderr, "%s: can't get time of day from system: %s\n",
156                         sfs_Myname, strerror(errno));
157                 (void) generic_kill(0, SIGINT);
158                 exit(175);
159         }
160
161         /*
162          * Use standard time function to get epoch time since 1970 for
163          * setattr/create.
164          */
165         t = time((time_t *)NULL);
166
167         if (test_start == 0) {
168                 test_start = clock_ticks;
169         }
170
171         time_ptr->sec = (clock_ticks - test_start) / ticks_per_sec;
172         time_ptr->usec = ((clock_ticks - test_start) -
173                                         (time_ptr->sec * ticks_per_sec)) *
174                                         (1000000/ticks_per_sec);
175         time_ptr->esec = (int32_t)t;
176 }
177 #endif /* USE_TIMES */
178
179 /*
180  * Compute the elapsed time between 'stop_ptr' and 'start_ptr', and
181  * add the result to the time acculated for operation 'op_ptr'.
182  */
183 void
184 sfs_elapsedtime(
185         sfs_op_type *   op_ptr,
186         struct ladtime *        start_ptr,
187         struct ladtime *        stop_ptr)
188 {
189         double  msec2;
190         struct ladtime time_ptr1, time_ptr2;
191
192         /* get the elapsed time */
193         if (stop_ptr->usec >= 1000000) {
194                 stop_ptr->sec += (stop_ptr->usec / 1000000);
195                 stop_ptr->usec %= 1000000;
196         }
197
198         if (stop_ptr->usec < start_ptr->usec) {
199                 stop_ptr->usec += 1000000;
200                 stop_ptr->sec--;
201         }
202
203         if (stop_ptr->sec < start_ptr->sec) {
204                 stop_ptr->sec = 0;
205                 stop_ptr->usec = 0;;
206         } else {
207                 stop_ptr->usec -= start_ptr->usec;
208                 stop_ptr->sec -= start_ptr->sec;
209         }
210
211         /* count ops that take zero time */
212         if ((stop_ptr->sec == 0) && (stop_ptr->usec == 0))
213                 op_ptr->results.fast_calls++;
214
215         /* add the elapsed time to the total time for this operation */
216
217         time_ptr1 = op_ptr->results.time;
218         time_ptr2 = *stop_ptr;
219
220         ADDTIME(time_ptr1, time_ptr2);
221
222         op_ptr->results.time = time_ptr1;
223         stop_ptr = &time_ptr2;
224
225         /* square the elapsed time */
226         msec2 = (stop_ptr->sec * 1000.0) + (stop_ptr->usec / 1000.0);
227         msec2 *= msec2;
228
229         /* add the squared elapsed time to the total of squared elapsed time */
230         op_ptr->results.msec2 += msec2;
231
232         /*
233          * Log this point if logging is on. The (op_ptr - Ops)
234          * calculation is a baroque way of deriving the "NFS Operation
235          * code" we just executed--given available information.
236          *
237          * stop_ptr at this time contains the *elapsed* time, or
238          * response time of the operation.
239          */
240          log_dump(start_ptr, stop_ptr, op_ptr - Ops);
241
242 } /* sfs_elapsedtime */
243
244 long cumulative_resets;
245 long cumulative_adjusts;
246 long msec_calls;
247 /*
248  * Use select to sleep for 'msec' milliseconds.
249  * Granularity is CLK_RESOLUTION msec.
250  * Return the amount we actually slept.
251  */
252 int
253 msec_sleep(
254         int             msecs)
255 {
256         int             actual_msecs;
257         static long     cumulative_error_msecs = 0;
258         int             select_msecs;
259         struct timeval  sleeptime;
260         int             Saveerrno;
261         struct ladtime  start;
262         struct ladtime  end;
263
264         sfs_gettime(&start);
265
266         select_msecs = msecs + cumulative_error_msecs;
267         if (select_msecs < 0) {
268                 sleeptime.tv_sec = 0;
269                 sleeptime.tv_usec = 0;
270         } else {
271                 sleeptime.tv_sec = select_msecs / 1000;
272                 sleeptime.tv_usec = (select_msecs % 1000) * 1000;
273         }
274
275         /* sleep */
276         if (select(0, NULL, NULL, NULL, &sleeptime) == -1) {
277                 if (errno != EINTR) {
278                         Saveerrno = errno;
279                         (void) fprintf(stderr, "%s: select failed ",
280                                                                 sfs_Myname);
281                         errno = Saveerrno;
282                         perror("select");
283                         (void) generic_kill(0, SIGINT);
284                         exit(176);
285                 }
286         }
287         sfs_gettime(&end);
288
289         SUBTIME(end, start);
290         actual_msecs = ((end.sec * 1000) + (end.usec / 1000));
291
292         cumulative_error_msecs += (msecs - actual_msecs);
293         if(cumulative_error_msecs > 100 ||
294                 cumulative_error_msecs < -100) /* Clip tops */
295         {
296                         cumulative_error_msecs = 0;
297                         cumulative_resets++;
298         }
299         else
300         {
301                 if(cumulative_error_msecs != 0) 
302                         cumulative_adjusts++;
303         }
304         msec_calls++;
305         return actual_msecs;
306 } /* msec_sleep */
307
308
309 /* sfs_c_clk.c */