rx: Build libtool library
[openafs.git] / src / rx / rx_clock.c
index 5d94973..ddf7bd9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 /* Elapsed time package */
 /* See rx_clock.h for calling conventions */
 
-#ifdef KERNEL
-#include "../afs/param.h"
-#else
-#include <afs/param.h>
-#endif
 #include <afsconfig.h>
+#include <afs/param.h>
 
-RCSID("$Header$");
+#ifdef AFS_SUN59_ENV
+#include <sys/time_impl.h>
+#endif
 
 #ifdef KERNEL
-#ifndef UKERNEL
-#include "../rx/rx_clock.h"
-#include "../h/types.h"
-#include "../h/time.h"
-#else /* !UKERNEL */
-#include "../afs/sysincludes.h"
-#include "../afs/afsincludes.h"
-#include "../rx/rx_clock.h"
-#endif /* !UKERNEL */
+# ifndef UKERNEL
+#  include "h/types.h"
+#  include "h/time.h"
+# else /* !UKERNEL */
+#  include "afs/sysincludes.h"
+#  include "afsincludes.h"
+# endif /* !UKERNEL */
 #else /* KERNEL */
-#include <sys/time.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include "rx_clock.h"
+# include <roken.h>
 #endif
 
-#if    !defined(AFS_USE_GETTIMEOFDAY)
+#ifndef AFS_PTHREAD_ENV
+
+#include "rx.h"
+#include "rx_clock.h"
+
+#if !defined(AFS_USE_GETTIMEOFDAY)
 /*use this package only if gettimeofday is much much costlier than getitime */
 
 #ifndef KERNEL
 
-#if defined(AFS_GFS_ENV)
-#define STARTVALUE 8000000     /* Ultrix bounds smaller, too small for general use */
-#else
-#define        STARTVALUE 100000000    /* Max number of seconds setitimer allows, for some reason */
-#endif
+#define STARTVALUE 3600
+static struct clock startvalue;
+static struct clock relclock_epoch;   /* The elapsed time of the last itimer reset */
 
 struct clock clock_now;                /* The last elapsed time ready by clock_GetTimer */
 
@@ -56,46 +51,90 @@ int clock_haveCurrentTime;
 int clock_nUpdates;            /* The actual number of clock updates */
 static int clockInitialized = 0;
 
-/* Initialize the clock */
-void clock_Init(void) {
+static void
+clock_Sync(void)
+{
     struct itimerval itimer, otimer;
+    itimer.it_value.tv_sec = STARTVALUE;
+    itimer.it_value.tv_usec = 0;
+    itimer.it_interval.tv_sec = 0;
+    itimer.it_interval.tv_usec = 0;
+
+    signal(SIGALRM, SIG_IGN);
+    if (setitimer(ITIMER_REAL, &itimer, &otimer) != 0) {
+       osi_Panic("clock:  could not set interval timer; aborted(errno=%d)\n",
+                  errno);
+    }
+    if (relclock_epoch.usec + startvalue.usec >= otimer.it_value.tv_usec) {
+       relclock_epoch.sec = relclock_epoch.sec +
+           startvalue.sec - otimer.it_value.tv_sec;
+       relclock_epoch.usec = relclock_epoch.usec +
+           startvalue.usec - otimer.it_value.tv_usec;
+    } else {
+       relclock_epoch.sec = relclock_epoch.sec +
+           startvalue.sec - 1 - otimer.it_value.tv_sec;
+       relclock_epoch.usec = relclock_epoch.usec +
+           startvalue.usec + 1000000 - otimer.it_value.tv_usec;
+    }
+    if (relclock_epoch.usec >= 1000000)
+       relclock_epoch.usec -= 1000000, relclock_epoch.sec++;
+    /* the initial value of the interval timer may not be exactly the same
+     * as the arg passed to setitimer. POSIX allows the implementation to
+     * round it up slightly, and some nonconformant implementations truncate
+     * it */
+    getitimer(ITIMER_REAL, &itimer);
+    startvalue.sec = itimer.it_value.tv_sec;
+    startvalue.usec = itimer.it_value.tv_usec;
+}
 
+/* Initialize the clock */
+void
+clock_Init(void)
+{
     if (!clockInitialized) {
-       itimer.it_value.tv_sec = STARTVALUE;
-       itimer.it_value.tv_usec = 0;
-       itimer.it_interval.tv_sec = 0;
-       itimer.it_interval.tv_usec = 0;
-
-       if (setitimer(ITIMER_REAL, &itimer, &otimer) != 0) {
-           fprintf(stderr, "clock:  could not set interval timer; \
-                               aborted(errno=%d)\n", errno);
-           fflush (stderr);
-           exit(1);
-       }
+       relclock_epoch.sec = relclock_epoch.usec = 0;
+       startvalue.sec = startvalue.usec = 0;
+       clock_Sync();
        clockInitialized = 1;
     }
 
     clock_UpdateTime();
 }
 
-#ifndef KERNEL
 /* Make clock uninitialized. */
 int
-clock_UnInit()
+clock_UnInit(void)
 {
     clockInitialized = 0;
     return 0;
-} 
-#endif 
+}
 
 /* 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 */
-void clock_UpdateTime()
+void
+clock_UpdateTime(void)
 {
     struct itimerval itimer;
+    struct clock offset;
+    struct clock new;
+
     getitimer(ITIMER_REAL, &itimer);
-    clock_now.sec = STARTVALUE - 1 - itimer.it_value.tv_sec; /* The "-1" makes up for adding 1000000 usec, on the next line */
-    clock_now.usec = 1000000 - itimer.it_value.tv_usec;
-    if (clock_now.usec == 1000000) clock_now.usec = 0, clock_now.sec++;
+
+    if (startvalue.usec >= itimer.it_value.tv_usec) {
+       offset.sec = startvalue.sec - itimer.it_value.tv_sec;
+       offset.usec = startvalue.usec - itimer.it_value.tv_usec;
+    } else {
+       /* The "-1" makes up for adding 1000000 usec, on the next line */
+       offset.sec = startvalue.sec - 1 - itimer.it_value.tv_sec;
+       offset.usec = startvalue.usec + 1000000 - itimer.it_value.tv_usec;
+    }
+    new.sec = relclock_epoch.sec + offset.sec;
+    new.usec = relclock_epoch.usec + offset.usec;
+    if (new.usec >= 1000000)
+       new.usec -= 1000000, new.sec++;
+    clock_now.sec = new.sec;
+    clock_now.usec = new.usec;
+    if (itimer.it_value.tv_sec < startvalue.sec / 2)
+       clock_Sync();
     clock_haveCurrentTime = 1;
     clock_nUpdates++;
 }
@@ -103,3 +142,4 @@ void clock_UpdateTime()
 #endif /* KERNEL */
 
 #endif /* AFS_USE_GETTIMEOFDAY */
+#endif /* !AFS_PTHREAD_ENV */