mirror of
https://github.com/nqtronix/fifofast.git
synced 2026-08-18 17:17:34 +08:00
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:
+26
-24
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user