History

bitmap: genericize percpu bitmap region iterators

Bitmaps are fairly popular for their space efficiency, but we don't have generic iterators available. Make percpu's bitmap region iterators available to everyone.

Dennis Zhou committed 6 years ago

Commit e837dfd1 parent 147a0972 files · +51 −45Browse files

Unified · Split

2 files
  1. include/linux/bitmap.h +35 −0
  2. mm/percpu.c +16 −45
include/linux/bitmap.h+35−0
@@ -456,6 +456,41 @@ static inline int bitmap_parse(const char *buf, unsigned int buflen, · 455 unmodified lines
456456 return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
457457 }
458458
459+static inline void bitmap_next_clear_region(unsigned long *bitmap,
460+ unsigned int *rs, unsigned int *re,
461+ unsigned int end)
462+{
463+ *rs = find_next_zero_bit(bitmap, end, *rs);
464+ *re = find_next_bit(bitmap, end, *rs + 1);
465+}
466+
467+static inline void bitmap_next_set_region(unsigned long *bitmap,
468+ unsigned int *rs, unsigned int *re,
469+ unsigned int end)
470+{
471+ *rs = find_next_bit(bitmap, end, *rs);
472+ *re = find_next_zero_bit(bitmap, end, *rs + 1);
473+}
474+
475+/*
476+ * Bitmap region iterators. Iterates over the bitmap between [@start, @end).
477+ * @rs and @re should be integer variables and will be set to start and end
478+ * index of the current clear or set region.
479+ */
480+#define bitmap_for_each_clear_region(bitmap, rs, re, start, end) \
481+ for ((rs) = (start), \
482+ bitmap_next_clear_region((bitmap), &(rs), &(re), (end)); \
483+ (rs) < (re); \
484+ (rs) = (re) + 1, \
485+ bitmap_next_clear_region((bitmap), &(rs), &(re), (end)))
486+
487+#define bitmap_for_each_set_region(bitmap, rs, re, start, end) \
488+ for ((rs) = (start), \
489+ bitmap_next_set_region((bitmap), &(rs), &(re), (end)); \
490+ (rs) < (re); \
491+ (rs) = (re) + 1, \
492+ bitmap_next_set_region((bitmap), &(rs), &(re), (end)))
493+
459494 /**
460495 * BITMAP_FROM_U64() - Represent u64 value in the format suitable for bitmap.
461496 * @n: u64 value
mm/percpu.c+16−45
@@ -270,33 +270,6 @@ static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, · 269 unmodified lines
270270 pcpu_unit_page_offset(cpu, page_idx);
271271 }
272272
273−static void pcpu_next_unpop(unsigned long *bitmap, int *rs, int *re, int end)
274−{
275− *rs = find_next_zero_bit(bitmap, end, *rs);
276− *re = find_next_bit(bitmap, end, *rs + 1);
277−}
278−
279−static void pcpu_next_pop(unsigned long *bitmap, int *rs, int *re, int end)
280−{
281− *rs = find_next_bit(bitmap, end, *rs);
282− *re = find_next_zero_bit(bitmap, end, *rs + 1);
283−}
284−
285−/*
286− * Bitmap region iterators. Iterates over the bitmap between
287− * [@start, @end) in @chunk. @rs and @re should be integer variables
288− * and will be set to start and end index of the current free region.
289− */
290−#define pcpu_for_each_unpop_region(bitmap, rs, re, start, end) \
291− for ((rs) = (start), pcpu_next_unpop((bitmap), &(rs), &(re), (end)); \
292− (rs) < (re); \
293− (rs) = (re) + 1, pcpu_next_unpop((bitmap), &(rs), &(re), (end)))
294−
295−#define pcpu_for_each_pop_region(bitmap, rs, re, start, end) \
296− for ((rs) = (start), pcpu_next_pop((bitmap), &(rs), &(re), (end)); \
297− (rs) < (re); \
298− (rs) = (re) + 1, pcpu_next_pop((bitmap), &(rs), &(re), (end)))
299−
300273 /*
301274 * The following are helper functions to help access bitmaps and convert
302275 * between bitmap offsets to address offsets.
@@ -732,9 +705,8 @@ static void pcpu_chunk_refresh_hint(struct pcpu_chunk *chunk, bool full_scan) · 429 unmodified lines
732705 }
733706
734707 bits = 0;
735− pcpu_for_each_md_free_region(chunk, bit_off, bits) {
708+ pcpu_for_each_md_free_region(chunk, bit_off, bits)
736709 pcpu_block_update(chunk_md, bit_off, bit_off + bits);
737− }
738710 }
739711
740712 /**
@@ -749,7 +721,7 @@ static void pcpu_block_refresh_hint(struct pcpu_chunk *chunk, int index) · 8 unmodified lines
749721 {
750722 struct pcpu_block_md *block = chunk->md_blocks + index;
751723 unsigned long *alloc_map = pcpu_index_alloc_map(chunk, index);
752− int rs, re, start; /* region start, region end */
724+ unsigned int rs, re, start; /* region start, region end */
753725
754726 /* promote scan_hint to contig_hint */
755727 if (block->scan_hint) {
@@ -765,10 +737,9 @@ static void pcpu_block_refresh_hint(struct pcpu_chunk *chunk, int index) · 9 unmodified lines
765737 block->right_free = 0;
766738
767739 /* iterate over free areas and update the contig hints */
768− pcpu_for_each_unpop_region(alloc_map, rs, re, start,
769− PCPU_BITMAP_BLOCK_BITS) {
740+ bitmap_for_each_clear_region(alloc_map, rs, re, start,
741+ PCPU_BITMAP_BLOCK_BITS)
770742 pcpu_block_update(block, rs, re);
771− }
772743 }
773744
774745 /**
@@ -1041,13 +1012,13 @@ static void pcpu_block_update_hint_free(struct pcpu_chunk *chunk, int bit_off, · 266 unmodified lines
10411012 static bool pcpu_is_populated(struct pcpu_chunk *chunk, int bit_off, int bits,
10421013 int *next_off)
10431014 {
1044− int page_start, page_end, rs, re;
1015+ unsigned int page_start, page_end, rs, re;
10451016
10461017 page_start = PFN_DOWN(bit_off * PCPU_MIN_ALLOC_SIZE);
10471018 page_end = PFN_UP((bit_off + bits) * PCPU_MIN_ALLOC_SIZE);
10481019
10491020 rs = page_start;
1050− pcpu_next_unpop(chunk->populated, &rs, &re, page_end);
1021+ bitmap_next_clear_region(chunk->populated, &rs, &re, page_end);
10511022 if (rs >= page_end)
10521023 return true;
10531024
@@ -1702,13 +1673,13 @@ area_found: · 648 unmodified lines
17021673
17031674 /* populate if not all pages are already there */
17041675 if (!is_atomic) {
1705− int page_start, page_end, rs, re;
1676+ unsigned int page_start, page_end, rs, re;
17061677
17071678 page_start = PFN_DOWN(off);
17081679 page_end = PFN_UP(off + size);
17091680
1710− pcpu_for_each_unpop_region(chunk->populated, rs, re,
1711− page_start, page_end) {
1681+ bitmap_for_each_clear_region(chunk->populated, rs, re,
1682+ page_start, page_end) {
17121683 WARN_ON(chunk->immutable);
17131684
17141685 ret = pcpu_populate_chunk(chunk, rs, re, pcpu_gfp);
@@ -1858,10 +1829,10 @@ static void pcpu_balance_workfn(struct work_struct *work) · 143 unmodified lines
18581829 spin_unlock_irq(&pcpu_lock);
18591830
18601831 list_for_each_entry_safe(chunk, next, &to_free, list) {
1861− int rs, re;
1832+ unsigned int rs, re;
18621833
1863− pcpu_for_each_pop_region(chunk->populated, rs, re, 0,
1864− chunk->nr_pages) {
1834+ bitmap_for_each_set_region(chunk->populated, rs, re, 0,
1835+ chunk->nr_pages) {
18651836 pcpu_depopulate_chunk(chunk, rs, re);
18661837 spin_lock_irq(&pcpu_lock);
18671838 pcpu_chunk_depopulated(chunk, rs, re);
@@ -1893,7 +1864,7 @@ retry_pop: · 25 unmodified lines
18931864 }
18941865
18951866 for (slot = pcpu_size_to_slot(PAGE_SIZE); slot < pcpu_nr_slots; slot++) {
1896− int nr_unpop = 0, rs, re;
1867+ unsigned int nr_unpop = 0, rs, re;
18971868
18981869 if (!nr_to_pop)
18991870 break;
@@ -1910,9 +1881,9 @@ retry_pop: · 10 unmodified lines
19101881 continue;
19111882
19121883 /* @chunk can't go away while pcpu_alloc_mutex is held */
1913− pcpu_for_each_unpop_region(chunk->populated, rs, re, 0,
1914− chunk->nr_pages) {
1915− int nr = min(re - rs, nr_to_pop);
1884+ bitmap_for_each_clear_region(chunk->populated, rs, re, 0,
1885+ chunk->nr_pages) {
1886+ int nr = min_t(int, re - rs, nr_to_pop);
19161887
19171888 ret = pcpu_populate_chunk(chunk, rs, rs + nr, gfp);
19181889 if (!ret) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t