amd64-linux-rx-clock-fix-20050320
[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 #ifdef  KERNEL
15 #include "afs/param.h"
16 #else
17 #include <afs/param.h>
18 #endif
19
20 #ifdef AFS_SUN59_ENV
21 #include <sys/time_impl.h>
22 #endif
23
24 RCSID
25     ("$Header$");
26
27 #ifdef KERNEL
28 #ifndef UKERNEL
29 #include "rx/rx_clock.h"
30 #include "h/types.h"
31 #include "h/time.h"
32 #else /* !UKERNEL */
33 #include "afs/sysincludes.h"
34 #include "afsincludes.h"
35 #include "rx/rx.h"
36 #include "rx/rx_clock.h"
37 #endif /* !UKERNEL */
38 #else /* KERNEL */
39 #include <sys/time.h>
40 #include <stdio.h>
41 #include <errno.h>
42 #include <stdlib.h>
43 #include "rx.h"
44 #include "rx_clock.h"
45 #endif
46
47 #if !defined(AFS_USE_GETTIMEOFDAY)
48 /*use this package only if gettimeofday is much much costlier than getitime */
49
50 #ifndef KERNEL
51
52 #if defined(AFS_GFS_ENV)
53 #define STARTVALUE 8000000      /* Ultrix bounds smaller, too small for general use */
54 #else
55 #define STARTVALUE 100000000    /* Max number of seconds setitimer allows, for some reason */
56 #endif
57 static int startvalue = STARTVALUE;
58
59 struct clock clock_now;         /* The last elapsed time ready by clock_GetTimer */
60
61 /* 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) */
62 int clock_haveCurrentTime;
63
64 int clock_nUpdates;             /* The actual number of clock updates */
65 static int clockInitialized = 0;
66
67 /* Initialize the clock */
68 void
69 clock_Init(void)
70 {
71     struct itimerval itimer, otimer;
72
73     if (!clockInitialized) {
74         itimer.it_value.tv_sec = STARTVALUE;
75         itimer.it_value.tv_usec = 0;
76         itimer.it_interval.tv_sec = 0;
77         itimer.it_interval.tv_usec = 0;
78
79         if (setitimer(ITIMER_REAL, &itimer, &otimer) != 0) {
80             fprintf(stderr, "clock:  could not set interval timer; \
81                                 aborted(errno=%d)\n", errno);
82             fflush(stderr);
83             exit(1);
84         }
85         getitimer(ITIMER_REAL, &itimer);
86         startvalue = itimer.it_value.tv_sec;
87         if (itimer.it_value.tv_usec > 0)
88           startvalue++;
89         clockInitialized = 1;
90     }
91
92     clock_UpdateTime();
93 }
94
95 /* Make clock uninitialized. */
96 int
97 clock_UnInit(void)
98 {
99     clockInitialized = 0;
100     return 0;
101 }
102
103 /* 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 */
104 void
105 clock_UpdateTime(void)
106 {
107     struct itimerval itimer;
108     getitimer(ITIMER_REAL, &itimer);
109     clock_now.sec = startvalue - 1 - itimer.it_value.tv_sec;    /* The "-1" makes up for adding 1000000 usec, on the next line */
110     clock_now.usec = 1000000 - itimer.it_value.tv_usec;
111     if (clock_now.usec == 1000000)
112         clock_now.usec = 0, clock_now.sec++;
113     clock_haveCurrentTime = 1;
114     clock_nUpdates++;
115 }
116 #else /* KERNEL */
117 #endif /* KERNEL */
118
119 #endif /* AFS_USE_GETTIMEOFDAY */