[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 2/6] bitmap: add atomic test and clear
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [RFC 2/6] bitmap: add atomic test and clear |
Date: |
Thu, 27 Nov 2014 12:29:22 +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 | 26 ++++++++++++++++++++++++++
2 files changed, 28 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 758749c..3125674 100644
--- a/util/bitmap.c
+++ b/util/bitmap.c
@@ -218,6 +218,32 @@ 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;
+
+ while (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++;
+ }
+ 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 0/6] memory: make dirty_memory[] accesses atomic, Stefan Hajnoczi, 2014/11/27
- [Qemu-devel] [RFC 1/6] bitmap: add atomic set functions, Stefan Hajnoczi, 2014/11/27
- [Qemu-devel] [RFC 2/6] bitmap: add atomic test and clear,
Stefan Hajnoczi <=
- [Qemu-devel] [RFC 4/6] migration: move dirty bitmap sync to ram_addr.h, Stefan Hajnoczi, 2014/11/27
- [Qemu-devel] [RFC 3/6] memory: use atomic ops for setting dirty memory bits, Stefan Hajnoczi, 2014/11/27
- [Qemu-devel] [RFC 5/6] memory: replace cpu_physical_memory_reset_dirty() with test-and-clear, Stefan Hajnoczi, 2014/11/27
- [Qemu-devel] [RFC 6/6] memory: make cpu_physical_memory_sync_dirty_bitmap() fully atomic, Stefan Hajnoczi, 2014/11/27
- Re: [Qemu-devel] [RFC 0/6] memory: make dirty_memory[] accesses atomic, Peter Maydell, 2014/11/27