Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2#ifndef __TRACING_MAP_H
  3#define __TRACING_MAP_H
  4
  5#define TRACING_MAP_BITS_DEFAULT	11
  6#define TRACING_MAP_BITS_MAX		17
  7#define TRACING_MAP_BITS_MIN		7
  8
  9#define TRACING_MAP_KEYS_MAX		3
 10#define TRACING_MAP_VALS_MAX		3
 11#define TRACING_MAP_FIELDS_MAX		(TRACING_MAP_KEYS_MAX + \
 12					 TRACING_MAP_VALS_MAX)
 13#define TRACING_MAP_VARS_MAX		16
 14#define TRACING_MAP_SORT_KEYS_MAX	2
 15
 16typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b);
 17
 18/*
 19 * This is an overview of the tracing_map data structures and how they
 20 * relate to the tracing_map API.  The details of the algorithms
 21 * aren't discussed here - this is just a general overview of the data
 22 * structures and how they interact with the API.
 23 *
 24 * The central data structure of the tracing_map is an initially
 25 * zeroed array of struct tracing_map_entry (stored in the map field
 26 * of struct tracing_map).  tracing_map_entry is a very simple data
 27 * structure containing only two fields: a 32-bit unsigned 'key'
 28 * variable and a pointer named 'val'.  This array of struct
 29 * tracing_map_entry is essentially a hash table which will be
 30 * modified by a single function, tracing_map_insert(), but which can
 31 * be traversed and read by a user at any time (though the user does
 32 * this indirectly via an array of tracing_map_sort_entry - see the
 33 * explanation of that data structure in the discussion of the
 34 * sorting-related data structures below).
 35 *
 36 * The central function of the tracing_map API is
 37 * tracing_map_insert().  tracing_map_insert() hashes the
 38 * arbitrarily-sized key passed into it into a 32-bit unsigned key.
 39 * It then uses this key, truncated to the array size, as an index
 40 * into the array of tracing_map_entries.  If the value of the 'key'
 41 * field of the tracing_map_entry found at that location is 0, then
 42 * that entry is considered to be free and can be claimed, by
 43 * replacing the 0 in the 'key' field of the tracing_map_entry with
 44 * the new 32-bit hashed key.  Once claimed, that tracing_map_entry's
 45 * 'val' field is then used to store a unique element which will be
 46 * forever associated with that 32-bit hashed key in the
 47 * tracing_map_entry.
 48 *
 49 * That unique element now in the tracing_map_entry's 'val' field is
 50 * an instance of tracing_map_elt, where 'elt' in the latter part of
 51 * that variable name is short for 'element'.  The purpose of a
 52 * tracing_map_elt is to hold values specific to the particular
 53 * 32-bit hashed key it's associated with.  Things such as the unique
 54 * set of aggregated sums associated with the 32-bit hashed key, along
 55 * with a copy of the full key associated with the entry, and which
 56 * was used to produce the 32-bit hashed key.
 57 *
 58 * When tracing_map_create() is called to create the tracing map, the
 59 * user specifies (indirectly via the map_bits param, the details are
 60 * unimportant for this discussion) the maximum number of elements
 61 * that the map can hold (stored in the max_elts field of struct
 62 * tracing_map).  This is the maximum possible number of
 63 * tracing_map_entries in the tracing_map_entry array which can be
 64 * 'claimed' as described in the above discussion, and therefore is
 65 * also the maximum number of tracing_map_elts that can be associated
 66 * with the tracing_map_entry array in the tracing_map.  Because of
 67 * the way the insertion algorithm works, the size of the allocated
 68 * tracing_map_entry array is always twice the maximum number of
 69 * elements (2 * max_elts).  This value is stored in the map_size
 70 * field of struct tracing_map.
 71 *
 72 * Because tracing_map_insert() needs to work from any context,
 73 * including from within the memory allocation functions themselves,
 74 * both the tracing_map_entry array and a pool of max_elts
 75 * tracing_map_elts are pre-allocated before any call is made to
 76 * tracing_map_insert().
 77 *
 78 * The tracing_map_entry array is allocated as a single block by
 79 * tracing_map_create().
 80 *
 81 * Because the tracing_map_elts are much larger objects and can't
 82 * generally be allocated together as a single large array without
 83 * failure, they're allocated individually, by tracing_map_init().
 84 *
 85 * The pool of tracing_map_elts are allocated by tracing_map_init()
 86 * rather than by tracing_map_create() because at the time
 87 * tracing_map_create() is called, there isn't enough information to
 88 * create the tracing_map_elts.  Specifically,the user first needs to
 89 * tell the tracing_map implementation how many fields the
 90 * tracing_map_elts contain, and which types of fields they are (key
 91 * or sum).  The user does this via the tracing_map_add_sum_field()
 92 * and tracing_map_add_key_field() functions, following which the user
 93 * calls tracing_map_init() to finish up the tracing map setup.  The
 94 * array holding the pointers which make up the pre-allocated pool of
 95 * tracing_map_elts is allocated as a single block and is stored in
 96 * the elts field of struct tracing_map.
 97 *
 98 * There is also a set of structures used for sorting that might
 99 * benefit from some minimal explanation.
100 *
101 * struct tracing_map_sort_key is used to drive the sort at any given
102 * time.  By 'any given time' we mean that a different
103 * tracing_map_sort_key will be used at different times depending on
104 * whether the sort currently being performed is a primary or a
105 * secondary sort.
106 *
107 * The sort key is very simple, consisting of the field index of the
108 * tracing_map_elt field to sort on (which the user saved when adding
109 * the field), and whether the sort should be done in an ascending or
110 * descending order.
111 *
112 * For the convenience of the sorting code, a tracing_map_sort_entry
113 * is created for each tracing_map_elt, again individually allocated
114 * to avoid failures that might be expected if allocated as a single
115 * large array of struct tracing_map_sort_entry.
116 * tracing_map_sort_entry instances are the objects expected by the
117 * various internal sorting functions, and are also what the user
118 * ultimately receives after calling tracing_map_sort_entries().
119 * Because it doesn't make sense for users to access an unordered and
120 * sparsely populated tracing_map directly, the
121 * tracing_map_sort_entries() function is provided so that users can
122 * retrieve a sorted list of all existing elements.  In addition to
123 * the associated tracing_map_elt 'elt' field contained within the
124 * tracing_map_sort_entry, which is the object of interest to the
125 * user, tracing_map_sort_entry objects contain a number of additional
126 * fields which are used for caching and internal purposes and can
127 * safely be ignored.
128*/
129
130struct tracing_map_field {
131	tracing_map_cmp_fn_t		cmp_fn;
132	union {
133		atomic64_t			sum;
134		unsigned int			offset;
135	};
136};
137
138struct tracing_map_elt {
139	struct tracing_map		*map;
140	struct tracing_map_field	*fields;
141	atomic64_t			*vars;
142	bool				*var_set;
143	void				*key;
144	void				*private_data;
145};
146
147struct tracing_map_entry {
148	u32				key;
149	struct tracing_map_elt		*val;
150};
151
152struct tracing_map_sort_key {
153	unsigned int			field_idx;
154	bool				descending;
155};
156
157struct tracing_map_sort_entry {
158	void				*key;
159	struct tracing_map_elt		*elt;
160	bool				elt_copied;
161	bool				dup;
162};
163
164struct tracing_map_array {
165	unsigned int entries_per_page;
166	unsigned int entry_size_shift;
167	unsigned int entry_shift;
168	unsigned int entry_mask;
169	unsigned int n_pages;
170	void **pages;
171};
172
173#define TRACING_MAP_ARRAY_ELT(array, idx)				\
174	(array->pages[idx >> array->entry_shift] +			\
175	 ((idx & array->entry_mask) << array->entry_size_shift))
176
177#define TRACING_MAP_ENTRY(array, idx)					\
178	((struct tracing_map_entry *)TRACING_MAP_ARRAY_ELT(array, idx))
179
180#define TRACING_MAP_ELT(array, idx)					\
181	((struct tracing_map_elt **)TRACING_MAP_ARRAY_ELT(array, idx))
182
183struct tracing_map {
184	unsigned int			key_size;
185	unsigned int			map_bits;
186	unsigned int			map_size;
187	unsigned int			max_elts;
188	atomic_t			next_elt;
189	struct tracing_map_array	*elts;
190	struct tracing_map_array	*map;
191	const struct tracing_map_ops	*ops;
192	void				*private_data;
193	struct tracing_map_field	fields[TRACING_MAP_FIELDS_MAX];
194	unsigned int			n_fields;
195	int				key_idx[TRACING_MAP_KEYS_MAX];
196	unsigned int			n_keys;
197	struct tracing_map_sort_key	sort_key;
198	unsigned int			n_vars;
199	atomic64_t			hits;
200	atomic64_t			drops;
201};
202
203/**
204 * struct tracing_map_ops - callbacks for tracing_map
205 *
206 * The methods in this structure define callback functions for various
207 * operations on a tracing_map or objects related to a tracing_map.
208 *
209 * For a detailed description of tracing_map_elt objects please see
210 * the overview of tracing_map data structures at the beginning of
211 * this file.
212 *
213 * All the methods below are optional.
214 *
215 * @elt_alloc: When a tracing_map_elt is allocated, this function, if
216 *	defined, will be called and gives clients the opportunity to
217 *	allocate additional data and attach it to the element
218 *	(tracing_map_elt->private_data is meant for that purpose).
219 *	Element allocation occurs before tracing begins, when the
220 *	tracing_map_init() call is made by client code.
221 *
 
 
 
 
 
222 * @elt_free: When a tracing_map_elt is freed, this function is called
223 *	and allows client-allocated per-element data to be freed.
224 *
225 * @elt_clear: This callback allows per-element client-defined data to
226 *	be cleared, if applicable.
227 *
228 * @elt_init: This callback allows per-element client-defined data to
229 *	be initialized when used i.e. when the element is actually
230 *	claimed by tracing_map_insert() in the context of the map
231 *	insertion.
232 */
233struct tracing_map_ops {
234	int			(*elt_alloc)(struct tracing_map_elt *elt);
 
 
235	void			(*elt_free)(struct tracing_map_elt *elt);
236	void			(*elt_clear)(struct tracing_map_elt *elt);
237	void			(*elt_init)(struct tracing_map_elt *elt);
238};
239
240extern struct tracing_map *
241tracing_map_create(unsigned int map_bits,
242		   unsigned int key_size,
243		   const struct tracing_map_ops *ops,
244		   void *private_data);
245extern int tracing_map_init(struct tracing_map *map);
246
247extern int tracing_map_add_sum_field(struct tracing_map *map);
248extern int tracing_map_add_var(struct tracing_map *map);
249extern int tracing_map_add_key_field(struct tracing_map *map,
250				     unsigned int offset,
251				     tracing_map_cmp_fn_t cmp_fn);
252
253extern void tracing_map_destroy(struct tracing_map *map);
254extern void tracing_map_clear(struct tracing_map *map);
255
256extern struct tracing_map_elt *
257tracing_map_insert(struct tracing_map *map, void *key);
258extern struct tracing_map_elt *
259tracing_map_lookup(struct tracing_map *map, void *key);
260
261extern tracing_map_cmp_fn_t tracing_map_cmp_num(int field_size,
262						int field_is_signed);
263extern int tracing_map_cmp_string(void *val_a, void *val_b);
264extern int tracing_map_cmp_none(void *val_a, void *val_b);
265
266extern void tracing_map_update_sum(struct tracing_map_elt *elt,
267				   unsigned int i, u64 n);
268extern void tracing_map_set_var(struct tracing_map_elt *elt,
269				unsigned int i, u64 n);
270extern bool tracing_map_var_set(struct tracing_map_elt *elt, unsigned int i);
271extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i);
272extern u64 tracing_map_read_var(struct tracing_map_elt *elt, unsigned int i);
273extern u64 tracing_map_read_var_once(struct tracing_map_elt *elt, unsigned int i);
274
 
275extern int
276tracing_map_sort_entries(struct tracing_map *map,
277			 struct tracing_map_sort_key *sort_keys,
278			 unsigned int n_sort_keys,
279			 struct tracing_map_sort_entry ***sort_entries);
280
281extern void
282tracing_map_destroy_sort_entries(struct tracing_map_sort_entry **entries,
283				 unsigned int n_entries);
284#endif /* __TRACING_MAP_H */
v4.10.11
 
  1#ifndef __TRACING_MAP_H
  2#define __TRACING_MAP_H
  3
  4#define TRACING_MAP_BITS_DEFAULT	11
  5#define TRACING_MAP_BITS_MAX		17
  6#define TRACING_MAP_BITS_MIN		7
  7
  8#define TRACING_MAP_KEYS_MAX		2
  9#define TRACING_MAP_VALS_MAX		3
 10#define TRACING_MAP_FIELDS_MAX		(TRACING_MAP_KEYS_MAX + \
 11					 TRACING_MAP_VALS_MAX)
 
 12#define TRACING_MAP_SORT_KEYS_MAX	2
 13
 14typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b);
 15
 16/*
 17 * This is an overview of the tracing_map data structures and how they
 18 * relate to the tracing_map API.  The details of the algorithms
 19 * aren't discussed here - this is just a general overview of the data
 20 * structures and how they interact with the API.
 21 *
 22 * The central data structure of the tracing_map is an initially
 23 * zeroed array of struct tracing_map_entry (stored in the map field
 24 * of struct tracing_map).  tracing_map_entry is a very simple data
 25 * structure containing only two fields: a 32-bit unsigned 'key'
 26 * variable and a pointer named 'val'.  This array of struct
 27 * tracing_map_entry is essentially a hash table which will be
 28 * modified by a single function, tracing_map_insert(), but which can
 29 * be traversed and read by a user at any time (though the user does
 30 * this indirectly via an array of tracing_map_sort_entry - see the
 31 * explanation of that data structure in the discussion of the
 32 * sorting-related data structures below).
 33 *
 34 * The central function of the tracing_map API is
 35 * tracing_map_insert().  tracing_map_insert() hashes the
 36 * arbitrarily-sized key passed into it into a 32-bit unsigned key.
 37 * It then uses this key, truncated to the array size, as an index
 38 * into the array of tracing_map_entries.  If the value of the 'key'
 39 * field of the tracing_map_entry found at that location is 0, then
 40 * that entry is considered to be free and can be claimed, by
 41 * replacing the 0 in the 'key' field of the tracing_map_entry with
 42 * the new 32-bit hashed key.  Once claimed, that tracing_map_entry's
 43 * 'val' field is then used to store a unique element which will be
 44 * forever associated with that 32-bit hashed key in the
 45 * tracing_map_entry.
 46 *
 47 * That unique element now in the tracing_map_entry's 'val' field is
 48 * an instance of tracing_map_elt, where 'elt' in the latter part of
 49 * that variable name is short for 'element'.  The purpose of a
 50 * tracing_map_elt is to hold values specific to the particular
 51 * 32-bit hashed key it's assocated with.  Things such as the unique
 52 * set of aggregated sums associated with the 32-bit hashed key, along
 53 * with a copy of the full key associated with the entry, and which
 54 * was used to produce the 32-bit hashed key.
 55 *
 56 * When tracing_map_create() is called to create the tracing map, the
 57 * user specifies (indirectly via the map_bits param, the details are
 58 * unimportant for this discussion) the maximum number of elements
 59 * that the map can hold (stored in the max_elts field of struct
 60 * tracing_map).  This is the maximum possible number of
 61 * tracing_map_entries in the tracing_map_entry array which can be
 62 * 'claimed' as described in the above discussion, and therefore is
 63 * also the maximum number of tracing_map_elts that can be associated
 64 * with the tracing_map_entry array in the tracing_map.  Because of
 65 * the way the insertion algorithm works, the size of the allocated
 66 * tracing_map_entry array is always twice the maximum number of
 67 * elements (2 * max_elts).  This value is stored in the map_size
 68 * field of struct tracing_map.
 69 *
 70 * Because tracing_map_insert() needs to work from any context,
 71 * including from within the memory allocation functions themselves,
 72 * both the tracing_map_entry array and a pool of max_elts
 73 * tracing_map_elts are pre-allocated before any call is made to
 74 * tracing_map_insert().
 75 *
 76 * The tracing_map_entry array is allocated as a single block by
 77 * tracing_map_create().
 78 *
 79 * Because the tracing_map_elts are much larger objects and can't
 80 * generally be allocated together as a single large array without
 81 * failure, they're allocated individually, by tracing_map_init().
 82 *
 83 * The pool of tracing_map_elts are allocated by tracing_map_init()
 84 * rather than by tracing_map_create() because at the time
 85 * tracing_map_create() is called, there isn't enough information to
 86 * create the tracing_map_elts.  Specifically,the user first needs to
 87 * tell the tracing_map implementation how many fields the
 88 * tracing_map_elts contain, and which types of fields they are (key
 89 * or sum).  The user does this via the tracing_map_add_sum_field()
 90 * and tracing_map_add_key_field() functions, following which the user
 91 * calls tracing_map_init() to finish up the tracing map setup.  The
 92 * array holding the pointers which make up the pre-allocated pool of
 93 * tracing_map_elts is allocated as a single block and is stored in
 94 * the elts field of struct tracing_map.
 95 *
 96 * There is also a set of structures used for sorting that might
 97 * benefit from some minimal explanation.
 98 *
 99 * struct tracing_map_sort_key is used to drive the sort at any given
100 * time.  By 'any given time' we mean that a different
101 * tracing_map_sort_key will be used at different times depending on
102 * whether the sort currently being performed is a primary or a
103 * secondary sort.
104 *
105 * The sort key is very simple, consisting of the field index of the
106 * tracing_map_elt field to sort on (which the user saved when adding
107 * the field), and whether the sort should be done in an ascending or
108 * descending order.
109 *
110 * For the convenience of the sorting code, a tracing_map_sort_entry
111 * is created for each tracing_map_elt, again individually allocated
112 * to avoid failures that might be expected if allocated as a single
113 * large array of struct tracing_map_sort_entry.
114 * tracing_map_sort_entry instances are the objects expected by the
115 * various internal sorting functions, and are also what the user
116 * ultimately receives after calling tracing_map_sort_entries().
117 * Because it doesn't make sense for users to access an unordered and
118 * sparsely populated tracing_map directly, the
119 * tracing_map_sort_entries() function is provided so that users can
120 * retrieve a sorted list of all existing elements.  In addition to
121 * the associated tracing_map_elt 'elt' field contained within the
122 * tracing_map_sort_entry, which is the object of interest to the
123 * user, tracing_map_sort_entry objects contain a number of additional
124 * fields which are used for caching and internal purposes and can
125 * safely be ignored.
126*/
127
128struct tracing_map_field {
129	tracing_map_cmp_fn_t		cmp_fn;
130	union {
131		atomic64_t			sum;
132		unsigned int			offset;
133	};
134};
135
136struct tracing_map_elt {
137	struct tracing_map		*map;
138	struct tracing_map_field	*fields;
 
 
139	void				*key;
140	void				*private_data;
141};
142
143struct tracing_map_entry {
144	u32				key;
145	struct tracing_map_elt		*val;
146};
147
148struct tracing_map_sort_key {
149	unsigned int			field_idx;
150	bool				descending;
151};
152
153struct tracing_map_sort_entry {
154	void				*key;
155	struct tracing_map_elt		*elt;
156	bool				elt_copied;
157	bool				dup;
158};
159
160struct tracing_map_array {
161	unsigned int entries_per_page;
162	unsigned int entry_size_shift;
163	unsigned int entry_shift;
164	unsigned int entry_mask;
165	unsigned int n_pages;
166	void **pages;
167};
168
169#define TRACING_MAP_ARRAY_ELT(array, idx)				\
170	(array->pages[idx >> array->entry_shift] +			\
171	 ((idx & array->entry_mask) << array->entry_size_shift))
172
173#define TRACING_MAP_ENTRY(array, idx)					\
174	((struct tracing_map_entry *)TRACING_MAP_ARRAY_ELT(array, idx))
175
176#define TRACING_MAP_ELT(array, idx)					\
177	((struct tracing_map_elt **)TRACING_MAP_ARRAY_ELT(array, idx))
178
179struct tracing_map {
180	unsigned int			key_size;
181	unsigned int			map_bits;
182	unsigned int			map_size;
183	unsigned int			max_elts;
184	atomic_t			next_elt;
185	struct tracing_map_array	*elts;
186	struct tracing_map_array	*map;
187	const struct tracing_map_ops	*ops;
188	void				*private_data;
189	struct tracing_map_field	fields[TRACING_MAP_FIELDS_MAX];
190	unsigned int			n_fields;
191	int				key_idx[TRACING_MAP_KEYS_MAX];
192	unsigned int			n_keys;
193	struct tracing_map_sort_key	sort_key;
 
194	atomic64_t			hits;
195	atomic64_t			drops;
196};
197
198/**
199 * struct tracing_map_ops - callbacks for tracing_map
200 *
201 * The methods in this structure define callback functions for various
202 * operations on a tracing_map or objects related to a tracing_map.
203 *
204 * For a detailed description of tracing_map_elt objects please see
205 * the overview of tracing_map data structures at the beginning of
206 * this file.
207 *
208 * All the methods below are optional.
209 *
210 * @elt_alloc: When a tracing_map_elt is allocated, this function, if
211 *	defined, will be called and gives clients the opportunity to
212 *	allocate additional data and attach it to the element
213 *	(tracing_map_elt->private_data is meant for that purpose).
214 *	Element allocation occurs before tracing begins, when the
215 *	tracing_map_init() call is made by client code.
216 *
217 * @elt_copy: At certain points in the lifetime of an element, it may
218 *	need to be copied.  The copy should include a copy of the
219 *	client-allocated data, which can be copied into the 'to'
220 *	element from the 'from' element.
221 *
222 * @elt_free: When a tracing_map_elt is freed, this function is called
223 *	and allows client-allocated per-element data to be freed.
224 *
225 * @elt_clear: This callback allows per-element client-defined data to
226 *	be cleared, if applicable.
227 *
228 * @elt_init: This callback allows per-element client-defined data to
229 *	be initialized when used i.e. when the element is actually
230 *	claimed by tracing_map_insert() in the context of the map
231 *	insertion.
232 */
233struct tracing_map_ops {
234	int			(*elt_alloc)(struct tracing_map_elt *elt);
235	void			(*elt_copy)(struct tracing_map_elt *to,
236					    struct tracing_map_elt *from);
237	void			(*elt_free)(struct tracing_map_elt *elt);
238	void			(*elt_clear)(struct tracing_map_elt *elt);
239	void			(*elt_init)(struct tracing_map_elt *elt);
240};
241
242extern struct tracing_map *
243tracing_map_create(unsigned int map_bits,
244		   unsigned int key_size,
245		   const struct tracing_map_ops *ops,
246		   void *private_data);
247extern int tracing_map_init(struct tracing_map *map);
248
249extern int tracing_map_add_sum_field(struct tracing_map *map);
 
250extern int tracing_map_add_key_field(struct tracing_map *map,
251				     unsigned int offset,
252				     tracing_map_cmp_fn_t cmp_fn);
253
254extern void tracing_map_destroy(struct tracing_map *map);
255extern void tracing_map_clear(struct tracing_map *map);
256
257extern struct tracing_map_elt *
258tracing_map_insert(struct tracing_map *map, void *key);
259extern struct tracing_map_elt *
260tracing_map_lookup(struct tracing_map *map, void *key);
261
262extern tracing_map_cmp_fn_t tracing_map_cmp_num(int field_size,
263						int field_is_signed);
264extern int tracing_map_cmp_string(void *val_a, void *val_b);
265extern int tracing_map_cmp_none(void *val_a, void *val_b);
266
267extern void tracing_map_update_sum(struct tracing_map_elt *elt,
268				   unsigned int i, u64 n);
 
 
 
269extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i);
270extern void tracing_map_set_field_descr(struct tracing_map *map,
271					unsigned int i,
272					unsigned int key_offset,
273					tracing_map_cmp_fn_t cmp_fn);
274extern int
275tracing_map_sort_entries(struct tracing_map *map,
276			 struct tracing_map_sort_key *sort_keys,
277			 unsigned int n_sort_keys,
278			 struct tracing_map_sort_entry ***sort_entries);
279
280extern void
281tracing_map_destroy_sort_entries(struct tracing_map_sort_entry **entries,
282				 unsigned int n_entries);
283#endif /* __TRACING_MAP_H */