Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #ifndef __TRACING_MAP_H
0003 #define __TRACING_MAP_H
0004 
0005 #define TRACING_MAP_BITS_DEFAULT    11
0006 #define TRACING_MAP_BITS_MAX        17
0007 #define TRACING_MAP_BITS_MIN        7
0008 
0009 #define TRACING_MAP_KEYS_MAX        3
0010 #define TRACING_MAP_VALS_MAX        3
0011 #define TRACING_MAP_FIELDS_MAX      (TRACING_MAP_KEYS_MAX + \
0012                      TRACING_MAP_VALS_MAX)
0013 #define TRACING_MAP_VARS_MAX        16
0014 #define TRACING_MAP_SORT_KEYS_MAX   2
0015 
0016 typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b);
0017 
0018 /*
0019  * This is an overview of the tracing_map data structures and how they
0020  * relate to the tracing_map API.  The details of the algorithms
0021  * aren't discussed here - this is just a general overview of the data
0022  * structures and how they interact with the API.
0023  *
0024  * The central data structure of the tracing_map is an initially
0025  * zeroed array of struct tracing_map_entry (stored in the map field
0026  * of struct tracing_map).  tracing_map_entry is a very simple data
0027  * structure containing only two fields: a 32-bit unsigned 'key'
0028  * variable and a pointer named 'val'.  This array of struct
0029  * tracing_map_entry is essentially a hash table which will be
0030  * modified by a single function, tracing_map_insert(), but which can
0031  * be traversed and read by a user at any time (though the user does
0032  * this indirectly via an array of tracing_map_sort_entry - see the
0033  * explanation of that data structure in the discussion of the
0034  * sorting-related data structures below).
0035  *
0036  * The central function of the tracing_map API is
0037  * tracing_map_insert().  tracing_map_insert() hashes the
0038  * arbitrarily-sized key passed into it into a 32-bit unsigned key.
0039  * It then uses this key, truncated to the array size, as an index
0040  * into the array of tracing_map_entries.  If the value of the 'key'
0041  * field of the tracing_map_entry found at that location is 0, then
0042  * that entry is considered to be free and can be claimed, by
0043  * replacing the 0 in the 'key' field of the tracing_map_entry with
0044  * the new 32-bit hashed key.  Once claimed, that tracing_map_entry's
0045  * 'val' field is then used to store a unique element which will be
0046  * forever associated with that 32-bit hashed key in the
0047  * tracing_map_entry.
0048  *
0049  * That unique element now in the tracing_map_entry's 'val' field is
0050  * an instance of tracing_map_elt, where 'elt' in the latter part of
0051  * that variable name is short for 'element'.  The purpose of a
0052  * tracing_map_elt is to hold values specific to the particular
0053  * 32-bit hashed key it's associated with.  Things such as the unique
0054  * set of aggregated sums associated with the 32-bit hashed key, along
0055  * with a copy of the full key associated with the entry, and which
0056  * was used to produce the 32-bit hashed key.
0057  *
0058  * When tracing_map_create() is called to create the tracing map, the
0059  * user specifies (indirectly via the map_bits param, the details are
0060  * unimportant for this discussion) the maximum number of elements
0061  * that the map can hold (stored in the max_elts field of struct
0062  * tracing_map).  This is the maximum possible number of
0063  * tracing_map_entries in the tracing_map_entry array which can be
0064  * 'claimed' as described in the above discussion, and therefore is
0065  * also the maximum number of tracing_map_elts that can be associated
0066  * with the tracing_map_entry array in the tracing_map.  Because of
0067  * the way the insertion algorithm works, the size of the allocated
0068  * tracing_map_entry array is always twice the maximum number of
0069  * elements (2 * max_elts).  This value is stored in the map_size
0070  * field of struct tracing_map.
0071  *
0072  * Because tracing_map_insert() needs to work from any context,
0073  * including from within the memory allocation functions themselves,
0074  * both the tracing_map_entry array and a pool of max_elts
0075  * tracing_map_elts are pre-allocated before any call is made to
0076  * tracing_map_insert().
0077  *
0078  * The tracing_map_entry array is allocated as a single block by
0079  * tracing_map_create().
0080  *
0081  * Because the tracing_map_elts are much larger objects and can't
0082  * generally be allocated together as a single large array without
0083  * failure, they're allocated individually, by tracing_map_init().
0084  *
0085  * The pool of tracing_map_elts are allocated by tracing_map_init()
0086  * rather than by tracing_map_create() because at the time
0087  * tracing_map_create() is called, there isn't enough information to
0088  * create the tracing_map_elts.  Specifically,the user first needs to
0089  * tell the tracing_map implementation how many fields the
0090  * tracing_map_elts contain, and which types of fields they are (key
0091  * or sum).  The user does this via the tracing_map_add_sum_field()
0092  * and tracing_map_add_key_field() functions, following which the user
0093  * calls tracing_map_init() to finish up the tracing map setup.  The
0094  * array holding the pointers which make up the pre-allocated pool of
0095  * tracing_map_elts is allocated as a single block and is stored in
0096  * the elts field of struct tracing_map.
0097  *
0098  * There is also a set of structures used for sorting that might
0099  * benefit from some minimal explanation.
0100  *
0101  * struct tracing_map_sort_key is used to drive the sort at any given
0102  * time.  By 'any given time' we mean that a different
0103  * tracing_map_sort_key will be used at different times depending on
0104  * whether the sort currently being performed is a primary or a
0105  * secondary sort.
0106  *
0107  * The sort key is very simple, consisting of the field index of the
0108  * tracing_map_elt field to sort on (which the user saved when adding
0109  * the field), and whether the sort should be done in an ascending or
0110  * descending order.
0111  *
0112  * For the convenience of the sorting code, a tracing_map_sort_entry
0113  * is created for each tracing_map_elt, again individually allocated
0114  * to avoid failures that might be expected if allocated as a single
0115  * large array of struct tracing_map_sort_entry.
0116  * tracing_map_sort_entry instances are the objects expected by the
0117  * various internal sorting functions, and are also what the user
0118  * ultimately receives after calling tracing_map_sort_entries().
0119  * Because it doesn't make sense for users to access an unordered and
0120  * sparsely populated tracing_map directly, the
0121  * tracing_map_sort_entries() function is provided so that users can
0122  * retrieve a sorted list of all existing elements.  In addition to
0123  * the associated tracing_map_elt 'elt' field contained within the
0124  * tracing_map_sort_entry, which is the object of interest to the
0125  * user, tracing_map_sort_entry objects contain a number of additional
0126  * fields which are used for caching and internal purposes and can
0127  * safely be ignored.
0128 */
0129 
0130 struct tracing_map_field {
0131     tracing_map_cmp_fn_t        cmp_fn;
0132     union {
0133         atomic64_t          sum;
0134         unsigned int            offset;
0135     };
0136 };
0137 
0138 struct tracing_map_elt {
0139     struct tracing_map      *map;
0140     struct tracing_map_field    *fields;
0141     atomic64_t          *vars;
0142     bool                *var_set;
0143     void                *key;
0144     void                *private_data;
0145 };
0146 
0147 struct tracing_map_entry {
0148     u32             key;
0149     struct tracing_map_elt      *val;
0150 };
0151 
0152 struct tracing_map_sort_key {
0153     unsigned int            field_idx;
0154     bool                descending;
0155 };
0156 
0157 struct tracing_map_sort_entry {
0158     void                *key;
0159     struct tracing_map_elt      *elt;
0160     bool                elt_copied;
0161     bool                dup;
0162 };
0163 
0164 struct tracing_map_array {
0165     unsigned int entries_per_page;
0166     unsigned int entry_size_shift;
0167     unsigned int entry_shift;
0168     unsigned int entry_mask;
0169     unsigned int n_pages;
0170     void **pages;
0171 };
0172 
0173 #define TRACING_MAP_ARRAY_ELT(array, idx)               \
0174     (array->pages[idx >> array->entry_shift] +          \
0175      ((idx & array->entry_mask) << array->entry_size_shift))
0176 
0177 #define TRACING_MAP_ENTRY(array, idx)                   \
0178     ((struct tracing_map_entry *)TRACING_MAP_ARRAY_ELT(array, idx))
0179 
0180 #define TRACING_MAP_ELT(array, idx)                 \
0181     ((struct tracing_map_elt **)TRACING_MAP_ARRAY_ELT(array, idx))
0182 
0183 struct tracing_map {
0184     unsigned int            key_size;
0185     unsigned int            map_bits;
0186     unsigned int            map_size;
0187     unsigned int            max_elts;
0188     atomic_t            next_elt;
0189     struct tracing_map_array    *elts;
0190     struct tracing_map_array    *map;
0191     const struct tracing_map_ops    *ops;
0192     void                *private_data;
0193     struct tracing_map_field    fields[TRACING_MAP_FIELDS_MAX];
0194     unsigned int            n_fields;
0195     int             key_idx[TRACING_MAP_KEYS_MAX];
0196     unsigned int            n_keys;
0197     struct tracing_map_sort_key sort_key;
0198     unsigned int            n_vars;
0199     atomic64_t          hits;
0200     atomic64_t          drops;
0201 };
0202 
0203 /**
0204  * struct tracing_map_ops - callbacks for tracing_map
0205  *
0206  * The methods in this structure define callback functions for various
0207  * operations on a tracing_map or objects related to a tracing_map.
0208  *
0209  * For a detailed description of tracing_map_elt objects please see
0210  * the overview of tracing_map data structures at the beginning of
0211  * this file.
0212  *
0213  * All the methods below are optional.
0214  *
0215  * @elt_alloc: When a tracing_map_elt is allocated, this function, if
0216  *  defined, will be called and gives clients the opportunity to
0217  *  allocate additional data and attach it to the element
0218  *  (tracing_map_elt->private_data is meant for that purpose).
0219  *  Element allocation occurs before tracing begins, when the
0220  *  tracing_map_init() call is made by client code.
0221  *
0222  * @elt_free: When a tracing_map_elt is freed, this function is called
0223  *  and allows client-allocated per-element data to be freed.
0224  *
0225  * @elt_clear: This callback allows per-element client-defined data to
0226  *  be cleared, if applicable.
0227  *
0228  * @elt_init: This callback allows per-element client-defined data to
0229  *  be initialized when used i.e. when the element is actually
0230  *  claimed by tracing_map_insert() in the context of the map
0231  *  insertion.
0232  */
0233 struct tracing_map_ops {
0234     int         (*elt_alloc)(struct tracing_map_elt *elt);
0235     void            (*elt_free)(struct tracing_map_elt *elt);
0236     void            (*elt_clear)(struct tracing_map_elt *elt);
0237     void            (*elt_init)(struct tracing_map_elt *elt);
0238 };
0239 
0240 extern struct tracing_map *
0241 tracing_map_create(unsigned int map_bits,
0242            unsigned int key_size,
0243            const struct tracing_map_ops *ops,
0244            void *private_data);
0245 extern int tracing_map_init(struct tracing_map *map);
0246 
0247 extern int tracing_map_add_sum_field(struct tracing_map *map);
0248 extern int tracing_map_add_var(struct tracing_map *map);
0249 extern int tracing_map_add_key_field(struct tracing_map *map,
0250                      unsigned int offset,
0251                      tracing_map_cmp_fn_t cmp_fn);
0252 
0253 extern void tracing_map_destroy(struct tracing_map *map);
0254 extern void tracing_map_clear(struct tracing_map *map);
0255 
0256 extern struct tracing_map_elt *
0257 tracing_map_insert(struct tracing_map *map, void *key);
0258 extern struct tracing_map_elt *
0259 tracing_map_lookup(struct tracing_map *map, void *key);
0260 
0261 extern tracing_map_cmp_fn_t tracing_map_cmp_num(int field_size,
0262                         int field_is_signed);
0263 extern int tracing_map_cmp_string(void *val_a, void *val_b);
0264 extern int tracing_map_cmp_none(void *val_a, void *val_b);
0265 
0266 extern void tracing_map_update_sum(struct tracing_map_elt *elt,
0267                    unsigned int i, u64 n);
0268 extern void tracing_map_set_var(struct tracing_map_elt *elt,
0269                 unsigned int i, u64 n);
0270 extern bool tracing_map_var_set(struct tracing_map_elt *elt, unsigned int i);
0271 extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i);
0272 extern u64 tracing_map_read_var(struct tracing_map_elt *elt, unsigned int i);
0273 extern u64 tracing_map_read_var_once(struct tracing_map_elt *elt, unsigned int i);
0274 
0275 extern void tracing_map_set_field_descr(struct tracing_map *map,
0276                     unsigned int i,
0277                     unsigned int key_offset,
0278                     tracing_map_cmp_fn_t cmp_fn);
0279 extern int
0280 tracing_map_sort_entries(struct tracing_map *map,
0281              struct tracing_map_sort_key *sort_keys,
0282              unsigned int n_sort_keys,
0283              struct tracing_map_sort_entry ***sort_entries);
0284 
0285 extern void
0286 tracing_map_destroy_sort_entries(struct tracing_map_sort_entry **entries,
0287                  unsigned int n_entries);
0288 #endif /* __TRACING_MAP_H */