OSSP CVS Repository

ossp - Check-in [3732]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 3732
Date: 2004-Jan-10 22:47:45 (local)
2004-Jan-10 21:47:45 (UTC)
User:rse
Branch:
Comment: add system clock resolution compensation according to the UUID standard(s)
Tickets:
Inspections:
Files:
ossp-pkg/uuid/uuid.ac      1.3 -> 1.4     3 inserted, 1 deleted
ossp-pkg/uuid/uuid.c      1.17 -> 1.18     61 inserted, 9 deleted

ossp-pkg/uuid/uuid.ac 1.3 -> 1.4

--- uuid.ac      2004/01/10 18:50:24     1.3
+++ uuid.ac      2004/01/10 21:47:45     1.4
@@ -71,7 +71,9 @@
     AC_CHECK_HEADERS(string.h sys/types.h sys/socket.h netdb.h netinet/in.h dnl
                      ifaddrs.h net/if_dl.h net/if_arp.h net/if.h sys/ioctl.h dnl
                      sys/sockio.h arpa/inet.h)
-    AC_CHECK_FUNCS(getifaddrs)
+
+    dnl #   check for functions
+    AC_CHECK_FUNCS(getifaddrs nanosleep)
 
     dnl #   check size of built-in types
     AC_CHECK_SIZEOF(char, 1)


ossp-pkg/uuid/uuid.c 1.17 -> 1.18

--- uuid.c       2004/01/10 19:17:39     1.17
+++ uuid.c       2004/01/10 21:47:45     1.18
@@ -121,10 +121,12 @@
 
 /* abstract data type (ADT) of API */
 struct uuid_st {
-    uuid_obj_t   obj;    /* inlined UUID object */
-    prng_t      *prng;   /* RPNG sub-object */
-    md5_t       *md5;    /* MD5 sub-object */
-    uuid_uint8_t mac[6]; /* pre-determined MAC address */
+    uuid_obj_t     obj;       /* inlined UUID object */
+    prng_t        *prng;      /* RPNG sub-object */
+    md5_t         *md5;       /* MD5 sub-object */
+    uuid_uint8_t   mac[6];    /* pre-determined MAC address */
+    struct timeval time_last; /* last retrieved timestamp */
+    unsigned long  time_seq;  /* last timestamp sequence counter */
 };
 
 /* create UUID object */
@@ -153,6 +155,11 @@
         (*uuid)->mac[0] = 0x80;
     }
 
+    /* initialize time attributes */
+    (*uuid)->time_last.tv_sec  = 0;
+    (*uuid)->time_last.tv_usec = 0;
+    (*uuid)->time_seq = 0;
+
     return UUID_RC_OK;
 }
 
@@ -467,22 +474,62 @@
     return;
 }
 
+/* maximum number of 100ns ticks of the actual resolution of system clock
+   (which in our case is 1us (= 1000ns) because we use gettimeofday(2) */
+#define UUIDS_PER_TICK 10
+
 /* INTERNAL: generate UUID version 1, time part */
 static uuid_rc_t uuid_generate_v1_time(uuid_t *uuid, unsigned int mode, va_list ap)
 {
+    struct timeval time_now;
     struct timeval tv;
     ui64_t t;
     ui64_t offset;
     ui64_t ov;
 
-    /* determine current system time */
-    if (gettimeofday(&tv, NULL) == -1)
-        return UUID_RC_SYS;
+    /* determine current system time and sequence counter */
+    while (1) {
+        /* determine current system time */
+        if (gettimeofday(&time_now, NULL) == -1)
+            return UUID_RC_SYS;
+
+        /* check whether system time changed since last retrieve */
+        if (!(   time_now.tv_sec  == uuid->time_last.tv_sec
+              && time_now.tv_usec == uuid->time_last.tv_usec)) {
+            /* reset time sequence counter */
+            uuid->time_seq = 0;
+
+            /* remember system time for next iteration */
+            uuid->time_last.tv_sec  = time_now.tv_sec;
+            uuid->time_last.tv_usec = time_now.tv_usec;
+        }
+
+        /* until we are out of UUIDs per tick, increment
+           the time/tick sequence counter and continue */
+        if (uuid->time_seq < UUIDS_PER_TICK) {
+            uuid->time_seq++;
+            break;
+        }
+
+        /* else sleep a little bit until the system clock (which has
+           a gettimeofday(2) resolution of 1us) has changed. */
+#ifdef HAVE_NANOSLEEP
+        /* sleep for 500ns (1/2us) */
+        ts.tv_sec  = 0;
+        ts.tv_nsec = 500;
+        nanosleep(&ts, NULL);
+#else
+        /* sleep for 1000ns (1us) */
+        tv.tv_sec  = 0;
+        tv.tv_usec = 1;
+        select(0, NULL, NULL, NULL, &tv);
+#endif
+    }
 
     /* convert from timeval (sec,usec) to OSSP ui64 (100*nsec) format */
-    t = ui64_n2i(tv.tv_sec);
+    t = ui64_n2i(time_now.tv_sec);
     t = ui64_muln(t, 1000000, NULL);
-    t = ui64_addn(t, tv.tv_usec, NULL);
+    t = ui64_addn(t, time_now.tv_usec, NULL);
     t = ui64_muln(t, 10, NULL);
 
     /* adjust for offset between UUID and Unix Epoch time through adding
@@ -492,6 +539,11 @@
     offset = ui64_s2i("01B21DD213814000", NULL, 16);
     t = ui64_add(t, offset, NULL);
 
+    /* compensate for low resolution system clock by adding
+       the time/tick sequence counter */
+    if (uuid->time_seq > 0)
+        t = ui64_addn(t, uuid->time_seq, NULL);
+
     /* store the 60 LSB of the time in the UUID */
     t = ui64_rol(t, 16, &ov);
     uuid->obj.time_hi_and_version =

CVSTrac 2.0.1