AIX: Fix undefined symbols
[openafs.git] / src / rx / rx_clock.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 /* Elapsed time package */
11 /* See rx_clock.h for calling conventions */
12
13 #include <afsconfig.h>
14 #include <afs/param.h>
15
16 #ifdef AFS_SUN59_ENV
17 #include <sys/time_impl.h>
18 #endif
19
20 #ifdef KERNEL
21 # ifndef UKERNEL
22 #  include "h/types.h"
23 #  include "h/time.h"
24 # else /* !UKERNEL */
25 #  include "afs/sysincludes.h"
26 #  include "afsincludes.h"
27 # endif /* !UKERNEL */
28 #else /* KERNEL */
29 # include <roken.h>
30 #endif
31
32 #ifndef AFS_PTHREAD_ENV
33
34 #include "rx.h"
35 #include "rx_clock.h"
36
37 #if !defined(AFS_USE_GETTIMEOFDAY)
38 /*use this package only if gettimeofday is much much costlier than getitime */
39
40 #ifndef KERNEL
41
42 #define STARTVALUE 3600
43 static struct clock startvalue;
44 static struct clock relclock_epoch;   /* The elapsed time of the last itimer reset */
45
46 struct clock clock_now;         /* The last elapsed time ready by clock_GetTimer */
47
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;
50
51 int clock_nUpdates;             /* The actual number of clock updates */
52 static int clockInitialized = 0;
53
54 static void
55 clock_Sync(void)
56 {
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;
62
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",
66                   errno);
67     }
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;
73     } else {
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;
78     }
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
84      * it */
85     getitimer(ITIMER_REAL, &itimer);
86     startvalue.sec = itimer.it_value.tv_sec;
87     startvalue.usec = itimer.it_value.tv_usec;
88 }
89
90 /* Initialize the clock */
91 void
92 clock_Init(void)
93 {
94     if (!clockInitialized) {
95         relclock_epoch.sec = relclock_epoch.usec = 0;
96         startvalue.sec = startvalue.usec = 0;
97         clock_Sync();
98         clockInitialized = 1;
99     }
100
101     clock_UpdateTime();
102 }
103
104 /* Make clock uninitialized. */
105 int
106 clock_UnInit(void)
107 {
108     clockInitialized = 0;
109     return 0;
110 }
111
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 */
113 void
114 clock_UpdateTime(void)
115 {
116     struct itimerval itimer;
117     struct clock offset;
118     struct clock new;
119
120     getitimer(ITIMER_REAL, &itimer);
121
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;
125     } else {
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;
129     }
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)
137         clock_Sync();
138     clock_haveCurrentTime = 1;
139     clock_nUpdates++;
140 }
141 #else /* KERNEL */
142 #endif /* KERNEL */
143
144 #endif /* AFS_USE_GETTIMEOFDAY */
145 #endif /* !AFS_PTHREAD_ENV */