Index: ossp-pkg/uuid/uuid.ac RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.ac,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.ac,v' 2>/dev/null --- 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) Index: ossp-pkg/uuid/uuid.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v rcsdiff -q -kk '-r1.17' '-r1.18' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v' 2>/dev/null --- 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 =