summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Manton <cmanton@google.com>2014-08-13 11:00:17 -0700
committerAndre Eisenbach <eisenbach@google.com>2015-03-16 16:51:28 -0700
commit87a62cb71860d0d14061c9c279f399d355affc2e (patch)
treed9264f030b1940c0c2ce93204d7360821c76a28a
parent97fd2c0c1b45f21015ff51f5185e3b47680fdd1f (diff)
downloadandroid_system_bt-87a62cb71860d0d14061c9c279f399d355affc2e.tar.gz
android_system_bt-87a62cb71860d0d14061c9c279f399d355affc2e.tar.bz2
android_system_bt-87a62cb71860d0d14061c9c279f399d355affc2e.zip
Extend add/subtract operations to atomics
Going to be used for counters
-rw-r--r--osi/include/atomic.h16
-rw-r--r--osi/test/atomic_test.cpp33
2 files changed, 48 insertions, 1 deletions
diff --git a/osi/include/atomic.h b/osi/include/atomic.h
index 171a5393f..beac2f151 100644
--- a/osi/include/atomic.h
+++ b/osi/include/atomic.h
@@ -86,6 +86,18 @@ inline type atomic_dec_postfix_##name(volatile atomic_##name##_t *atomic) { \
return __atomic_fetch_sub_##sz(atomic, 1, __ATOMIC_SEQ_CST); \
}
+// Returns value after operation, e.g. new value
+#define ATOMIC_ADD(name, type, sz) \
+inline type atomic_add_##name(volatile atomic_##name##_t *atomic, type val) { \
+ return __atomic_add_fetch_##sz(atomic, val, __ATOMIC_SEQ_CST); \
+}
+
+// Returns value after operation, e.g. new value
+#define ATOMIC_SUB(name, type, sz) \
+inline type atomic_sub_##name(volatile atomic_##name##_t *atomic, type val) { \
+ return __atomic_sub_fetch_##sz(atomic, val, __ATOMIC_SEQ_CST); \
+}
+
#define ATOMIC_MAKE(name, type, sz) \
ATOMIC_TYPE(name, type) \
ATOMIC_STORE(name, type, sz) \
@@ -93,7 +105,9 @@ inline type atomic_dec_postfix_##name(volatile atomic_##name##_t *atomic) { \
ATOMIC_INC_PREFIX(name, type, sz) \
ATOMIC_DEC_PREFIX(name, type, sz) \
ATOMIC_INC_POSTFIX(name, type, sz) \
- ATOMIC_DEC_POSTFIX(name, type, sz)
+ ATOMIC_DEC_POSTFIX(name, type, sz) \
+ ATOMIC_ADD(name, type, sz) \
+ ATOMIC_SUB(name, type, sz)
ATOMIC_MAKE(s32, int32_t, 4)
ATOMIC_MAKE(u32, uint32_t, 4)
diff --git a/osi/test/atomic_test.cpp b/osi/test/atomic_test.cpp
index bed4733e0..b0039ab3f 100644
--- a/osi/test/atomic_test.cpp
+++ b/osi/test/atomic_test.cpp
@@ -243,3 +243,36 @@ TEST(AtomicTest, test_inc_dec_s64) {
EXPECT_EQ(-1, val);
EXPECT_EQ(-2, atomic_load_s64(&data));
}
+
+TEST(AtomicTest, test_add_sub_u64) {
+ atomic_u64_t data;
+
+ atomic_store_u64(&data, 0);
+ EXPECT_EQ((unsigned)0, atomic_load_u64(&data));
+
+ uint64_t val = atomic_add_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)0xffff, atomic_load_u64(&data));
+ EXPECT_EQ((unsigned)0xffff, val);
+
+ val = atomic_add_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)(2 * 0xffff), atomic_load_u64(&data));
+ EXPECT_EQ((unsigned)(2 * 0xffff), val);
+
+ val = atomic_add_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)(3 * 0xffff), atomic_load_u64(&data));
+ EXPECT_EQ((unsigned)(3 * 0xffff), val);
+ EXPECT_NE((unsigned)(3 * 0xfff0), val);
+
+ val = atomic_sub_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)(2 * 0xffff), val);
+
+ val = atomic_sub_u64(&data, 0);
+ EXPECT_EQ((unsigned)(2 * 0xffff), val);
+ val = atomic_sub_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)(1 * 0xffff), val);
+
+ val = atomic_sub_u64(&data, 0xffff);
+ EXPECT_EQ((unsigned)0, val);
+}
+
+