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)