2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Elapsed time package */
11 /* See rx_clock.h for calling conventions */
13 #include <afsconfig.h>
15 #include "afs/param.h"
17 #include <afs/param.h>
21 #include <sys/time_impl.h>
29 #include "rx/rx_clock.h"
33 #include "afs/sysincludes.h"
34 #include "afsincludes.h"
35 #include "rx/rx_internal.h"
37 #include "rx/rx_clock.h"
47 #include "rx_internal.h"
52 #if !defined(AFS_USE_GETTIMEOFDAY)
53 /*use this package only if gettimeofday is much much costlier than getitime */
57 #define STARTVALUE 3600
58 static struct clock startvalue;
59 static struct clock relclock_epoch; /* The elapsed time of the last itimer reset */
61 struct clock clock_now; /* The last elapsed time ready by clock_GetTimer */
63 /* This is set to 1 whenever the time is read, and reset to 0 whenever clock_NewTime is called. This is to allow the caller to control the frequency with which the actual time is re-evaluated (an expensive operation) */
64 int clock_haveCurrentTime;
66 int clock_nUpdates; /* The actual number of clock updates */
67 static int clockInitialized = 0;
72 struct itimerval itimer, otimer;
73 itimer.it_value.tv_sec = STARTVALUE;
74 itimer.it_value.tv_usec = 0;
75 itimer.it_interval.tv_sec = 0;
76 itimer.it_interval.tv_usec = 0;
78 signal(SIGALRM, SIG_IGN);
79 if (setitimer(ITIMER_REAL, &itimer, &otimer) != 0) {
80 fprintf(stderr, "clock: could not set interval timer; \
81 aborted(errno=%d)\n", errno);
85 if (relclock_epoch.usec + startvalue.usec >= otimer.it_value.tv_usec) {
86 relclock_epoch.sec = relclock_epoch.sec +
87 startvalue.sec - otimer.it_value.tv_sec;
88 relclock_epoch.usec = relclock_epoch.usec +
89 startvalue.usec - otimer.it_value.tv_usec;
91 relclock_epoch.sec = relclock_epoch.sec +
92 startvalue.sec - 1 - otimer.it_value.tv_sec;
93 relclock_epoch.usec = relclock_epoch.usec +
94 startvalue.usec + 1000000 - otimer.it_value.tv_usec;
96 if (relclock_epoch.usec >= 1000000)
97 relclock_epoch.usec -= 1000000, relclock_epoch.sec++;
98 /* the initial value of the interval timer may not be exactly the same
99 * as the arg passed to setitimer. POSIX allows the implementation to
100 * round it up slightly, and some nonconformant implementations truncate
102 getitimer(ITIMER_REAL, &itimer);
103 startvalue.sec = itimer.it_value.tv_sec;
104 startvalue.usec = itimer.it_value.tv_usec;
107 /* Initialize the clock */
111 if (!clockInitialized) {
112 relclock_epoch.sec = relclock_epoch.usec = 0;
113 startvalue.sec = startvalue.usec = 0;
115 clockInitialized = 1;
121 /* Make clock uninitialized. */
125 clockInitialized = 0;
129 /* Compute the current time. The timer gets the current total elapsed time since startup, expressed in seconds and microseconds. This call is almost 200 usec on an APC RT */
131 clock_UpdateTime(void)
133 struct itimerval itimer;
137 getitimer(ITIMER_REAL, &itimer);
139 if (startvalue.usec >= itimer.it_value.tv_usec) {
140 offset.sec = startvalue.sec - itimer.it_value.tv_sec;
141 offset.usec = startvalue.usec - itimer.it_value.tv_usec;
143 /* The "-1" makes up for adding 1000000 usec, on the next line */
144 offset.sec = startvalue.sec - 1 - itimer.it_value.tv_sec;
145 offset.usec = startvalue.usec + 1000000 - itimer.it_value.tv_usec;
147 new.sec = relclock_epoch.sec + offset.sec;
148 new.usec = relclock_epoch.usec + offset.usec;
149 if (new.usec >= 1000000)
150 new.usec -= 1000000, new.sec++;
151 clock_now.sec = new.sec;
152 clock_now.usec = new.usec;
153 if (itimer.it_value.tv_sec < startvalue.sec / 2)
155 clock_haveCurrentTime = 1;
161 #endif /* AFS_USE_GETTIMEOFDAY */