summaryrefslogtreecommitdiffstats
path: root/src/common/perf_counters.h
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2014-05-14 17:58:07 +0200
committerSage Weil <sage@inktank.com>2014-05-14 17:58:07 +0200
commitc48a4ef96d181c39f4f7e4704f1926bba5069035 (patch)
treebaeaac877d369d6517de655ce7c93b1776d64396 /src/common/perf_counters.h
parentcommon/perf_counters: use atomics instead of a mutex (diff)
downloadceph-c48a4ef96d181c39f4f7e4704f1926bba5069035.tar.xz
ceph-c48a4ef96d181c39f4f7e4704f1926bba5069035.zip
common/perf_counters: use second atomic to make counters safe to read
Add a second counter so that we can detect a race with an add/inc during read, and retry. Signed-off-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'src/common/perf_counters.h')
-rw-r--r--src/common/perf_counters.h29
1 files changed, 23 insertions, 6 deletions
diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h
index f4f650771bc..78c8684a2a5 100644
--- a/src/common/perf_counters.h
+++ b/src/common/perf_counters.h
@@ -115,14 +115,18 @@ private:
: name(NULL),
type(PERFCOUNTER_NONE),
u64(0),
- avgcount(0)
+ avgcount(0),
+ avgcount2(0)
{}
perf_counter_data_any_d(const perf_counter_data_any_d& other)
: name(other.name),
type(other.type),
- u64(other.u64.read()),
- avgcount(other.avgcount.read())
- {}
+ u64(other.u64.read()) {
+ pair<uint64_t,uint64_t> a = other.read_avg();
+ u64.set(a.first);
+ avgcount.set(a.second);
+ avgcount2.set(a.second);
+ }
void write_schema_json(char *buf, size_t buf_sz) const;
void write_json(char *buf, size_t buf_sz) const;
@@ -131,14 +135,27 @@ private:
enum perfcounter_type_d type;
atomic64_t u64;
atomic64_t avgcount;
+ atomic64_t avgcount2;
perf_counter_data_any_d& operator=(const perf_counter_data_any_d& other) {
name = other.name;
type = other.type;
- u64.set(other.u64.read());
- avgcount.set(other.avgcount.read());
+ pair<uint64_t,uint64_t> a = other.read_avg();
+ u64.set(a.first);
+ avgcount.set(a.second);
+ avgcount2.set(a.second);
return *this;
}
+
+ /// read <sum, count> safely
+ pair<uint64_t,uint64_t> read_avg() const {
+ uint64_t sum, count;
+ do {
+ count = avgcount.read();
+ sum = u64.read();
+ } while (avgcount2.read() != count);
+ return make_pair(sum, count);
+ }
};
typedef std::vector<perf_counter_data_any_d> perf_counter_data_vec_t;