a8665faef8feb3c5743705ac7b5a3d672f45ffa7
[openafs.git] / src / rx / rx_clock.h
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 /* This package maintains a clock which is independent of the time of day.  It uses the 4.3BSD interval timer (getitimer/setitimer) in TIMER_REAL mode.  Any other use of the timer voids this package's warranty. */
12
13 #ifndef _CLOCK_
14 #define _CLOCK_
15
16 #ifdef  KERNEL
17 #if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV)
18 #include "../h/systm.h"
19 #include "../h/time.h"
20 #endif  /* System V */
21 #else /* KERNEL */
22 #ifndef AFS_NT40_ENV
23 #ifndef ITIMER_REAL
24 #include <sys/time.h>
25 #endif /* ITIMER_REAL */
26 #else
27 #include <time.h>
28 #include <afs/afsutil.h>
29 #endif
30 #endif /* KERNEL */
31
32 /* Some macros to make macros more reasonable (this allows a block to be used within a macro which does not cause if statements to screw up).   That is, you can use "if (...) macro_name(); else ...;" without having things blow up on the semi-colon. */
33
34 #ifndef BEGIN
35 #define BEGIN do {
36 #define END } while(0)
37 #endif
38
39 /* A clock value is the number of seconds and microseconds that have elapsed since calling clock_Init. */
40 struct clock {
41     afs_int32 sec;          /* Seconds since clock_Init */
42     afs_int32 usec;         /* Microseconds since clock_Init */
43 };
44
45 #ifndef KERNEL
46 #if defined(AFS_USE_GETTIMEOFDAY) || defined(AFS_PTHREAD_ENV)
47 #define clock_Init()
48 #define clock_NewTime()
49 #define clock_UpdateTime()
50 #define clock_Sec() (time(NULL))
51 #define clock_haveCurrentTime 1
52
53 #define        clock_GetTime(cv)                               \
54     BEGIN                                              \
55        struct timeval tv;                              \
56        gettimeofday(&tv, NULL);                        \
57        (cv)->sec = (afs_int32)tv.tv_sec;               \
58        (cv)->usec = (afs_int32)tv.tv_usec;             \
59     END
60
61 #else /* AFS_USE_GETTIMEOFDAY || AFS_PTHREAD_ENV */
62
63 /* For internal use.  The last value returned from clock_GetTime() */
64 extern struct clock clock_now;
65
66 /* For internal use:  this flag, if set, indicates a new time should be read by clock_getTime() */
67 extern int clock_haveCurrentTime;
68
69 /* For external use: the number of times the clock value is actually updated */
70 extern int clock_nUpdates;
71
72 /* Initialize the clock package */
73 extern void clock_Init();
74
75 #define clock_NewTime() (clock_haveCurrentTime = 0)
76
77 /* Update the value to be returned by gettime */
78 extern void clock_UpdateTime();
79
80 /* Return the current clock time.  If the clock value has not been updated since the last call to clock_NewTime, it is updated now */
81 #define        clock_GetTime(cv)                               \
82     BEGIN                                              \
83        if (!clock_haveCurrentTime) clock_UpdateTime(); \
84        (cv)->sec = clock_now.sec;                      \
85        (cv)->usec = clock_now.usec;                    \
86     END
87
88 /* Current clock time, truncated to seconds */
89 #define clock_Sec() ((!clock_haveCurrentTime)? clock_UpdateTime(), clock_now.sec:clock_now.sec)
90 #endif /* AFS_USE_GETTIMEOFDAY || AFS_PTHREAD_ENV */
91 #else /* KERNEL */
92 #include "../afs/afs_osi.h"
93 #define clock_Init()
94 #if defined(AFS_SGI61_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX_64BIT_KERNEL)
95 #define clock_GetTime(cv) osi_GetTime((osi_timeval_t *)cv)
96 #else
97 #define clock_GetTime(cv) osi_GetTime((struct timeval *)cv)
98 #endif
99 #define clock_Sec() osi_Time()
100 #define clock_NewTime()    /* don't do anything; clock is fast enough in kernel */
101 #endif /* KERNEL */
102
103 /* Returns the elapsed time in milliseconds between clock values (*cv1) and (*cv2) */
104 #define clock_ElapsedTime(cv1, cv2) \
105     (((cv2)->sec - (cv1)->sec)*1000 + ((cv2)->usec - (cv1)->usec)/1000)
106
107 #ifdef AFS_PTHREAD_ENV
108 #define clock_Advance(cv)
109 #else
110 /* Advance the known value of the current clock time (clock_now) by the specified clock value */
111 #define clock_Advance(cv) clock_Add(&clock_now, cv)
112 #endif /* AFS_PTHREAD_ENV */
113
114 /* Some comparison operators for clock values */
115 #define clock_Gt(a, b)  ((a)->sec>(b)->sec || ((a)->sec==(b)->sec && (a)->usec>(b)->usec))
116 #define clock_Ge(a, b)  ((a)->sec>(b)->sec || ((a)->sec==(b)->sec && (a)->usec>=(b)->usec))
117 #define clock_Eq(a, b)  ((a)->sec==(b)->sec && (a)->usec==(b)->usec)
118 #define clock_Le(a, b)  ((a)->sec<(b)->sec || ((a)->sec==(b)->sec && (a)->usec<=(b)->usec))
119 #define clock_Lt(a, b)  ((a)->sec<(b)->sec || ((a)->sec==(b)->sec && (a)->usec<(b)->usec))
120
121 /* Is the clock value zero? */
122 #define clock_IsZero(c) ((c)->sec == 0 && (c)->usec == 0)
123
124 /* Set the clock value to zero */
125 #define clock_Zero(c)   ((c)->sec = (c)->usec = 0)
126
127 /* Add time c2 to time c1.  Both c2 and c1 must be positive times. */
128 #define clock_Add(c1, c2)                                       \
129     BEGIN                                                       \
130         if (((c1)->usec += (c2)->usec) >= 1000000) {            \
131             (c1)->usec -= 1000000;                              \
132             (c1)->sec++;                                        \
133         }                                                       \
134         (c1)->sec += (c2)->sec;                                 \
135     END
136
137 #define MSEC(cp)        ((cp->sec * 1000) + (cp->usec / 1000))
138
139 /* Add ms milliseconds to time c1.  Both ms and c1 must be positive */
140 #define clock_Addmsec(c1, ms)                                    \
141     BEGIN                                                        \
142         if ((ms) >= 1000) {                                      \
143             (c1)->sec += (afs_int32)((ms) / 1000);                       \
144             (c1)->usec += (afs_int32)(((ms) % 1000) * 1000);     \
145         } else {                                                 \
146             (c1)->usec += (afs_int32)((ms) * 1000);                      \
147         }                                                        \
148         if ((c1)->usec >= 1000000) {                             \
149             (c1)->usec -= 1000000;                               \
150             (c1)->sec++;                                         \
151         }                                                        \
152     END
153
154 /* Subtract time c2 from time c1.  c2 should be less than c1 */
155 #define clock_Sub(c1, c2)                                       \
156     BEGIN                                                       \
157         if (((c1)->usec -= (c2)->usec) < 0) {                   \
158             (c1)->usec += 1000000;                              \
159             (c1)->sec--;                                        \
160         }                                                       \
161         (c1)->sec -= (c2)->sec;                                 \
162     END
163
164 #define clock_Float(c) ((c)->sec + (c)->usec/1e6)
165
166 /* Add square of time c2 to time c1.  Both c2 and c1 must be positive times. */
167 #define clock_AddSq(c1, c2)                                                   \
168     BEGIN                                                                     \
169    if((c2)->sec > 0 )                                                         \
170      {                                                                        \
171        (c1)->sec += (c2)->sec * (c2)->sec                                     \
172                     +  2 * (c2)->sec * (c2)->usec /1000000;                   \
173        (c1)->usec += (2 * (c2)->sec * (c2)->usec) % 1000000                   \
174                      + ((c2)->usec / 1000)*((c2)->usec / 1000)                \
175                      + 2 * ((c2)->usec / 1000) * ((c2)->usec % 1000) / 1000   \
176                      + ((((c2)->usec % 1000) > 707) ? 1 : 0);                 \
177      }                                                                        \
178    else                                                                       \
179      {                                                                        \
180        (c1)->usec += ((c2)->usec / 1000)*((c2)->usec / 1000)                  \
181                      + 2 * ((c2)->usec / 1000) * ((c2)->usec % 1000) / 1000   \
182                      + ((((c2)->usec % 1000) > 707) ? 1 : 0);                 \
183      }                                                                        \
184    if ((c1)->usec > 1000000) {                                                \
185         (c1)->usec -= 1000000;                                                \
186         (c1)->sec++;                                                          \
187    }                                                                          \
188     END
189
190 #endif /* _CLOCK_ */