Add more validation of oplists before expanding data

This commit is contained in:
Patrick Pelissier committed 2020-05-10 11:16:46 +02:00
1 parent 7d17223332
commit 45d2a529b5
5 files changed
+99 -19

No files matched your search

+10 -1
View File
@@ -42,8 +42,9 @@
#define ISHARED_PTR_INTERFACE(name, type) \ #define ISHARED_PTR_INTERFACE(name, type) \
atomic_int M_C(name, _cpt) atomic_int M_C(name, _cpt)
/* Define the intrusive shared pointer type and its static inline functions. /* Define the intrusive shared pointer type and its static inline functions.
USAGE: ISHARED_PTR_DEF(name[, oplist]) */ USAGE: ISHARED_PTR_DEF(name, type, [, oplist]) */
#define ISHARED_PTR_DEF(name, ...) \ #define ISHARED_PTR_DEF(name, ...) \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
@@ -73,7 +74,15 @@
// Deferred evaluatioin // Deferred evaluatioin
#define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg #define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg
/* Validate the oplist before going further */
#define ISHAREDI_PTR_DEF_P2(name, type, oplist) \ #define ISHAREDI_PTR_DEF_P2(name, type, oplist) \
M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ISHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
#define ISHAREDI_PTR_DEF_P3(name, type, oplist) \
\ \
typedef type *M_C(name,_t); \ typedef type *M_C(name,_t); \
typedef type M_C(name, _type_t); \ typedef type M_C(name, _type_t); \
+14 -2
View File
@@ -52,7 +52,6 @@
/* Deferred evaluation for the definition, /* Deferred evaluation for the definition,
so that all arguments are evaluated before further expansion */ so that all arguments are evaluated before further expansion */
#define PRIOQUEUEI_OPLIST_P1(arg) PRIOQUEUEI_OPLIST_P2 arg #define PRIOQUEUEI_OPLIST_P1(arg) PRIOQUEUEI_OPLIST_P2 arg
#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg
/* Define oplist of a priority queue */ /* Define oplist of a priority queue */
#define PRIOQUEUEI_OPLIST_P2(name, oplist) \ #define PRIOQUEUEI_OPLIST_P2(name, oplist) \
@@ -74,6 +73,19 @@
,GET_SIZE(M_C(name, _size)) \ ,GET_SIZE(M_C(name, _size)) \
) )
/* Deferred evaluation for the definition,
so that all arguments are evaluated before further expansion */
#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg
/* Validate the oplist before going further */
#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \
M_IF_OPLIST(oplist)(PRIOQUEUEI_DEF_P3, PRIOQUEUEI_DEF_FAILURE)(name, type, oplist, prioqueue_t, it_t)
/* Stop processing with a compilation failure */
#define PRIOQUEUEI_DEF_FAILURE(name, type, oplist, prioqueue_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(PRIOQUEUE_DEF): the given argument is not a valid oplist: " #oplist)
/* Define the priority queue: /* Define the priority queue:
- name: prefix to use, - name: prefix to use,
- type: type of the contained objects, - type: type of the contained objects,
@@ -81,7 +93,7 @@
- prioqueue_t: type of the container, - prioqueue_t: type of the container,
- it_t: iterator of the container - it_t: iterator of the container
*/ */
#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \ #define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \
ARRAY_DEF(M_C(name, _array), type, oplist) \ ARRAY_DEF(M_C(name, _array), type, oplist) \
\ \
typedef type M_C(name, _type_t); \ typedef type M_C(name, _type_t); \
+12 -3
View File
@@ -36,6 +36,7 @@
(name, __VA_ARGS__ , \ (name, __VA_ARGS__ , \
M_C(name, _t), M_C(name, _node_t), M_C(name, _it_t)))) M_C(name, _t), M_C(name, _node_t), M_C(name, _it_t))))
/* Define the oplist of a rbtree of type. /* Define the oplist of a rbtree of type.
USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */ USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */
#define RBTREE_OPLIST(...) \ #define RBTREE_OPLIST(...) \
@@ -137,6 +138,14 @@ typedef enum {
so that all arguments are evaluated before further expansion */ so that all arguments are evaluated before further expansion */
#define RBTREEI_DEF_P1(arg) RBTREEI_DEF_P2 arg #define RBTREEI_DEF_P1(arg) RBTREEI_DEF_P2 arg
/* Validate the oplist before going further */
#define RBTREEI_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \
M_IF_OPLIST(oplist)(RBTREEI_DEF_P3, RBTREEI_DEF_FAILURE)(name, type, oplist, tree_t, node_t, it_t)
/* Stop processing with a compilation failure */
#define RBTREEI_DEF_FAILURE(name, type, oplist, tree_t, note_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(RBTREE_DEF): the given argument is not a valid oplist: " #oplist)
/* Internal rbtree definition /* Internal rbtree definition
- name: prefix to be used - name: prefix to be used
- type: type of the elements of the array - type: type of the elements of the array
@@ -145,7 +154,7 @@ typedef enum {
- it_t: alias for M_C(name, _it_t) [ iterator of the container ] - it_t: alias for M_C(name, _it_t) [ iterator of the container ]
- node_t: alias for M_C(name, _node_t) [ node ] - node_t: alias for M_C(name, _node_t) [ node ]
*/ */
#define RBTREEI_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \ #define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \
\ \
typedef struct M_C(name, _node_s) { \ typedef struct M_C(name, _node_s) { \
struct M_C(name, _node_s) *child[2]; \ struct M_C(name, _node_s) *child[2]; \
@@ -187,9 +196,9 @@ typedef enum {
M_CALL_DEL(oplist, ptr); \ M_CALL_DEL(oplist, ptr); \
} ) \ } ) \
\ \
RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t)
#define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \ #define RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t) \
\ \
static inline void \ static inline void \
M_C(name, _init)(tree_t tree) \ M_C(name, _init)(tree_t tree) \
+30 -7
View File
@@ -36,6 +36,7 @@
((__VA_ARGS__, M_DEFAULT_OPLIST ), \ ((__VA_ARGS__, M_DEFAULT_OPLIST ), \
_OPLIST(__VA_ARGS__ ))) _OPLIST(__VA_ARGS__ )))
/* Define shared pointer and its function. /* Define shared pointer and its function.
USAGE: SHARED_PTR_DEF(name, type, [, oplist]) */ USAGE: SHARED_PTR_DEF(name, type, [, oplist]) */
#define SHARED_PTR_DEF(name, ...) \ #define SHARED_PTR_DEF(name, ...) \
@@ -43,6 +44,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST ), \
(name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST))) (name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST)))
/* Define relaxed shared pointer and its function (thread unsafe). /* Define relaxed shared pointer and its function (thread unsafe).
USAGE: SHARED_PTR_RELAXED_DEF(name, type, [, oplist]) */ USAGE: SHARED_PTR_RELAXED_DEF(name, type, [, oplist]) */
#define SHARED_PTR_RELAXED_DEF(name, ...) \ #define SHARED_PTR_RELAXED_DEF(name, ...) \
@@ -50,6 +52,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST ), \
(name, __VA_ARGS__ , SHAREDI_INTEGER_OPLIST))) (name, __VA_ARGS__ , SHAREDI_INTEGER_OPLIST)))
/* Define shared resource and its function. /* Define shared resource and its function.
This is a bounded pool of resource shared by multiple owners. This is a bounded pool of resource shared by multiple owners.
USAGE: SHARED_RESOURCE_DEF(name, type, [, oplist]) */ USAGE: SHARED_RESOURCE_DEF(name, type, [, oplist]) */
@@ -62,7 +65,7 @@
/********************************** INTERNAL ************************************/ /********************************** INTERNAL ************************************/
// deferred // deferred evaluation
#define SHAREDI_PTR_OPLIST_P1(arg) SHAREDI_PTR_OPLIST_P2 arg #define SHAREDI_PTR_OPLIST_P1(arg) SHAREDI_PTR_OPLIST_P2 arg
#define SHAREDI_PTR_OPLIST_P2(name, oplist) ( \ #define SHAREDI_PTR_OPLIST_P2(name, oplist) ( \
@@ -79,9 +82,6 @@
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \ ,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
) )
// deferred
#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg
// OPLIST to handle a counter of atomic type // OPLIST to handle a counter of atomic type
#define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \ #define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \
INIT_SET(atomic_init), \ INIT_SET(atomic_init), \
@@ -89,23 +89,38 @@
SUB(atomic_fetch_sub), \ SUB(atomic_fetch_sub), \
IT_CREF(atomic_load)) IT_CREF(atomic_load))
// OPLIST to handle a counter of non-atomic type with its helper functions. // OPLIST to handle a counter of non-atomic type
#define SHAREDI_INTEGER_OPLIST (TYPE(int), \ #define SHAREDI_INTEGER_OPLIST (TYPE(int), \
INIT_SET(sharedi_integer_init_set), \ INIT_SET(sharedi_integer_init_set), \
ADD(sharedi_integer_add), \ ADD(sharedi_integer_add), \
SUB(sharedi_integer_sub), \ SUB(sharedi_integer_sub), \
IT_CREF(sharedi_integer_cref)) IT_CREF(sharedi_integer_cref))
/* Atomic like interface for basic integers */
static inline void sharedi_integer_init_set(int *p, int val) { *p = val; } static inline void sharedi_integer_init_set(int *p, int val) { *p = val; }
static inline int sharedi_integer_add(int *p, int val) { int r = *p; *p += val; return r; } static inline int sharedi_integer_add(int *p, int val) { int r = *p; *p += val; return r; }
static inline int sharedi_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; } static inline int sharedi_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; }
static inline int sharedi_integer_cref(int *p) { return *p; } static inline int sharedi_integer_cref(int *p) { return *p; }
/* Contract of a shared pointer */
#define SHAREDI_CONTRACT(shared, cpt_oplist) do { \ #define SHAREDI_CONTRACT(shared, cpt_oplist) do { \
assert(shared != NULL); \ assert(shared != NULL); \
assert(*shared == NULL || M_CALL_IT_CREF(cpt_oplist, &(*shared)->cpt) >= 1); \ assert(*shared == NULL || M_CALL_IT_CREF(cpt_oplist, &(*shared)->cpt) >= 1); \
} while (0) } while (0)
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist) \ // deferred evaluation
#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg
/* Validate the oplist before going further */
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist_t) \
M_IF_OPLIST(oplist)(SHAREDI_PTR_DEF_P3, SHAREDI_PTR_DEF_FAILURE)(name, type, oplist, cpt_oplist_t)
/* Stop processing with a compilation failure */
#define SHAREDI_PTR_DEF_FAILURE(name, type, oplist, cpt_oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
/* Code generation */
#define SHAREDI_PTR_DEF_P3(name, type, oplist, cpt_oplist) \
\ \
typedef struct M_C(name, _s){ \ typedef struct M_C(name, _s){ \
type *data; /* Pointer to the data */ \ type *data; /* Pointer to the data */ \
@@ -299,7 +314,15 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
// deferred // deferred
#define SHAREDI_RESOURCE_DEF_P1(arg) SHAREDI_RESOURCE_DEF_P2 arg #define SHAREDI_RESOURCE_DEF_P1(arg) SHAREDI_RESOURCE_DEF_P2 arg
#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist) \ /* Validate the oplist before going further */
#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist) \
M_IF_OPLIST(oplist)(SHAREDI_RESOURCE_DEF_P3, SHAREDI_RESOURCE_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */
#define SHAREDI_RESOURCE_DEF_FAILURE(name, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SHARED_RESOURCE_DEF): the given argument is not a valid oplist: " #oplist)
#define SHAREDI_RESOURCE_DEF_P3(name, type, oplist) \
\ \
/* Create an aligned type to avoid false sharing between threads */ \ /* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _atype_s) { \ typedef struct M_C(name, _atype_s) { \
+33 -6
View File
@@ -36,6 +36,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(name, __VA_ARGS__ ))) (name, __VA_ARGS__ )))
/* Define a Single Producer Multiple Consummer snapshot and its functions /* Define a Single Producer Multiple Consummer snapshot and its functions
USAGE: SNAPSHOT_SPMC_DEF(name, type[, oplist]) */ USAGE: SNAPSHOT_SPMC_DEF(name, type[, oplist]) */
#define SNAPSHOT_SPMC_DEF(name, ...) \ #define SNAPSHOT_SPMC_DEF(name, ...) \
@@ -43,6 +44,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(name, __VA_ARGS__ ))) (name, __VA_ARGS__ )))
/* Define a Multiple Producer Multiple Consummer snapshot and its functions /* Define a Multiple Producer Multiple Consummer snapshot and its functions
USAGE: SNAPSHOT_MPMC_DEF(name, type[, oplist]) */ USAGE: SNAPSHOT_MPMC_DEF(name, type[, oplist]) */
#define SNAPSHOT_MPMC_DEF(name, ...) \ #define SNAPSHOT_MPMC_DEF(name, ...) \
@@ -50,6 +52,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(name, __VA_ARGS__ ))) (name, __VA_ARGS__ )))
/* Define the oplist of a snapshot (SPSC, SPMC or MPMC). /* Define the oplist of a snapshot (SPSC, SPMC or MPMC).
USAGE: SNAPSHOT_OPLIST(name[, oplist]) */ USAGE: SNAPSHOT_OPLIST(name[, oplist]) */
#define SNAPSHOT_OPLIST(...) \ #define SNAPSHOT_OPLIST(...) \
@@ -109,14 +112,22 @@
SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \ SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \
} while (0) } while (0)
// Defered evaluation of the arguments.
#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg
// A snapshot is basically an atomic triple buffer (Lock Free) // A snapshot is basically an atomic triple buffer (Lock Free)
// between a single producer thread and a single consummer thread. // between a single producer thread and a single consummer thread.
#define SNAPSHOTI_SPSC_MAX_BUFFER 3 #define SNAPSHOTI_SPSC_MAX_BUFFER 3
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist) \ // Defered evaluation of the arguments.
#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg
/* Validate the oplist before going further */
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist) \
M_IF_OPLIST(oplist)(SNAPSHOTI_SPSC_DEF_P3, SNAPSHOTI_SPSC_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPSC_DEF): the given argument is not a valid oplist: " #oplist)
#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist) \
\ \
/* Create an aligned type to avoid false sharing between threads */ \ /* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \ typedef struct M_C(name, _aligned_type_s) { \
@@ -490,7 +501,15 @@ static inline void snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned in
// Defered evaluation // Defered evaluation
#define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg #define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist) \ /* Validate the oplist before going further */
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist) \
M_IF_OPLIST(oplist)(SNAPSHOTI_SPMC_DEF_P3, SNAPSHOTI_SPMC_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPMC_DEF): the given argument is not a valid oplist: " #oplist)
#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist) \
\ \
/* Create an aligned type to avoid false sharing between threads */ \ /* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \ typedef struct M_C(name, _aligned_type_s) { \
@@ -579,7 +598,15 @@ static inline void snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned in
// Defered evaluation // Defered evaluation
#define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg #define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist) \ /* Validate the oplist before going further */
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist) \
M_IF_OPLIST(oplist)(SNAPSHOTI_MPMC_DEF_P3, SNAPSHOTI_MPMC_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_MPMC_DEF): the given argument is not a valid oplist: " #oplist)
#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist) \
\ \
SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist)) \ SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist)) \
\ \