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>
14 #include <afs/param.h>
17 #include <sys/time_impl.h>
25 # include "afs/sysincludes.h"
26 # include "afsincludes.h"
27 # endif /* !UKERNEL */
32 #ifndef AFS_PTHREAD_ENV
37 #if !defined(AFS_USE_GETTIMEOFDAY)
38 /*use this package only if gettimeofday is much much costlier than getitime */
42 #define STARTVALUE 3600
43 static struct clock startvalue
;
44 static struct clock relclock_epoch
; /* The elapsed time of the last itimer reset */
46 struct clock clock_now
; /* The last elapsed time ready by clock_GetTimer */
48 /* 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) */
49 int clock_haveCurrentTime
;
51 int clock_nUpdates
; /* The actual number of clock updates */
52 static int clockInitialized
= 0;
57 struct itimerval itimer
, otimer
;
58 itimer
.it_value
.tv_sec
= STARTVALUE
;
59 itimer
.it_value
.tv_usec
= 0;
60 itimer
.it_interval
.tv_sec
= 0;
61 itimer
.it_interval
.tv_usec
= 0;
63 signal(SIGALRM
, SIG_IGN
);
64 if (setitimer(ITIMER_REAL
, &itimer
, &otimer
) != 0) {
65 osi_Panic("clock: could not set interval timer; aborted(errno=%d)\n",
68 if (relclock_epoch
.usec
+ startvalue
.usec
>= otimer
.it_value
.tv_usec
) {
69 relclock_epoch
.sec
= relclock_epoch
.sec
+
70 startvalue
.sec
- otimer
.it_value
.tv_sec
;
71 relclock_epoch
.usec
= relclock_epoch
.usec
+
72 startvalue
.usec
- otimer
.it_value
.tv_usec
;
74 relclock_epoch
.sec
= relclock_epoch
.sec
+
75 startvalue
.sec
- 1 - otimer
.it_value
.tv_sec
;
76 relclock_epoch
.usec
= relclock_epoch
.usec
+
77 startvalue
.usec
+ 1000000 - otimer
.it_value
.tv_usec
;
79 if (relclock_epoch
.usec
>= 1000000)
80 relclock_epoch
.usec
-= 1000000, relclock_epoch
.sec
++;
81 /* the initial value of the interval timer may not be exactly the same
82 * as the arg passed to setitimer. POSIX allows the implementation to
83 * round it up slightly, and some nonconformant implementations truncate
85 getitimer(ITIMER_REAL
, &itimer
);
86 startvalue
.sec
= itimer
.it_value
.tv_sec
;
87 startvalue
.usec
= itimer
.it_value
.tv_usec
;
90 /* Initialize the clock */
94 if (!clockInitialized
) {
95 relclock_epoch
.sec
= relclock_epoch
.usec
= 0;
96 startvalue
.sec
= startvalue
.usec
= 0;
104 /* Make clock uninitialized. */
108 clockInitialized
= 0;
112 /* 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 */
114 clock_UpdateTime(void)
116 struct itimerval itimer
;
120 getitimer(ITIMER_REAL
, &itimer
);
122 if (startvalue
.usec
>= itimer
.it_value
.tv_usec
) {
123 offset
.sec
= startvalue
.sec
- itimer
.it_value
.tv_sec
;
124 offset
.usec
= startvalue
.usec
- itimer
.it_value
.tv_usec
;
126 /* The "-1" makes up for adding 1000000 usec, on the next line */
127 offset
.sec
= startvalue
.sec
- 1 - itimer
.it_value
.tv_sec
;
128 offset
.usec
= startvalue
.usec
+ 1000000 - itimer
.it_value
.tv_usec
;
130 new.sec
= relclock_epoch
.sec
+ offset
.sec
;
131 new.usec
= relclock_epoch
.usec
+ offset
.usec
;
132 if (new.usec
>= 1000000)
133 new.usec
-= 1000000, new.sec
++;
134 clock_now
.sec
= new.sec
;
135 clock_now
.usec
= new.usec
;
136 if (itimer
.it_value
.tv_sec
< startvalue
.sec
/ 2)
138 clock_haveCurrentTime
= 1;
144 #endif /* AFS_USE_GETTIMEOFDAY */
145 #endif /* !AFS_PTHREAD_ENV */