[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v2 2/6] bitmap: add atomic test and clear
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [RFC v2 2/6] bitmap: add atomic test and clear |
Date: |
Tue, 2 Dec 2014 11:23:15 +0000 |
The new bitmap_test_and_clear_atomic() function clears a range and
returns whether or not the bits were set.
Signed-off-by: Stefan Hajnoczi <address@hidden>
---
include/qemu/bitmap.h | 2 ++
util/bitmap.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
index 3e0a4f3..86dd9cd 100644
--- a/include/qemu/bitmap.h
+++ b/include/qemu/bitmap.h
@@ -41,6 +41,7 @@
* bitmap_set(dst, pos, nbits) Set specified bit area
* bitmap_set_atomic(dst, pos, nbits) Set specified bit area with atomic ops
* bitmap_clear(dst, pos, nbits) Clear specified bit area
+ * bitmap_test_and_clear_atomic(dst, pos, nbits) Test and clear area
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
*/
@@ -229,6 +230,7 @@ static inline int bitmap_intersects(const unsigned long
*src1,
void bitmap_set(unsigned long *map, long i, long len);
void bitmap_set_atomic(unsigned long *map, long i, long len);
void bitmap_clear(unsigned long *map, long start, long nr);
+bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr);
unsigned long bitmap_find_next_zero_area(unsigned long *map,
unsigned long size,
unsigned long start,
diff --git a/util/bitmap.c b/util/bitmap.c
index 40db0d9..d297066 100644
--- a/util/bitmap.c
+++ b/util/bitmap.c
@@ -233,6 +233,43 @@ void bitmap_clear(unsigned long *map, long start, long nr)
}
}
+bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const long size = start + nr;
+ int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+ unsigned long dirty = 0;
+ unsigned long old_bits;
+
+ /* First word */
+ if (nr - bits_to_clear > 0) {
+ old_bits = atomic_fetch_and(p, ~mask_to_clear);
+ dirty |= old_bits & mask_to_clear;
+ nr -= bits_to_clear;
+ bits_to_clear = BITS_PER_LONG;
+ mask_to_clear = ~0UL;
+ p++;
+ }
+
+ /* Full words */
+ while (nr - bits_to_clear >= 0) {
+ old_bits = atomic_xchg(p, 0);
+ dirty |= old_bits;
+ nr -= bits_to_clear;
+ p++;
+ }
+
+ /* Last word */
+ if (nr) {
+ mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+ old_bits = atomic_fetch_and(p, ~mask_to_clear);
+ dirty |= old_bits & mask_to_clear;
+ }
+
+ return dirty;
+}
+
#define ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
/**
--
2.1.0
- [Qemu-devel] [RFC v2 0/6] memory: make dirty_memory[] accesses atomic, Stefan Hajnoczi, 2014/12/02
- [Qemu-devel] [RFC v2 1/6] bitmap: add atomic set functions, Stefan Hajnoczi, 2014/12/02
- [Qemu-devel] [RFC v2 2/6] bitmap: add atomic test and clear,
Stefan Hajnoczi <=
- [Qemu-devel] [RFC v2 3/6] memory: use atomic ops for setting dirty memory bits, Stefan Hajnoczi, 2014/12/02
- [Qemu-devel] [RFC v2 4/6] migration: move dirty bitmap sync to ram_addr.h, Stefan Hajnoczi, 2014/12/02
- [Qemu-devel] [RFC v2 5/6] memory: replace cpu_physical_memory_reset_dirty() with test-and-clear, Stefan Hajnoczi, 2014/12/02
- [Qemu-devel] [RFC v2 6/6] memory: make cpu_physical_memory_sync_dirty_bitmap() fully atomic, Stefan Hajnoczi, 2014/12/02