I think this will fix the lack of thread-safety in apr_uuid_get(),
but it changes the semantics of the time lookup algorithm.  Before
I commit, does anyone have objections to this new implementation?

Thanks,
--Brian

Index: misc/unix/getuuid.c
===================================================================
RCS file: /home/cvs/apr/misc/unix/getuuid.c,v
retrieving revision 1.17
diff -u -r1.17 getuuid.c
--- misc/unix/getuuid.c 13 Mar 2002 20:39:23 -0000      1.17
+++ misc/unix/getuuid.c 5 Jul 2002 01:40:23 -0000
@@ -187,31 +187,29 @@
 
 static void get_current_time(apr_uint64_t *timestamp)
 {
-    /* ### this needs to be made thread-safe! */
-
     apr_uint64_t time_now;
-    static apr_uint64_t time_last = 0;
-    static int fudge = 0;
+    apr_uint32_t time_fingerprint_now;
+    static apr_uint32_t time_fingerprint_last = 0;
+    apr_uint32_t last;
 
-    get_system_time(&time_now);
-        
-    /* if clock reading changed since last UUID generated... */
-    if (time_last != time_now) {
-        /* The clock reading has changed since the last UUID was generated.
-           Reset the fudge factor. if we are generating them too fast, then
-           the fudge may need to be reset to something greater than zero. */
-        if (time_last + fudge > time_now)
-            fudge = time_last + fudge - time_now + 1;
-        else
-            fudge = 0;
-        time_last = time_now;
-    }
-    else {
-        /* We generated two really fast. Bump the fudge factor. */
-        ++fudge;
+    for (;;) {
+        get_system_time(&time_now);
+        time_fingerprint_now = (apr_uint32_t)(time_now & 0xffffffff);
+        last = time_fingerprint_last;
+        if (time_fingerprint_now != last) {
+            /* This time is different from the last time that we
+             * returned.  We can use it, as long as the following
+             * apr_atomic_cas succeeds (meaning that we haven't
+             * collided with another thread that's running this
+             * function at the same time)
+             */
+            if (apr_atomic_cas(&time_fingerprint_last, time_fingerprint_now,
+                               last) == last) {
+                break;
+            }
+        }
     }
-
-    *timestamp = time_now + fudge;
+    *timestamp = time_now;
 }
 
 APR_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid)

Reply via email to