From a47d0a0dd4ef6b11495522c8669271cc3c761c63 Mon Sep 17 00:00:00 2001 From: ludehp Date: Sun, 2 Dec 2018 23:01:51 +0800 Subject: [PATCH] common: fix a racing in PerfCounters::perf_counter_data_any_d::read_avg Fixes: http://tracker.ceph.com/issues/25211 Signed-off-by: ludehp --- src/common/perf_counters.h | 4 ++-- src/test/perf_counters.cc | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h index 0b9f782bc9e3d..d65af189f5671 100644 --- a/src/common/perf_counters.h +++ b/src/common/perf_counters.h @@ -204,9 +204,9 @@ public: pair read_avg() const { uint64_t sum, count; do { - count = avgcount; + count = avgcount2; sum = u64; - } while (avgcount2 != count); + } while (avgcount != count); return make_pair(sum, count); } }; diff --git a/src/test/perf_counters.cc b/src/test/perf_counters.cc index 87ce7163cdead..a3a5a52782b37 100644 --- a/src/test/perf_counters.cc +++ b/src/test/perf_counters.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include "common/common_init.h" @@ -219,3 +220,48 @@ TEST(PerfCounters, ResetPerfCounters) { ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf reset\", \"var\": \"test_perfcounter_1\", \"format\": \"json\" }", &msg)); ASSERT_EQ(sd("{\"error\":\"Not find: test_perfcounter_1\"}"), msg); } + +enum { + TEST_PERFCOUNTERS3_ELEMENT_FIRST = 400, + TEST_PERFCOUNTERS3_ELEMENT_READ, + TEST_PERFCOUNTERS3_ELEMENT_LAST, +}; + +static std::shared_ptr setup_test_perfcounter3(CephContext* cct) { + PerfCountersBuilder bld(cct, "test_percounter_3", + TEST_PERFCOUNTERS3_ELEMENT_FIRST, TEST_PERFCOUNTERS3_ELEMENT_LAST); + bld.add_time_avg(TEST_PERFCOUNTERS3_ELEMENT_READ, "read_avg"); + std::shared_ptr p(bld.create_perf_counters()); + return p; +} + +static void counters_inc_test(std::shared_ptr fake_pf) { + int i = 100000; + utime_t t; + + // set to 1 nsec + t.set_from_double(0.000000001); + while (i--) { + // increase by one, make sure data.u64 equal to data.avgcount + fake_pf->tinc(TEST_PERFCOUNTERS3_ELEMENT_READ, t); + } +} + +static void counters_readavg_test(std::shared_ptr fake_pf) { + int i = 100000; + + while (i--) { + std::pair dat = fake_pf->get_tavg_ns(TEST_PERFCOUNTERS3_ELEMENT_READ); + // sum and count should be identical as we increment TEST_PERCOUNTERS_ELEMENT_READ by 1 nsec eveytime + ASSERT_EQ(dat.first, dat.second); + } +} + +TEST(PerfCounters, read_avg) { + std::shared_ptr fake_pf = setup_test_perfcounter3(g_ceph_context); + + std::thread t1(counters_inc_test, fake_pf); + std::thread t2(counters_readavg_test, fake_pf); + t2.join(); + t1.join(); +} \ No newline at end of file -- 2.39.5