]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common/perf_counters: fix race condition with atomic variables 14227/head
authorJ. Eric Ivancich <ivancich@redhat.com>
Tue, 21 Mar 2017 17:23:55 +0000 (13:23 -0400)
committerJ. Eric Ivancich <ivancich@redhat.com>
Wed, 29 Mar 2017 14:25:08 +0000 (10:25 -0400)
Fix potential race condition. With the old code it would be possible
to get incorrect pair if the following sequence occured:

    ==inc==          ==read_avg==
    avgcount.inc()
                    avgcount.read()
A)                  u64.read()
    u64.add()
B)                  u64.read()
    avgcount2.inc()
                    avgcount2.read()

Depending on whether u64.read() is called at A) or B) we'd get the new
count with either the old value or new value. By flipping the order of
the avgcount & avgcount2 reads we're guaranteed to only get matched
values.

Signed-off-by: J. Eric Ivancich <ivancich@redhat.com>
src/common/perf_counters.h

index ca498a9bc7dcd1d02dc356bb62afe71b13cb6f2f..11b616c353d305605dcfe52324d5e136f5364865 100644 (file)
@@ -120,13 +120,15 @@ public:
       }
     }
 
-    /// read <sum, count> safely
+    // read <sum, count> safely by making sure the post- and pre-count
+    // are identical; in other words the whole loop needs to be run
+    // without any intervening calls to inc, set, or tinc.
     pair<uint64_t,uint64_t> read_avg() const {
       uint64_t sum, count;
       do {
-       count = avgcount.read();
+       count = avgcount2.read();
        sum = u64.read();
-      } while (avgcount2.read() != count);
+      } while (avgcount.read() != count);
       return make_pair(sum, count);
     }
   };