linux/include/linux/flex_array.h
<<
>>
Prefs
   1#ifndef _FLEX_ARRAY_H
   2#define _FLEX_ARRAY_H
   3
   4#include <linux/types.h>
   5#include <asm/page.h>
   6
   7#define FLEX_ARRAY_PART_SIZE PAGE_SIZE
   8#define FLEX_ARRAY_BASE_SIZE PAGE_SIZE
   9
  10struct flex_array_part;
  11
  12/*
  13 * This is meant to replace cases where an array-like
  14 * structure has gotten too big to fit into kmalloc()
  15 * and the developer is getting tempted to use
  16 * vmalloc().
  17 */
  18
  19struct flex_array {
  20        union {
  21                struct {
  22                        int element_size;
  23                        int total_nr_elements;
  24                        int elems_per_part;
  25                        u32 reciprocal_elems;
  26                        struct flex_array_part *parts[];
  27                };
  28                /*
  29                 * This little trick makes sure that
  30                 * sizeof(flex_array) == PAGE_SIZE
  31                 */
  32                char padding[FLEX_ARRAY_BASE_SIZE];
  33        };
  34};
  35
  36/* Number of bytes left in base struct flex_array, excluding metadata */
  37#define FLEX_ARRAY_BASE_BYTES_LEFT                                      \
  38        (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts))
  39
  40/* Number of pointers in base to struct flex_array_part pages */
  41#define FLEX_ARRAY_NR_BASE_PTRS                                         \
  42        (FLEX_ARRAY_BASE_BYTES_LEFT / sizeof(struct flex_array_part *))
  43
  44/* Number of elements of size that fit in struct flex_array_part */
  45#define FLEX_ARRAY_ELEMENTS_PER_PART(size)                              \
  46        (FLEX_ARRAY_PART_SIZE / size)
  47
  48/*
  49 * Defines a statically allocated flex array and ensures its parameters are
  50 * valid.
  51 */
  52#define DEFINE_FLEX_ARRAY(__arrayname, __element_size, __total)         \
  53        struct flex_array __arrayname = { { {                           \
  54                .element_size = (__element_size),                       \
  55                .total_nr_elements = (__total),                         \
  56        } } };                                                          \
  57        static inline void __arrayname##_invalid_parameter(void)        \
  58        {                                                               \
  59                BUILD_BUG_ON((__total) > FLEX_ARRAY_NR_BASE_PTRS *      \
  60                        FLEX_ARRAY_ELEMENTS_PER_PART(__element_size));  \
  61        }
  62
  63struct flex_array *flex_array_alloc(int element_size, unsigned int total,
  64                gfp_t flags);
  65int flex_array_prealloc(struct flex_array *fa, unsigned int start,
  66                unsigned int nr_elements, gfp_t flags);
  67void flex_array_free(struct flex_array *fa);
  68void flex_array_free_parts(struct flex_array *fa);
  69int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
  70                gfp_t flags);
  71int flex_array_clear(struct flex_array *fa, unsigned int element_nr);
  72void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
  73int flex_array_shrink(struct flex_array *fa);
  74
  75#define flex_array_put_ptr(fa, nr, src, gfp) \
  76        flex_array_put(fa, nr, (void *)&(src), gfp)
  77
  78void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr);
  79
  80#endif /* _FLEX_ARRAY_H */
  81