LCOV - code coverage report
Current view: top level - mm - percpu-internal.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 4 100.0 %
Date: 2023-08-24 13:40:31 Functions: 0 0 -

          Line data    Source code
       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             : #include <linux/memcontrol.h>
       8             : 
       9             : /*
      10             :  * pcpu_block_md is the metadata block struct.
      11             :  * Each chunk's bitmap is split into a number of full blocks.
      12             :  * All units are in terms of bits.
      13             :  *
      14             :  * The scan hint is the largest known contiguous area before the contig hint.
      15             :  * It is not necessarily the actual largest contig hint though.  There is an
      16             :  * invariant that the scan_hint_start > contig_hint_start iff
      17             :  * scan_hint == contig_hint.  This is necessary because when scanning forward,
      18             :  * we don't know if a new contig hint would be better than the current one.
      19             :  */
      20             : struct pcpu_block_md {
      21             :         int                     scan_hint;      /* scan hint for block */
      22             :         int                     scan_hint_start; /* block relative starting
      23             :                                                     position of the scan hint */
      24             :         int                     contig_hint;    /* contig hint for block */
      25             :         int                     contig_hint_start; /* block relative starting
      26             :                                                       position of the contig hint */
      27             :         int                     left_free;      /* size of free space along
      28             :                                                    the left side of the block */
      29             :         int                     right_free;     /* size of free space along
      30             :                                                    the right side of the block */
      31             :         int                     first_free;     /* block position of first free */
      32             :         int                     nr_bits;        /* total bits responsible for */
      33             : };
      34             : 
      35             : struct pcpu_chunk {
      36             : #ifdef CONFIG_PERCPU_STATS
      37             :         int                     nr_alloc;       /* # of allocations */
      38             :         size_t                  max_alloc_size; /* largest allocation size */
      39             : #endif
      40             : 
      41             :         struct list_head        list;           /* linked to pcpu_slot lists */
      42             :         int                     free_bytes;     /* free bytes in the chunk */
      43             :         struct pcpu_block_md    chunk_md;
      44             :         unsigned long           *bound_map;     /* boundary map */
      45             : 
      46             :         /*
      47             :          * base_addr is the base address of this chunk.
      48             :          * To reduce false sharing, current layout is optimized to make sure
      49             :          * base_addr locate in the different cacheline with free_bytes and
      50             :          * chunk_md.
      51             :          */
      52             :         void                    *base_addr ____cacheline_aligned_in_smp;
      53             : 
      54             :         unsigned long           *alloc_map;     /* allocation map */
      55             :         struct pcpu_block_md    *md_blocks;     /* metadata blocks */
      56             : 
      57             :         void                    *data;          /* chunk data */
      58             :         bool                    immutable;      /* no [de]population allowed */
      59             :         bool                    isolated;       /* isolated from active chunk
      60             :                                                    slots */
      61             :         int                     start_offset;   /* the overlap with the previous
      62             :                                                    region to have a page aligned
      63             :                                                    base_addr */
      64             :         int                     end_offset;     /* additional area required to
      65             :                                                    have the region end page
      66             :                                                    aligned */
      67             : #ifdef CONFIG_MEMCG_KMEM
      68             :         struct obj_cgroup       **obj_cgroups;  /* vector of object cgroups */
      69             : #endif
      70             : 
      71             :         int                     nr_pages;       /* # of pages served by this chunk */
      72             :         int                     nr_populated;   /* # of populated pages */
      73             :         int                     nr_empty_pop_pages; /* # of empty populated pages */
      74             :         unsigned long           populated[];    /* populated bitmap */
      75             : };
      76             : 
      77             : extern spinlock_t pcpu_lock;
      78             : 
      79             : extern struct list_head *pcpu_chunk_lists;
      80             : extern int pcpu_nr_slots;
      81             : extern int pcpu_sidelined_slot;
      82             : extern int pcpu_to_depopulate_slot;
      83             : extern int pcpu_nr_empty_pop_pages;
      84             : 
      85             : extern struct pcpu_chunk *pcpu_first_chunk;
      86             : extern struct pcpu_chunk *pcpu_reserved_chunk;
      87             : 
      88             : /**
      89             :  * pcpu_chunk_nr_blocks - converts nr_pages to # of md_blocks
      90             :  * @chunk: chunk of interest
      91             :  *
      92             :  * This conversion is from the number of physical pages that the chunk
      93             :  * serves to the number of bitmap blocks used.
      94             :  */
      95             : static inline int pcpu_chunk_nr_blocks(struct pcpu_chunk *chunk)
      96             : {
      97        2078 :         return chunk->nr_pages * PAGE_SIZE / PCPU_BITMAP_BLOCK_SIZE;
      98             : }
      99             : 
     100             : /**
     101             :  * pcpu_nr_pages_to_map_bits - converts the pages to size of bitmap
     102             :  * @pages: number of physical pages
     103             :  *
     104             :  * This conversion is from physical pages to the number of bits
     105             :  * required in the bitmap.
     106             :  */
     107             : static inline int pcpu_nr_pages_to_map_bits(int pages)
     108             : {
     109        1314 :         return pages * PAGE_SIZE / PCPU_MIN_ALLOC_SIZE;
     110             : }
     111             : 
     112             : /**
     113             :  * pcpu_chunk_map_bits - helper to convert nr_pages to size of bitmap
     114             :  * @chunk: chunk of interest
     115             :  *
     116             :  * This conversion is from the number of physical pages that the chunk
     117             :  * serves to the number of bits in the bitmap.
     118             :  */
     119             : static inline int pcpu_chunk_map_bits(struct pcpu_chunk *chunk)
     120             : {
     121        2628 :         return pcpu_nr_pages_to_map_bits(chunk->nr_pages);
     122             : }
     123             : 
     124             : /**
     125             :  * pcpu_obj_full_size - helper to calculate size of each accounted object
     126             :  * @size: size of area to allocate in bytes
     127             :  *
     128             :  * For each accounted object there is an extra space which is used to store
     129             :  * obj_cgroup membership if kmemcg is not disabled. Charge it too.
     130             :  */
     131             : static inline size_t pcpu_obj_full_size(size_t size)
     132             : {
     133         242 :         size_t extra_size = 0;
     134             : 
     135             : #ifdef CONFIG_MEMCG_KMEM
     136             :         if (!mem_cgroup_kmem_disabled())
     137             :                 extra_size += size / PCPU_MIN_ALLOC_SIZE * sizeof(struct obj_cgroup *);
     138             : #endif
     139             : 
     140             :         return size * num_possible_cpus() + extra_size;
     141             : }
     142             : 
     143             : #ifdef CONFIG_PERCPU_STATS
     144             : 
     145             : #include <linux/spinlock.h>
     146             : 
     147             : struct percpu_stats {
     148             :         u64 nr_alloc;           /* lifetime # of allocations */
     149             :         u64 nr_dealloc;         /* lifetime # of deallocations */
     150             :         u64 nr_cur_alloc;       /* current # of allocations */
     151             :         u64 nr_max_alloc;       /* max # of live allocations */
     152             :         u32 nr_chunks;          /* current # of live chunks */
     153             :         u32 nr_max_chunks;      /* max # of live chunks */
     154             :         size_t min_alloc_size;  /* min allocation size */
     155             :         size_t max_alloc_size;  /* max allocation size */
     156             : };
     157             : 
     158             : extern struct percpu_stats pcpu_stats;
     159             : extern struct pcpu_alloc_info pcpu_stats_ai;
     160             : 
     161             : /*
     162             :  * For debug purposes. We don't care about the flexible array.
     163             :  */
     164             : static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
     165             : {
     166             :         memcpy(&pcpu_stats_ai, ai, sizeof(struct pcpu_alloc_info));
     167             : 
     168             :         /* initialize min_alloc_size to unit_size */
     169             :         pcpu_stats.min_alloc_size = pcpu_stats_ai.unit_size;
     170             : }
     171             : 
     172             : /*
     173             :  * pcpu_stats_area_alloc - increment area allocation stats
     174             :  * @chunk: the location of the area being allocated
     175             :  * @size: size of area to allocate in bytes
     176             :  *
     177             :  * CONTEXT:
     178             :  * pcpu_lock.
     179             :  */
     180             : static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
     181             : {
     182             :         lockdep_assert_held(&pcpu_lock);
     183             : 
     184             :         pcpu_stats.nr_alloc++;
     185             :         pcpu_stats.nr_cur_alloc++;
     186             :         pcpu_stats.nr_max_alloc =
     187             :                 max(pcpu_stats.nr_max_alloc, pcpu_stats.nr_cur_alloc);
     188             :         pcpu_stats.min_alloc_size =
     189             :                 min(pcpu_stats.min_alloc_size, size);
     190             :         pcpu_stats.max_alloc_size =
     191             :                 max(pcpu_stats.max_alloc_size, size);
     192             : 
     193             :         chunk->nr_alloc++;
     194             :         chunk->max_alloc_size = max(chunk->max_alloc_size, size);
     195             : }
     196             : 
     197             : /*
     198             :  * pcpu_stats_area_dealloc - decrement allocation stats
     199             :  * @chunk: the location of the area being deallocated
     200             :  *
     201             :  * CONTEXT:
     202             :  * pcpu_lock.
     203             :  */
     204             : static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
     205             : {
     206             :         lockdep_assert_held(&pcpu_lock);
     207             : 
     208             :         pcpu_stats.nr_dealloc++;
     209             :         pcpu_stats.nr_cur_alloc--;
     210             : 
     211             :         chunk->nr_alloc--;
     212             : }
     213             : 
     214             : /*
     215             :  * pcpu_stats_chunk_alloc - increment chunk stats
     216             :  */
     217             : static inline void pcpu_stats_chunk_alloc(void)
     218             : {
     219             :         unsigned long flags;
     220             :         spin_lock_irqsave(&pcpu_lock, flags);
     221             : 
     222             :         pcpu_stats.nr_chunks++;
     223             :         pcpu_stats.nr_max_chunks =
     224             :                 max(pcpu_stats.nr_max_chunks, pcpu_stats.nr_chunks);
     225             : 
     226             :         spin_unlock_irqrestore(&pcpu_lock, flags);
     227             : }
     228             : 
     229             : /*
     230             :  * pcpu_stats_chunk_dealloc - decrement chunk stats
     231             :  */
     232             : static inline void pcpu_stats_chunk_dealloc(void)
     233             : {
     234             :         unsigned long flags;
     235             :         spin_lock_irqsave(&pcpu_lock, flags);
     236             : 
     237             :         pcpu_stats.nr_chunks--;
     238             : 
     239             :         spin_unlock_irqrestore(&pcpu_lock, flags);
     240             : }
     241             : 
     242             : #else
     243             : 
     244             : static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
     245             : {
     246             : }
     247             : 
     248             : static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
     249             : {
     250             : }
     251             : 
     252             : static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
     253             : {
     254             : }
     255             : 
     256             : static inline void pcpu_stats_chunk_alloc(void)
     257             : {
     258             : }
     259             : 
     260             : static inline void pcpu_stats_chunk_dealloc(void)
     261             : {
     262             : }
     263             : 
     264             : #endif /* !CONFIG_PERCPU_STATS */
     265             : 
     266             : #endif

Generated by: LCOV version 1.14