rx: Build libtool library
[openafs.git] / src / rx / rx_clock.c
index 63213fc..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
 /* See rx_clock.h for calling conventions */
 
 #include <afsconfig.h>
-#ifdef KERNEL
-#include "afs/param.h"
-#else
 #include <afs/param.h>
-#endif
 
 #ifdef AFS_SUN59_ENV
 #include <sys/time_impl.h>
 #endif
 
-RCSID
-    ("$Header$");
-
 #ifdef KERNEL
-#ifndef UKERNEL
-#include "rx/rx_clock.h"
-#include "h/types.h"
-#include "h/time.h"
-#else /* !UKERNEL */
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "rx/rx.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 <roken.h>
+#endif
+
+#ifndef AFS_PTHREAD_ENV
+
 #include "rx.h"
 #include "rx_clock.h"
-#endif
 
 #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 */
 
@@ -63,24 +51,50 @@ int clock_haveCurrentTime;
 int clock_nUpdates;            /* The actual number of clock updates */
 static int clockInitialized = 0;
 
+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)
 {
-    struct itimerval itimer, otimer;
-
     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;
     }
 
@@ -100,11 +114,27 @@ 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++;
 }
@@ -112,3 +142,4 @@ clock_UpdateTime(void)
 #endif /* KERNEL */
 
 #endif /* AFS_USE_GETTIMEOFDAY */
+#endif /* !AFS_PTHREAD_ENV */