Fix '_depth' and 'FIFOFAST_MAX_DEPTH_POINTABLE' sanity checks

Previously some invalid values (not a 2^n value) were accepted, in which cases it compiled without error, BUT creates major runtime bugs. To prevent this, all '_depth' inputs (including the config '#define FIFOFAST_MAX_DEPTH_POINTABLE') are rounded up to the next possible value.

The upper bound check implemended by '_FFF_GET_ARRAYDEPTH_P' was maually tested with a reasonable size of 255, 256 and 257 elements and it behaved as expected.
This commit is contained in:
nqtronix
2018-11-10 21:57:16 +01:00
parent e86e142d35
commit 482d16dec0
+26 -24
View File
@@ -50,7 +50,8 @@
// defines the maximum depth of pointable fifos. The performance of fifofast drops with increased
// maximum depth in discrete steps, especially on 8bit MCUs. 32bit MCUs (such as ARM cortex) are
// mostly unaffected, except they require slightly more RAM.
// mostly unaffected, except they require slightly more RAM. If the value is NOT a 2^n value, it
// will automatically be rounded up.
//
// depth | performance
// -----------------+-------------
@@ -86,13 +87,33 @@
#endif
//////////////////////////////////////////////////////////////////////////
// internal macros (_FFF_*)
//////////////////////////////////////////////////////////////////////////
// rounds up given argument to next 2^n value. Used to deal with invalid user input.
#define ROUND_UP_2N(_arg) ((uint64_t)1<<(_log2(_arg-1)+1))
// returns the structure name matching to given ID without the keyword 'struct'
#define _FFF_NAME_STRUCT(_id) CAT(fff_, _id, _s)
// returns matching type for internal index values; fifo contrains are automatically applied
#define _FFF_GET_TYPE(_depth) _type_min(_limit_lo(_depth,4)-1)
#define _FFF_SIZEOF_DATA(_id) sizeof(((struct _FFF_NAME_STRUCT(_id)*)0)->data[0])
#define _FFF_SIZEOF_ARRAY(_id) _sizeof_array(((struct _FFF_NAME_STRUCT(_id)*)0)->data)
// returns the length of the data array; fifo contrains are automatically applied
#define _FFF_GET_ARRAYDEPTH(_depth) _limit(ROUND_UP_2N(_depth), 4, ((uint32_t)1<<31))
#define _FFF_GET_ARRAYDEPTH_P(_depth) _limit(ROUND_UP_2N(_depth), 4, ROUND_UP_2N(FIFOFAST_MAX_DEPTH_POINTABLE))
//////////////////////////////////////////////////////////////////////////
// Data Structures (for inline functions only)
//////////////////////////////////////////////////////////////////////////
// extra #defines prevent VAssitX from marking the type red (because it doesn't understand 'typeof')
#define FIFOFAST_INDEX_T _type_min(FIFOFAST_MAX_DEPTH_POINTABLE-1)
#define FIFOFAST_LEVEL_T _type_min(FIFOFAST_MAX_DEPTH_POINTABLE)
#define FIFOFAST_INDEX_T _type_min(ROUND_UP_2N(FIFOFAST_MAX_DEPTH_POINTABLE)-1)
#define FIFOFAST_LEVEL_T _type_min(ROUND_UP_2N(FIFOFAST_MAX_DEPTH_POINTABLE))
typedef FIFOFAST_INDEX_T fff_index_t;
typedef FIFOFAST_LEVEL_T fff_level_t;
@@ -107,23 +128,6 @@ typedef struct
} fff_proto_t;
//////////////////////////////////////////////////////////////////////////
// internal macros (_FFF_*)
//////////////////////////////////////////////////////////////////////////
// returns the structure name matching to given ID without the keyword 'struct'
#define _FFF_NAME_STRUCT(_id) CAT(fff_, _id, _s)
// returns matching type for internal index values; fifo contrains are automatically applied
#define _FFF_GET_TYPE(_depth) _type_min(_limit_lo(_depth,4)-1)
#define _FFF_SIZEOF_DATA(_id) sizeof(((struct _FFF_NAME_STRUCT(_id)*)0)->data[0])
#define _FFF_SIZEOF_ARRAY(_id) _sizeof_array(((struct _FFF_NAME_STRUCT(_id)*)0)->data)
// returns the length of the data array; fifo contrains are automatically applied
#define _FFF_GET_ARRAYDEPTH8(_depth) _limit((1<<(1+_log2((uint8_t)_depth-1))), 4, UINT8_MAX+1)
#define _FFF_GET_ARRAYDEPTH16(_depth) _limit((1<<(1+_log2((uint16_t)_depth-1))), 4, (uint16_t)INT16_MAX+1)
//////////////////////////////////////////////////////////////////////////
// user macros (_fff_*)
//////////////////////////////////////////////////////////////////////////
@@ -161,7 +165,7 @@ struct _FFF_NAME_STRUCT(_id) { \
_FFF_GET_TYPE(_depth) read; \
_FFF_GET_TYPE(_depth) write; \
_FFF_GET_TYPE(_depth+1) level; \
_type data[_FFF_GET_ARRAYDEPTH16(_depth)]; \
_type data[_FFF_GET_ARRAYDEPTH(_depth)]; \
} _id
#define _fff_declare_p(_type, _id, _depth) \
@@ -171,15 +175,13 @@ struct _FFF_NAME_STRUCT(_id) { \
fff_index_t read; \
fff_index_t write; \
fff_level_t level; \
_type data[_FFF_GET_ARRAYDEPTH8(_depth)]; \
_type data[_FFF_GET_ARRAYDEPTH_P(_depth)]; \
} _id
// declares an array with '_size' fifos. '_size' can be any positive integer.
#define _fff_declare_a(_type, _id, _depth, _size) _fff_declare(_type, _id, _depth) [_size]
#define _fff_declare_pa(_type, _id, _depth, _size) _fff_declare_p(_type, , _depth) [_size]
// TODO: make '_FFF_GET_ARRAYDEPTH8(_depth)' dependent on fff_index_t
// initializes the fifo with the name '<_id>'
// This initialization function is technically identical to the term "definition" in c, but to