linux/mm/percpu-internal.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _MM_PERCPU_INTERNAL_H
   3#define _MM_PERCPU_INTERNAL_H
   4
   5#include <linux/types.h>
   6#include <linux/percpu.h>
   7
   8/*
   9 * pcpu_block_md is the metadata block struct.
  10 * Each chunk's bitmap is split into a number of full blocks.
  11 * All units are in terms of bits.
  12 */
  13struct pcpu_block_md {
  14        int                     contig_hint;    /* contig hint for block */
  15        int                     contig_hint_start; /* block relative starting
  16                                                      position of the contig hint */
  17        int                     left_free;      /* size of free space along
  18                                                   the left side of the block */
  19        int                     right_free;     /* size of free space along
  20                                                   the right side of the block */
  21        int                     first_free;     /* block position of first free */
  22};
  23
  24struct pcpu_chunk {
  25#ifdef CONFIG_PERCPU_STATS
  26        int                     nr_alloc;       /* # of allocations */
  27        size_t                  max_alloc_size; /* largest allocation size */
  28#endif
  29
  30        struct list_head        list;           /* linked to pcpu_slot lists */
  31        int                     free_bytes;     /* free bytes in the chunk */
  32        int                     contig_bits;    /* max contiguous size hint */
  33        int                     contig_bits_start; /* contig_bits starting
  34                                                      offset */
  35        void                    *base_addr;     /* base address of this chunk */
  36
  37        unsigned long           *alloc_map;     /* allocation map */
  38        unsigned long           *bound_map;     /* boundary map */
  39        struct pcpu_block_md    *md_blocks;     /* metadata blocks */
  40
  41        void                    *data;          /* chunk data */
  42        int                     first_bit;      /* no free below this */
  43        bool                    immutable;      /* no [de]population allowed */
  44        int                     start_offset;   /* the overlap with the previous
  45                                                   region to have a page aligned
  46                                                   base_addr */
  47        int                     end_offset;     /* additional area required to
  48                                                   have the region end page
  49                                                   aligned */
  50
  51        int                     nr_pages;       /* # of pages served by this chunk */
  52        int                     nr_populated;   /* # of populated pages */
  53        int                     nr_empty_pop_pages; /* # of empty populated pages */
  54        unsigned long           populated[];    /* populated bitmap */
  55};
  56
  57extern spinlock_t pcpu_lock;
  58
  59extern struct list_head *pcpu_slot;
  60extern int pcpu_nr_slots;
  61extern int pcpu_nr_empty_pop_pages;
  62
  63extern struct pcpu_chunk *pcpu_first_chunk;
  64extern struct pcpu_chunk *pcpu_reserved_chunk;
  65
  66/**
  67 * pcpu_chunk_nr_blocks - converts nr_pages to # of md_blocks
  68 * @chunk: chunk of interest
  69 *
  70 * This conversion is from the number of physical pages that the chunk
  71 * serves to the number of bitmap blocks used.
  72 */
  73static inline int pcpu_chunk_nr_blocks(struct pcpu_chunk *chunk)
  74{
  75        return chunk->nr_pages * PAGE_SIZE / PCPU_BITMAP_BLOCK_SIZE;
  76}
  77
  78/**
  79 * pcpu_nr_pages_to_map_bits - converts the pages to size of bitmap
  80 * @pages: number of physical pages
  81 *
  82 * This conversion is from physical pages to the number of bits
  83 * required in the bitmap.
  84 */
  85static inline int pcpu_nr_pages_to_map_bits(int pages)
  86{
  87        return pages * PAGE_SIZE / PCPU_MIN_ALLOC_SIZE;
  88}
  89
  90/**
  91 * pcpu_chunk_map_bits - helper to convert nr_pages to size of bitmap
  92 * @chunk: chunk of interest
  93 *
  94 * This conversion is from the number of physical pages that the chunk
  95 * serves to the number of bits in the bitmap.
  96 */
  97static inline int pcpu_chunk_map_bits(struct pcpu_chunk *chunk)
  98{
  99        return pcpu_nr_pages_to_map_bits(chunk->nr_pages);
 100}
 101
 102#ifdef CONFIG_PERCPU_STATS
 103
 104#include <linux/spinlock.h>
 105
 106struct percpu_stats {
 107        u64 nr_alloc;           /* lifetime # of allocations */
 108        u64 nr_dealloc;         /* lifetime # of deallocations */
 109        u64 nr_cur_alloc;       /* current # of allocations */
 110        u64 nr_max_alloc;       /* max # of live allocations */
 111        u32 nr_chunks;          /* current # of live chunks */
 112        u32 nr_max_chunks;      /* max # of live chunks */
 113        size_t min_alloc_size;  /* min allocaiton size */
 114        size_t max_alloc_size;  /* max allocation size */
 115};
 116
 117extern struct percpu_stats pcpu_stats;
 118extern struct pcpu_alloc_info pcpu_stats_ai;
 119
 120/*
 121 * For debug purposes. We don't care about the flexible array.
 122 */
 123static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
 124{
 125        memcpy(&pcpu_stats_ai, ai, sizeof(struct pcpu_alloc_info));
 126
 127        /* initialize min_alloc_size to unit_size */
 128        pcpu_stats.min_alloc_size = pcpu_stats_ai.unit_size;
 129}
 130
 131/*
 132 * pcpu_stats_area_alloc - increment area allocation stats
 133 * @chunk: the location of the area being allocated
 134 * @size: size of area to allocate in bytes
 135 *
 136 * CONTEXT:
 137 * pcpu_lock.
 138 */
 139static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
 140{
 141        lockdep_assert_held(&pcpu_lock);
 142
 143        pcpu_stats.nr_alloc++;
 144        pcpu_stats.nr_cur_alloc++;
 145        pcpu_stats.nr_max_alloc =
 146                max(pcpu_stats.nr_max_alloc, pcpu_stats.nr_cur_alloc);
 147        pcpu_stats.min_alloc_size =
 148                min(pcpu_stats.min_alloc_size, size);
 149        pcpu_stats.max_alloc_size =
 150                max(pcpu_stats.max_alloc_size, size);
 151
 152        chunk->nr_alloc++;
 153        chunk->max_alloc_size = max(chunk->max_alloc_size, size);
 154}
 155
 156/*
 157 * pcpu_stats_area_dealloc - decrement allocation stats
 158 * @chunk: the location of the area being deallocated
 159 *
 160 * CONTEXT:
 161 * pcpu_lock.
 162 */
 163static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
 164{
 165        lockdep_assert_held(&pcpu_lock);
 166
 167        pcpu_stats.nr_dealloc++;
 168        pcpu_stats.nr_cur_alloc--;
 169
 170        chunk->nr_alloc--;
 171}
 172
 173/*
 174 * pcpu_stats_chunk_alloc - increment chunk stats
 175 */
 176static inline void pcpu_stats_chunk_alloc(void)
 177{
 178        unsigned long flags;
 179        spin_lock_irqsave(&pcpu_lock, flags);
 180
 181        pcpu_stats.nr_chunks++;
 182        pcpu_stats.nr_max_chunks =
 183                max(pcpu_stats.nr_max_chunks, pcpu_stats.nr_chunks);
 184
 185        spin_unlock_irqrestore(&pcpu_lock, flags);
 186}
 187
 188/*
 189 * pcpu_stats_chunk_dealloc - decrement chunk stats
 190 */
 191static inline void pcpu_stats_chunk_dealloc(void)
 192{
 193        unsigned long flags;
 194        spin_lock_irqsave(&pcpu_lock, flags);
 195
 196        pcpu_stats.nr_chunks--;
 197
 198        spin_unlock_irqrestore(&pcpu_lock, flags);
 199}
 200
 201#else
 202
 203static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
 204{
 205}
 206
 207static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
 208{
 209}
 210
 211static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
 212{
 213}
 214
 215static inline void pcpu_stats_chunk_alloc(void)
 216{
 217}
 218
 219static inline void pcpu_stats_chunk_dealloc(void)
 220{
 221}
 222
 223#endif /* !CONFIG_PERCPU_STATS */
 224
 225#endif
 226