blob: c876b5b5bc18aabbe3b8381f32f44d81d7a89f69 [file] [log] [blame]
Dennis Zhou8fa3ed82017-06-19 19:28:30 -04001#ifndef _MM_PERCPU_INTERNAL_H
2#define _MM_PERCPU_INTERNAL_H
3
4#include <linux/types.h>
5#include <linux/percpu.h>
6
7struct pcpu_chunk {
Dennis Zhou30a5b532017-06-19 19:28:31 -04008#ifdef CONFIG_PERCPU_STATS
9 int nr_alloc; /* # of allocations */
10 size_t max_alloc_size; /* largest allocation size */
11#endif
12
Dennis Zhou8fa3ed82017-06-19 19:28:30 -040013 struct list_head list; /* linked to pcpu_slot lists */
14 int free_size; /* free bytes in the chunk */
15 int contig_hint; /* max contiguous size hint */
16 void *base_addr; /* base address of this chunk */
17
18 int map_used; /* # of map entries used before the sentry */
19 int map_alloc; /* # of map entries allocated */
20 int *map; /* allocation map */
21 struct list_head map_extend_list;/* on pcpu_map_extend_chunks */
22
23 void *data; /* chunk data */
24 int first_free; /* no free below this */
25 bool immutable; /* no [de]population allowed */
Dennis Zhou (Facebook)e2266702017-07-24 19:01:59 -040026 int start_offset; /* the overlap with the previous
27 region to have a page aligned
28 base_addr */
Dennis Zhou8fa3ed82017-06-19 19:28:30 -040029 int nr_populated; /* # of populated pages */
30 unsigned long populated[]; /* populated bitmap */
31};
32
33extern spinlock_t pcpu_lock;
34
35extern struct list_head *pcpu_slot;
36extern int pcpu_nr_slots;
Dennis Zhou (Facebook)6b9b6f32017-07-15 22:23:08 -040037extern int pcpu_nr_empty_pop_pages;
Dennis Zhou8fa3ed82017-06-19 19:28:30 -040038
39extern struct pcpu_chunk *pcpu_first_chunk;
40extern struct pcpu_chunk *pcpu_reserved_chunk;
41
Dennis Zhou30a5b532017-06-19 19:28:31 -040042#ifdef CONFIG_PERCPU_STATS
43
44#include <linux/spinlock.h>
45
46struct percpu_stats {
47 u64 nr_alloc; /* lifetime # of allocations */
48 u64 nr_dealloc; /* lifetime # of deallocations */
49 u64 nr_cur_alloc; /* current # of allocations */
50 u64 nr_max_alloc; /* max # of live allocations */
51 u32 nr_chunks; /* current # of live chunks */
52 u32 nr_max_chunks; /* max # of live chunks */
53 size_t min_alloc_size; /* min allocaiton size */
54 size_t max_alloc_size; /* max allocation size */
55};
56
57extern struct percpu_stats pcpu_stats;
58extern struct pcpu_alloc_info pcpu_stats_ai;
59
60/*
61 * For debug purposes. We don't care about the flexible array.
62 */
63static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
64{
65 memcpy(&pcpu_stats_ai, ai, sizeof(struct pcpu_alloc_info));
66
67 /* initialize min_alloc_size to unit_size */
68 pcpu_stats.min_alloc_size = pcpu_stats_ai.unit_size;
69}
70
71/*
72 * pcpu_stats_area_alloc - increment area allocation stats
73 * @chunk: the location of the area being allocated
74 * @size: size of area to allocate in bytes
75 *
76 * CONTEXT:
77 * pcpu_lock.
78 */
79static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
80{
81 lockdep_assert_held(&pcpu_lock);
82
83 pcpu_stats.nr_alloc++;
84 pcpu_stats.nr_cur_alloc++;
85 pcpu_stats.nr_max_alloc =
86 max(pcpu_stats.nr_max_alloc, pcpu_stats.nr_cur_alloc);
87 pcpu_stats.min_alloc_size =
88 min(pcpu_stats.min_alloc_size, size);
89 pcpu_stats.max_alloc_size =
90 max(pcpu_stats.max_alloc_size, size);
91
92 chunk->nr_alloc++;
93 chunk->max_alloc_size = max(chunk->max_alloc_size, size);
94}
95
96/*
97 * pcpu_stats_area_dealloc - decrement allocation stats
98 * @chunk: the location of the area being deallocated
99 *
100 * CONTEXT:
101 * pcpu_lock.
102 */
103static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
104{
105 lockdep_assert_held(&pcpu_lock);
106
107 pcpu_stats.nr_dealloc++;
108 pcpu_stats.nr_cur_alloc--;
109
110 chunk->nr_alloc--;
111}
112
113/*
114 * pcpu_stats_chunk_alloc - increment chunk stats
115 */
116static inline void pcpu_stats_chunk_alloc(void)
117{
Dennis Zhou303abfd2017-06-21 13:52:46 -0400118 unsigned long flags;
119 spin_lock_irqsave(&pcpu_lock, flags);
Dennis Zhou30a5b532017-06-19 19:28:31 -0400120
121 pcpu_stats.nr_chunks++;
122 pcpu_stats.nr_max_chunks =
123 max(pcpu_stats.nr_max_chunks, pcpu_stats.nr_chunks);
124
Dennis Zhou303abfd2017-06-21 13:52:46 -0400125 spin_unlock_irqrestore(&pcpu_lock, flags);
Dennis Zhou30a5b532017-06-19 19:28:31 -0400126}
127
128/*
129 * pcpu_stats_chunk_dealloc - decrement chunk stats
130 */
131static inline void pcpu_stats_chunk_dealloc(void)
132{
Dennis Zhou303abfd2017-06-21 13:52:46 -0400133 unsigned long flags;
134 spin_lock_irqsave(&pcpu_lock, flags);
Dennis Zhou30a5b532017-06-19 19:28:31 -0400135
136 pcpu_stats.nr_chunks--;
137
Dennis Zhou303abfd2017-06-21 13:52:46 -0400138 spin_unlock_irqrestore(&pcpu_lock, flags);
Dennis Zhou30a5b532017-06-19 19:28:31 -0400139}
140
141#else
142
143static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
144{
145}
146
147static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
148{
149}
150
151static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
152{
153}
154
155static inline void pcpu_stats_chunk_alloc(void)
156{
157}
158
159static inline void pcpu_stats_chunk_dealloc(void)
160{
161}
162
163#endif /* !CONFIG_PERCPU_STATS */
164
Dennis Zhou8fa3ed82017-06-19 19:28:30 -0400165#endif