From: J. Eric Ivancich Date: Tue, 21 Mar 2017 17:23:55 +0000 (-0400) Subject: common/perf_counters: fix race condition with atomic variables X-Git-Tag: v12.0.2~148^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=30b284dc4ebb3f07c7027dfba66a7452521c7925;p=ceph.git common/perf_counters: fix race condition with atomic variables 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 --- diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h index ca498a9bc7dc..11b616c353d3 100644 --- a/src/common/perf_counters.h +++ b/src/common/perf_counters.h @@ -120,13 +120,15 @@ public: } } - /// read safely + // read 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 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); } };