| 1 |
|
| 2 |
|
| 3 |
|
| 4 | #ifndef __LIBETH_CACHE_H
|
| 5 | #define __LIBETH_CACHE_H
|
| 6 |
|
| 7 | #include <linux/cache.h>
|
| 8 |
|
| 9 | |
| 10 | * libeth_cacheline_group_assert - make sure cacheline group size is expected
|
| 11 | * @type: type of the structure containing the group
|
| 12 | * @grp: group name inside the struct
|
| 13 | * @sz: expected group size
|
| 14 |
|
| 15 | #if defined(CONFIG_64BIT) && SMP_CACHE_BYTES == 64
|
| 16 | #define libeth_cacheline_group_assert(type, grp, sz) \
|
| 17 | static_assert(offsetof(type, __cacheline_group_end__##grp) - \
|
| 18 | offsetofend(type, __cacheline_group_begin__##grp) == \
|
| 19 | (sz))
|
| 20 | #define __libeth_cacheline_struct_assert(type, sz) \
|
| 21 | static_assert(sizeof(type) == (sz))
|
| 22 | #else
|
| 23 | #define libeth_cacheline_group_assert(type, grp, sz) \
|
| 24 | static_assert(offsetof(type, __cacheline_group_end__##grp) - \
|
| 25 | offsetofend(type, __cacheline_group_begin__##grp) <= \
|
| 26 | (sz))
|
| 27 | #define __libeth_cacheline_struct_assert(type, sz) \
|
| 28 | static_assert(sizeof(type) <= (sz))
|
| 29 | #endif
|
| 30 |
|
| 31 | #define __libeth_cls1(sz1) SMP_CACHE_ALIGN(sz1)
|
| 32 | #define __libeth_cls2(sz1, sz2) (SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2))
|
| 33 | #define __libeth_cls3(sz1, sz2, sz3) \
|
| 34 | (SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2) + SMP_CACHE_ALIGN(sz3))
|
| 35 | #define __libeth_cls(...) \
|
| 36 | CONCATENATE(__libeth_cls, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
| 37 |
|
| 38 | |
| 39 | * libeth_cacheline_struct_assert - make sure CL-based struct size is expected
|
| 40 | * @type: type of the struct
|
| 41 | * @...: from 1 to 3 CL group sizes (read-mostly, read-write, cold)
|
| 42 | *
|
| 43 | * When a struct contains several CL groups, it's difficult to predict its size
|
| 44 | * on different architectures. The macro instead takes sizes of all of the
|
| 45 | * groups the structure contains and generates the final struct size.
|
| 46 |
|
| 47 | #define libeth_cacheline_struct_assert(type, ...) \
|
| 48 | __libeth_cacheline_struct_assert(type, __libeth_cls(__VA_ARGS__)); \
|
| 49 | static_assert(__alignof(type) >= SMP_CACHE_BYTES)
|
| 50 |
|
| 51 | |
| 52 | * libeth_cacheline_set_assert - make sure CL-based struct layout is expected
|
| 53 | * @type: type of the struct
|
| 54 | * @ro: expected size of the read-mostly group
|
| 55 | * @rw: expected size of the read-write group
|
| 56 | * @c: expected size of the cold group
|
| 57 | *
|
| 58 | * Check that each group size is expected and then do final struct size check.
|
| 59 |
|
| 60 | #define libeth_cacheline_set_assert(type, ro, rw, c) \
|
| 61 | libeth_cacheline_group_assert(type, read_mostly, ro); \
|
| 62 | libeth_cacheline_group_assert(type, read_write, rw); \
|
| 63 | libeth_cacheline_group_assert(type, cold, c); \
|
| 64 | libeth_cacheline_struct_assert(type, ro, rw, c)
|
| 65 |
|
| 66 | #endif
|