From 4ac318667b371036771aaaf11372cd702ebf088d Mon Sep 17 00:00:00 2001 From: MacRsh <1063220965@qq.com> Date: Wed, 24 Jul 2024 00:21:42 +0800 Subject: [PATCH] feat(class): Supports determining whether it is a subclass This change adds a new method to the class that allows checking whether a given class is a subclass of the base class. The new rule states that the private data size of the subclass must be larger than that of the base class. --- include/mr_def.h | 7 +- include/mr_library.h | 30 +- include/mr_list.h | 2 +- include/mr_ref.h | 2 +- include/mr_service.h | 171 +++++----- include/mr_spinlock.h | 6 +- source/class.c | 661 ++++++++++++++++++++------------------ source/fifo.c | 134 ++++---- source/memory.c | 8 +- source/service.c | 8 +- tool.py => tools/build.py | 0 11 files changed, 518 insertions(+), 511 deletions(-) rename tool.py => tools/build.py (100%) diff --git a/include/mr_def.h b/include/mr_def.h index c5353d3..e26cd01 100644 --- a/include/mr_def.h +++ b/include/mr_def.h @@ -75,6 +75,7 @@ extern "C" { #define MR_EINVAL (-22) /**< Invalid argument */ #define MR_ENOSYS (-38) /**< Not supported */ #define MR_ETIMEOUT (-110) /**< Operation timed */ + /** @} */ /** @@ -209,9 +210,9 @@ typedef struct mr_class struct mr_class *parent; /**< Parent */ mr_list_t list, clist; /**< List */ mr_spinlock_t lock; /**< List lock */ - void *priv_data; /**< Private data */ - size_t priv_size; /**< Private data size */ - mr_ref_t ref_count; /**< Reference count */ + void *privdata; /**< Private data */ + size_t privsize; /**< Private data size */ + mr_ref_t refcount; /**< Reference count */ void (*release)(struct mr_class *); /**< Release function */ void *methods; /**< Methods */ } mr_class_t; diff --git a/include/mr_library.h b/include/mr_library.h index 2d79e6f..6be58b1 100644 --- a/include/mr_library.h +++ b/include/mr_library.h @@ -50,15 +50,6 @@ int mr_log_printf(const char *tag, const char *fmt, ...); /** @} */ -/** - * @addtogroup Assert - * @{ - */ - -void mr_assert_handler(const char *ex, const char *tag, const char *fn, const char *file, int line); - -/** @} */ - /** * @addtogroup Memory * @{ @@ -78,17 +69,17 @@ void *mr_realloc(void *memory, size_t size); */ int mr_fifo_init(mr_fifo_t *fifo, void *buf, size_t size); -void mr_fifo_reset(mr_fifo_t *fifo); int mr_fifo_allocate(mr_fifo_t *fifo, size_t size); void mr_fifo_free(mr_fifo_t *fifo); -size_t mr_fifo_used_get(const mr_fifo_t *fifo); -size_t mr_fifo_free_get(const mr_fifo_t *fifo); -size_t mr_fifo_size_get(const mr_fifo_t *fifo); +void mr_fifo_reset(mr_fifo_t *fifo); size_t mr_fifo_peek(const mr_fifo_t *fifo, void *buf, size_t count); size_t mr_fifo_discard(mr_fifo_t *fifo, size_t count); size_t mr_fifo_read(mr_fifo_t *fifo, void *buf, size_t count); size_t mr_fifo_write(mr_fifo_t *fifo, const void *buf, size_t count); size_t mr_fifo_write_force(mr_fifo_t *fifo, const void *buf, size_t count); +size_t mr_fifo_get_used(const mr_fifo_t *fifo); +size_t mr_fifo_get_free(const mr_fifo_t *fifo); +size_t mr_fifo_get_size(const mr_fifo_t *fifo); /** @} */ @@ -97,19 +88,20 @@ size_t mr_fifo_write_force(mr_fifo_t *fifo, const void *buf, size_t count); * @{ */ -mr_class_t *mr_class_find(mr_class_t *parent, const char *path); -void mr_class_init(mr_class_t *class, const char *name, size_t priv_size, +void mr_class_init(mr_class_t *class, const char *name, size_t privsize, void (*release)(mr_class_t *), void *methods); -mr_class_t *mr_class_create(const char *name, uint32_t priv_size, void *methods); +mr_class_t *mr_class_create(const char *name, uint32_t privsize, void *methods); int mr_class_add(mr_class_t *class, mr_class_t *parent); void mr_class_delete(mr_class_t *class); +int mr_class_rename(mr_class_t *class, const char *name); int mr_class_register(mr_class_t *class, mr_class_t *parent, const char *dir); void mr_class_unregister(mr_class_t *class); mr_class_t *mr_class_get(mr_class_t *class); void mr_class_put(mr_class_t *class); -int mr_class_rename(mr_class_t *class, const char *name); -void *mr_class_priv_data_get(mr_class_t *class); -void *mr_class_methods_get(mr_class_t *class); +mr_class_t *mr_class_find(mr_class_t *parent, const char *path); +bool mr_class_is_subclass(mr_class_t *class, mr_class_t *base); +void *mr_class_get_privdata(mr_class_t *class); +void *mr_class_get_methods(mr_class_t *class); char *mr_extract_name(const char *path); char *mr_extract_dir(const char *path); diff --git a/include/mr_list.h b/include/mr_list.h index 701cbf3..9fbe2a9 100644 --- a/include/mr_list.h +++ b/include/mr_list.h @@ -202,7 +202,7 @@ MR_INLINE void mr_list_concat(mr_list_t *list1, mr_list_t *list2) * * @return The length of the list. */ -MR_INLINE size_t mr_list_length_get(mr_list_t *list) +MR_INLINE size_t mr_list_get_length(mr_list_t *list) { mr_list_t *node; size_t len; diff --git a/include/mr_ref.h b/include/mr_ref.h index ef205a7..dcf64ff 100644 --- a/include/mr_ref.h +++ b/include/mr_ref.h @@ -84,7 +84,7 @@ MR_INLINE bool mr_ref_put(mr_ref_t *ref, void (*release)(mr_ref_t *)) * * @return The reference count. */ -MR_INLINE mr_atomic_t mr_ref_count_get(mr_ref_t *ref) +MR_INLINE mr_atomic_t mr_ref_get_count(mr_ref_t *ref) { /* Get reference count */ return ref->count; diff --git a/include/mr_service.h b/include/mr_service.h index cb90e77..185ca19 100644 --- a/include/mr_service.h +++ b/include/mr_service.h @@ -73,6 +73,30 @@ extern "C" { */ #define MR_BIT_CLR(_value, _mask) ((_value) &= ~(_mask)) +/** + * @brief This macro function gets the maximum of two values. + * + * @param _type The type of the value. + * @param _a The first value. + * @param _b The second value. + * + * @return The maximum of the two values. + */ +#define MR_MAX(_type, _a, _b) \ + ((_type){(_a)} > (_type){(_b)} ? (_type){(_a)} : (_type){(_b)}) + +/** + * @brief This macro function gets the minimum of two values. + * + * @param _type The type of the value. + * @param _a The first value. + * @param _b The second value. + * + * @return The minimum of the two values. + */ +#define MR_MIN(_type, _a, _b) \ + ((_type){(_a)} < (_type){(_b)} ? (_type){(_a)} : (_type){(_b)}) + /** * @brief This macro function ensures that a value is within a specified range. * @@ -82,13 +106,23 @@ extern "C" { * * @return The value within the specified range. */ -#define MR_CLAMP(_value, _min, _max) \ - ({ \ - typeof(_value) __value = (_value); \ - typeof(_min) __min = (_min); \ - typeof(_max) __max = (_max); \ - __value < __min ? __min : (__value > __max ? __max : __value); \ - }) +#define MR_CLAMP(_type, _value, _min, _max) \ + (MR_MAX(_type, MR_MIN(_type, _value, _max), _min)) + +/** + * @brief This macro function swaps two values. + * + * @param _type The type of the value. + * @param _a The first value. + * @param _b The second value. + */ +#define MR_SWAP(_type, _a, _b) \ + do \ + { \ + _type __a = (_a); \ + (_a) = (_b); \ + (_b) = __a; \ + } while (0) /** * @brief This macro function concatenates two strings. @@ -100,6 +134,15 @@ extern "C" { */ #define MR_CONCAT(_a, _b) _a##_b +/** + * @brief This macro function converts an integer to a string. + * + * @param _a The integer to convert. + * + * @return The string representation of the integer. + */ +#define MR_STR(_a) #_a + /** * @brief This macro function gets its structure from its member. * @@ -122,89 +165,7 @@ extern "C" { * * @note The variable is local, please use it carefully. */ -#define MR_MAKE_LOCAL(_type, ...) (&((_type){__VA_ARGS__})) - -/** - * @brief This macro function gets the maximum of two values. - * - * @param _a The first value. - * @param _b The second value. - * - * @return The maximum of the two values. - */ -#define MR_MAX(_a, _b) \ - ({ \ - typeof(_a) __a = (_a); \ - typeof(_b) __b = (_b); \ - __a > __b ? __a : __b; \ - }) - -/** - * @brief This macro function gets the minimum of two values. - * - * @param _a The first value. - * @param _b The second value. - * - * @return The minimum of the two values. - */ -#define MR_MIN(_a, _b) \ - ({ \ - typeof(_a) __a = (_a); \ - typeof(_b) __b = (_b); \ - __a < __b ? __a : __b; \ - }) - -/** - * @brief This macro function converts an integer to a string. - * - * @param _a The integer to convert. - * - * @return The string representation of the integer. - */ -#define MR_STR(_a) #_a - -/** - * @brief This macro function swaps two values. - * - * @param _a The first value. - * @param _b The second value. - */ -#define MR_SWAP(_a, _b) \ - ({ \ - typeof(_a) __a = (_a); \ - (_a) = (_b); \ - (_b) = __a; \ - }) - -/** - * @brief This macro function converts a value to a boolean. - * - * @param _value The value to convert. - * - * @return The boolean value. - */ -#define MR_TO_BOOL(_value) (!!(_value)) - -/** - * @brief This macro function provides a with-like construct for execution blocks. - * - * @param _begin The beginning of the block. - * @param _end The end of the block. - * - * @note Using the 'break' or 'return' may caused 'end' not to executed. - */ -#define MR_WITH(_begin, _end) \ - for (bool __with = ({ (_begin), false; }); __with != true; __with = true, (_end)) - -/** @} */ - -/** - * @addtogroup Interrupt - * @{ - */ - -size_t mr_interrupt_disable(void); -void mr_interrupt_enable(size_t mask); +#define MR_LOCAL_MAKE(_type, ...) (&((_type){__VA_ARGS__})) /** @} */ @@ -215,50 +176,64 @@ void mr_interrupt_enable(size_t mask); #define MR_LOG_TAG ("null") #define __MR_LOG_PRINTF(_tag, _fmt, ...) \ - ({ \ + do \ + { \ if (strcmp(_tag, "null") != 0) \ { \ printf(_fmt, ##__VA_ARGS__); \ } \ - }) + } while (0) #ifdef MR_USE_LOG_ERROR #define MR_LOG_E(_fmt, ...) \ - __MR_LOG_PRINTF(MR_LOG_TAG, "[E/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Error log */ + __MR_LOG_PRINTF(MR_LOG_TAG, "[E/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Error log */ #else #define MR_LOG_E(_fmt, ...) #endif /* MR_USE_LOG_ERROR */ #ifdef MR_USE_LOG_WARN #define MR_LOG_W(_fmt, ...) \ - __MR_LOG_PRINTF(MR_LOG_TAG, "[W/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Warning log */ + __MR_LOG_PRINTF(MR_LOG_TAG, "[W/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Warning log */ #else #define MR_LOG_W(_fmt, ...) #endif /* MR_USE_LOG_WARN */ #ifdef MR_USE_LOG_INFO #define MR_LOG_I(_fmt, ...) \ - __MR_LOG_PRINTF(MR_LOG_TAG, "[I/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Information log */ + __MR_LOG_PRINTF(MR_LOG_TAG, "[I/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Information log */ #else #define MR_LOG_I(_fmt, ...) #endif /* MR_USE_LOG_INFO */ #ifdef MR_USE_LOG_DEBUG -#define MR_LOG_D(_fmt, ...) __MR_LOG_PRINTF(MR_LOG_TAG, "[D/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) +#define MR_LOG_D(_fmt, ...) \ + __MR_LOG_PRINTF(MR_LOG_TAG, "[D/%s] "_fmt, MR_LOG_TAG, ##__VA_ARGS__) /**< Debug log */ #else #define MR_LOG_D(_fmt, ...) #endif /* MR_USE_LOG_DEBUG */ #ifdef MR_USE_LOG_ASSERT #define MR_ASSERT(_cond) \ - ({ \ + do \ + { \ if (!(_cond)) \ { \ __MR_LOG_PRINTF("Assert", "[A/%s] Assertion failed: %s, %s, %d.\r\n", __FUNCTION__, \ #_cond, __FILE__, __LINE__); \ + while (1); \ } \ - }) + } while (0) #else #define MR_ASSERT(_cond) #endif /* MR_USE_LOG_ASSERT */ /** @} */ +/** + * @addtogroup Interrupt + * @{ + */ + +size_t mr_irq_disable(void); +void mr_irq_enable(size_t mask); + +/** @} */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/mr_spinlock.h b/include/mr_spinlock.h index d4bbfd9..27082d4 100644 --- a/include/mr_spinlock.h +++ b/include/mr_spinlock.h @@ -24,7 +24,7 @@ extern "C" { /** * @brief This macro function initializes the spinlock. */ -#define MR_SPINLOCK_INIT() \ +#define MR_SPIN_LOCK_INIT() \ { \ .lock = 0 \ } @@ -86,7 +86,7 @@ MR_INLINE size_t mr_spin_lock_irqsave(mr_spinlock_t *lock) size_t mask; /* Disable interrupt */ - mask = mr_interrupt_disable(); + mask = mr_irq_disable(); /* Lock spinlock */ mr_spin_lock(lock); @@ -107,7 +107,7 @@ MR_INLINE void mr_spin_unlock_irqrestore(mr_spinlock_t *lock, size_t mask) mr_spin_unlock(lock); /* Enable mask */ - mr_interrupt_enable(mask); + mr_irq_enable(mask); } /** @} */ diff --git a/source/class.c b/source/class.c index 944fac4..5d4d105 100644 --- a/source/class.c +++ b/source/class.c @@ -46,6 +46,326 @@ static mr_class_t *__class_find(mr_class_t *parent, const char *name) return NULL; } +/** + * @brief This function initialize the class. + * + * @param class The class to initialize. + * @param name The name of the class. + * @param privsize The size of the private data. + * @param release The release function(released when ref-count is 0). + * @param methods The methods of the class. + * + * @note priv_size must be 0 if methods is NULL. + */ +void mr_class_init(mr_class_t *class, const char *name, size_t privsize, + void (*release)(mr_class_t *), void *methods) +{ + MR_ASSERT(class != NULL); + MR_ASSERT(name != NULL); + MR_ASSERT((privsize == 0) || (methods != NULL)); + + /* Initialize the class */ + class->name = name; + class->parent = NULL; + mr_list_init(&class->list); + mr_list_init(&class->clist); + mr_spin_lock_init(&class->lock); + class->privdata = NULL; + class->privsize = privsize; + mr_ref_init(&class->refcount); + class->release = release; + class->methods = methods; +} + +static void __class_release(mr_class_t *class) +{ + /* Release the class */ + mr_free(class); +} + +/** + * @brief This function create the class. + * + * @param name The name of the class. + * @param privsize The size of the private data. + * @param methods The methods of the class. + * + * @return The class, or NULL if failed. + * + * @note priv_size must be 0 if methods is NULL. + */ +mr_class_t *mr_class_create(const char *name, uint32_t privsize, void *methods) +{ + mr_class_t *class; + + MR_ASSERT(name != NULL); + MR_ASSERT((privsize == 0) || (methods != NULL)); + + /* Create the class */ + class = mr_malloc(sizeof(mr_class_t)); + if (class == NULL) + { + return NULL; + } + + /* Initialize the class */ + mr_class_init(class, name, privsize, __class_release, methods); + return class; +} + +/** + * @brief This function add the class to the parent class. + * + * @param class The class to add. + * @param parent The parent class. + * + * @return The error code. + */ +int mr_class_add(mr_class_t *class, mr_class_t *parent) +{ + size_t mask; + int ret; + + MR_ASSERT(class != NULL); + MR_ASSERT(parent != NULL); + + /* Lock the class */ + mask = mr_spin_lock_irqsave(&class->lock); + mr_spin_lock(&parent->lock); + + /* Check if the same name class already exists */ + if (__class_find(parent, class->name) == NULL) + { + ret = MR_EEXIST; + goto _exit; + } + + /* Inherit parent class's implementation if current class has no methods */ + if (class->methods == NULL) + { + class->privsize = parent->privsize; + class->methods = parent->methods; + + /* Child class's private data must be larger than parent's */ + } else if (class->privsize < parent->privsize) + { + ret = MR_EINVAL; + goto _exit; + } + + /* Add the class to the parent */ + class->parent = parent; + mr_list_append(&parent->clist, &class->list); + mr_ref_get(&parent->refcount); + ret = MR_EOK; + +_exit: + /* Unlock the class */ + mr_spin_unlock(&parent->lock); + mr_spin_unlock_irqrestore(&class->lock, mask); + return ret; +} + +static void __ref_release(struct mr_ref *ref) +{ + mr_class_t *class; + + /* Get the class from the reference */ + class = MR_CONTAINER_OF(ref, mr_class_t, refcount); + + /* Remove the class from the list and release the private data */ + mr_list_remove(&class->list); + mr_list_remove(&class->clist); + if (class->privdata != NULL) + { + mr_free(class->privdata); + } + + /* Release the class */ + if (class->release != NULL) + { + class->release(class); + } +} + +/** + * @brief This function delete the class. + * + * @param class The class to delete. + * + * @note 1.The class will not be visited. + * 2.If the class reference count is 0, it will be released. + */ +void mr_class_delete(mr_class_t *class) +{ + mr_class_t *parent; + size_t mask; + + MR_ASSERT(class != NULL); + + /* Lock the class */ + mask = mr_spin_lock_irqsave(&class->lock); + parent = class->parent; + if (parent != NULL) + { + mr_spin_lock(&parent->lock); + } + + /* Remove the class */ + mr_list_remove(&class->list); + + /* Unlock the class */ + if (parent != NULL) + { + /* Put the reference */ + if (mr_ref_put(&parent->refcount, __ref_release) == false) + { + mr_spin_unlock(&parent->lock); + } + } + + /* Put the reference */ + if (mr_ref_put(&class->refcount, __ref_release) == true) + { + /* Enable interrupt */ + mr_irq_enable(mask); + return; + } + + /* Unlock the class if not release */ + mr_spin_unlock_irqrestore(&class->lock, mask); +} + +/** + * @brief This function rename the class. + * + * @param class The class to rename. + * @param name The new name of the class. + * + * @return The error code. + */ +int mr_class_rename(mr_class_t *class, const char *name) +{ + mr_class_t *parent; + size_t mask; + + MR_ASSERT(class != NULL); + MR_ASSERT(name != NULL); + + /* Lock the class */ + mask = mr_spin_lock_irqsave(&class->lock); + parent = class->parent; + if (parent != NULL) + { + mr_spin_lock(&parent->lock); + + /* Check if the same name class already exists */ + if (__class_find(parent, name) != NULL) + { + /* Unlock the class */ + mr_spin_unlock(&parent->lock); + mr_spin_unlock_irqrestore(&class->lock, mask); + return MR_EEXIST; + } + } + + /* Rename the class */ + class->name = name; + + /* Unlock the class */ + if (parent != NULL) + { + mr_spin_unlock(&parent->lock); + } + mr_spin_unlock_irqrestore(&class->lock, mask); + return MR_EOK; +} + +/** + * @brief This function register the class to the directory. + * + * @param class The class to register. + * @param parent The parent class. + * @param dir The directory of the class. + * + * @return The error code. + * + * @note 1.If parent is NULL, path is resolved as an absolute path. + * 2.If dir is NULL, the class will be registered to the parent. + */ +int mr_class_register(mr_class_t *class, mr_class_t *parent, const char *dir) +{ + MR_ASSERT(class != NULL); + + /* Find the directory class */ + parent = mr_class_find(parent, dir); + if (parent == NULL) + { + return MR_ENOENT; + } + + /* Add the class to the directory */ + return mr_class_add(class, parent); +} + +/** + * @brief This function unregister the class. + * + * @param class The class to unregister. + * + * @note 1.The class will not be visited. + * 2.If the class reference count is 0, it will be released. + */ +void mr_class_unregister(mr_class_t *class) +{ + MR_ASSERT(class != NULL); + + /* Delete the class from the root class */ + mr_class_delete(class); +} + +/** + * @brief This function get the reference of the class. + * + * @param class The class. + * + * @return The class. + */ +mr_class_t *mr_class_get(mr_class_t *class) +{ + MR_ASSERT(class != NULL); + + /* Get the reference */ + mr_ref_get(&class->refcount); + return class; +} + +/** + * @brief This function put the reference of the class. + * + * @param class The class. + */ +void mr_class_put(mr_class_t *class) +{ + size_t mask; + + MR_ASSERT(class != NULL); + + /* Lock the class */ + mask = mr_spin_lock_irqsave(&class->lock); + + /* Put the reference */ + if (mr_ref_put(&class->refcount, __ref_release) == true) + { + /* Enable interrupt */ + mr_irq_enable(mask); + return; + } + + /* Unlock the class if not release */ + mr_spin_unlock_irqrestore(&class->lock, mask); +} + /** * @brief This function find the class. * @@ -54,8 +374,7 @@ static mr_class_t *__class_find(mr_class_t *parent, const char *name) * * @return The class. * - * @note 1.If parent is NULL, path is resolved as an absolute path. - * 2.If parent is not NULL, path is resolved as a relative path. + * @note If parent is NULL, path is resolved as an absolute path. */ mr_class_t *mr_class_find(mr_class_t *parent, const char *path) { @@ -115,346 +434,66 @@ mr_class_t *mr_class_find(mr_class_t *parent, const char *path) } /** - * @brief This function initialize the class. - * - * @param class The class to initialize. - * @param name The name of the class. - * @param priv_size The size of the private data. - * @param release The release function(released when ref-count is 0). - * @param methods The methods of the class. - * - * @note priv_size must be 0 if methods is NULL. - */ -void mr_class_init(mr_class_t *class, const char *name, size_t priv_size, - void (*release)(mr_class_t *), void *methods) -{ - MR_ASSERT(class != NULL); - MR_ASSERT(name != NULL); - MR_ASSERT((priv_size == 0) || (methods != NULL)); - - /* Initialize the class */ - class->name = name; - class->parent = NULL; - mr_list_init(&class->list); - mr_list_init(&class->clist); - mr_spin_lock_init(&class->lock); - class->priv_data = NULL; - class->priv_size = priv_size; - mr_ref_init(&class->ref_count); - class->release = release; - class->methods = methods; -} - -static void __class_release(mr_class_t *class) -{ - /* Release the class */ - mr_free(class); -} - -/** - * @brief This function create the class. - * - * @param name The name of the class. - * @param priv_size The size of the private data. - * @param methods The methods of the class. - * - * @return The class, or NULL if failed. - * - * @note priv_size must be 0 if methods is NULL. - */ -mr_class_t *mr_class_create(const char *name, uint32_t priv_size, void *methods) -{ - mr_class_t *class; - - MR_ASSERT(name != NULL); - MR_ASSERT((priv_size == 0) || (methods != NULL)); - - /* Create the class */ - class = mr_malloc(sizeof(mr_class_t)); - if (class == NULL) - { - return NULL; - } - - /* Initialize the class */ - mr_class_init(class, name, priv_size, __class_release, methods); - return class; -} - -/** - * @brief This function add the class to the parent class. - * - * @param class The class to add. - * @param parent The parent class. - * - * @return The error code. - */ -int mr_class_add(mr_class_t *class, mr_class_t *parent) -{ - size_t mask; - int ret; - - MR_ASSERT(class != NULL); - MR_ASSERT(parent != NULL); - - /* Lock the class */ - mask = mr_spin_lock_irqsave(&class->lock); - mr_spin_lock(&parent->lock); - - /* Add the class if not exist same name class */ - if (__class_find(parent, class->name) == NULL) - { - /* Add the class to the list */ - class->parent = parent; - mr_list_append(&parent->clist, &class->list); - - /* Inherit parent class's implementation if current class has no methods */ - if (class->methods == NULL) - { - class->priv_size = parent->priv_size; - class->methods = parent->methods; - } - - /* Get the reference */ - mr_ref_get(&parent->ref_count); - ret = MR_EOK; - } else - { - ret = MR_EEXIST; - } - - /* Unlock the class */ - mr_spin_unlock(&parent->lock); - mr_spin_unlock_irqrestore(&class->lock, mask); - return ret; -} - -static void __ref_release(struct mr_ref *ref) -{ - mr_class_t *class; - - /* Get the class from the reference */ - class = MR_CONTAINER_OF(ref, mr_class_t, ref_count); - - /* Remove the class from the list and release the private data */ - mr_list_remove(&class->list); - mr_list_remove(&class->clist); - if (class->priv_data != NULL) - { - mr_free(class->priv_data); - } - - /* Release the class */ - if (class->release != NULL) - { - class->release(class); - } -} - -/** - * @brief This function delete the class. - * - * @param class The class to delete. - * - * @note 1.The class will not be visited. - * 2.If the class reference count is 0, it will be released. - */ -void mr_class_delete(mr_class_t *class) -{ - mr_class_t *parent; - size_t mask; - - MR_ASSERT(class != NULL); - - /* Lock the class */ - mask = mr_spin_lock_irqsave(&class->lock); - parent = class->parent; - if (parent != NULL) - { - mr_spin_lock(&parent->lock); - } - - /* Remove the class */ - mr_list_remove(&class->list); - - /* Unlock the class */ - if (parent != NULL) - { - /* Put the reference */ - if (mr_ref_put(&parent->ref_count, __ref_release) == false) - { - mr_spin_unlock(&parent->lock); - } - } - - /* Put the reference */ - if (mr_ref_put(&class->ref_count, __ref_release) == true) - { - /* Enable interrupt */ - mr_interrupt_enable(mask); - return; - } - - /* Unlock the class if not release */ - mr_spin_unlock_irqrestore(&class->lock, mask); -} - -/** - * @brief This function register the class to the directory. - * - * @param class The class to register. - * @param parent The parent class. - * @param dir The directory of the class. - * - * @return The error code. - * - * @note 1.If parent is NULL, path is resolved as an absolute path. - * 2.If parent is not NULL, path is resolved as a relative path. - * 3.If dir is NULL, the class will be registered to the parent. - */ -int mr_class_register(mr_class_t *class, mr_class_t *parent, const char *dir) -{ - MR_ASSERT(class != NULL); - - /* Find the directory class */ - parent = mr_class_find(parent, dir); - if (parent == NULL) - { - return MR_ENOENT; - } - - /* Add the class to the directory */ - return mr_class_add(class, parent); -} - -/** - * @brief This function unregister the class. - * - * @param class The class to unregister. - * - * @note 1.The class will not be visited. - * 2.If the class reference count is 0, it will be released. - */ -void mr_class_unregister(mr_class_t *class) -{ - MR_ASSERT(class != NULL); - - /* Delete the class from the root class */ - mr_class_delete(class); -} - -/** - * @brief This function get the reference of the class. + * @brief This function check if the class is a subclass of the base class. * * @param class The class. + * @param base The base class. * - * @return The class. + * @return True if the class is a subclass of the base class, False otherwise. */ -mr_class_t *mr_class_get(mr_class_t *class) +bool mr_class_is_subclass(mr_class_t *class, mr_class_t *base) { MR_ASSERT(class != NULL); + MR_ASSERT(base != NULL); - /* Get the reference */ - mr_ref_get(&class->ref_count); - return class; -} - -/** - * @brief This function put the reference of the class. - * - * @param class The class. - */ -void mr_class_put(mr_class_t *class) -{ - size_t mask; - - MR_ASSERT(class != NULL); - - /* Lock the class */ - mask = mr_spin_lock_irqsave(&class->lock); - - /* Put the reference */ - if (mr_ref_put(&class->ref_count, __ref_release) == true) + /* Check if the class is a subclass of the base class */ + while (class != NULL) { - /* Enable interrupt */ - mr_interrupt_enable(mask); - return; - } - - /* Unlock the class if not release */ - mr_spin_unlock_irqrestore(&class->lock, mask); -} - -/** - * @brief This function rename the class. - * - * @param class The class to rename. - * @param name The new name of the class. - * - * @return The error code. - */ -int mr_class_rename(mr_class_t *class, const char *name) -{ - mr_class_t *parent; - size_t mask; - - MR_ASSERT(class != NULL); - MR_ASSERT(name != NULL); - - /* Lock the class */ - mask = mr_spin_lock_irqsave(&class->lock); - parent = class->parent; - if (parent != NULL) - { - mr_spin_lock(&parent->lock); - - /* Check if the same name class already exists */ - if (__class_find(parent, name) != NULL) + if (class == base) { - /* Unlock the class */ - mr_spin_unlock(&parent->lock); - mr_spin_unlock_irqrestore(&class->lock, mask); - return MR_EEXIST; + return true; } + class = class->parent; } - - /* Rename the class */ - class->name = name; - - /* Unlock the class */ - if (parent != NULL) - { - mr_spin_unlock(&parent->lock); - } - mr_spin_unlock_irqrestore(&class->lock, mask); - return MR_EOK; + return false; } /** * @brief This function get the private data of the class. * + * @param class The class. + * * @return The private data. */ -void *mr_class_priv_data_get(mr_class_t *class) +void *mr_class_get_privdata(mr_class_t *class) { + uint32_t mask; + MR_ASSERT(class != NULL); + /* Lock the class */ + mask = mr_spin_lock_irqsave(&class->lock); + /* Allocate the private data */ - if ((class->priv_data == NULL) && (class->priv_size > 0)) + if ((class->privdata == NULL) && (class->privsize > 0)) { - class->priv_data = mr_malloc(class->priv_size); + class->privdata = mr_malloc(class->privsize); + memset(class->privdata, 0, class->privsize); } - /* Get the private data */ - return class->priv_data; + /* Unlock the class */ + mr_spin_unlock_irqrestore(&class->lock, mask); + return class->privdata; } /** * @brief This function get the methods of the class. - * + * + * @param class The class. + * * @return The methods. */ -void *mr_class_methods_get(mr_class_t *class) +void *mr_class_get_methods(mr_class_t *class) { MR_ASSERT(class != NULL); diff --git a/source/fifo.c b/source/fifo.c index cf4f7bc..0324f8f 100644 --- a/source/fifo.c +++ b/source/fifo.c @@ -31,19 +31,6 @@ int mr_fifo_init(mr_fifo_t *fifo, void *buf, size_t size) return MR_EOK; } -/** - * @brief This function resets a fifo. - * - * @param fifo The fifo. - */ -void mr_fifo_reset(mr_fifo_t *fifo) -{ - MR_ASSERT(fifo != NULL); - - fifo->in = 0; - fifo->out = 0; -} - /** * @brief This function allocates a fifo. * @@ -97,60 +84,16 @@ void mr_fifo_free(mr_fifo_t *fifo) } /** - * @brief This function gets the used space of a fifo. + * @brief This function resets a fifo. * * @param fifo The fifo. - * - * @return The used space. */ -size_t mr_fifo_used_get(const mr_fifo_t *fifo) -{ - uint32_t in, out; - - MR_ASSERT(fifo != NULL); - - /* Get the in and out */ - in = fifo->in; - out = fifo->out; - - /* Calculate the used space */ - return (in >= out) ? in - out : fifo->size - (out - in); -} - -/** - * @brief This function gets the free space of a fifo. - * - * @param fifo The fifo. - * - * @return The free space. - */ -size_t mr_fifo_space_get(const mr_fifo_t *fifo) -{ - uint32_t in, out; - - MR_ASSERT(fifo != NULL); - - /* Get the in and out */ - in = fifo->in; - out = fifo->out; - - /* Calculate the free space */ - return (in >= out) ? fifo->size - (in - out) - 1 : out - in - 1; -} - -/** - * @brief This function gets the size of a fifo. - * - * @param fifo The fifo. - * - * @return The size. - */ -size_t mr_fifo_size_get(const mr_fifo_t *fifo) +void mr_fifo_reset(mr_fifo_t *fifo) { MR_ASSERT(fifo != NULL); - /* Return the buffer size that can be used */ - return (fifo->size == 0) ? 0 : fifo->size - 1; + fifo->in = 0; + fifo->out = 0; } /** @@ -170,7 +113,7 @@ size_t mr_fifo_peek(const mr_fifo_t *fifo, void *buf, size_t count) MR_ASSERT((buf != NULL) || (count == 0)); /* Get used space, limit by count */ - used = mr_fifo_used_get(fifo); + used = mr_fifo_get_used(fifo); if (used < count) { count = used; @@ -211,7 +154,7 @@ size_t mr_fifo_discard(mr_fifo_t *fifo, size_t count) MR_ASSERT(fifo != NULL); /* Get used space, limit by count */ - used = mr_fifo_used_get(fifo); + used = mr_fifo_get_used(fifo); if (used < count) { count = used; @@ -256,7 +199,7 @@ size_t mr_fifo_read(mr_fifo_t *fifo, void *buf, size_t count) MR_ASSERT((buf != NULL) || (count == 0)); /* Get used space, limit by count */ - used = mr_fifo_used_get(fifo); + used = mr_fifo_get_used(fifo); if (used < count) { count = used; @@ -304,7 +247,7 @@ size_t mr_fifo_write(mr_fifo_t *fifo, const void *buf, size_t count) MR_ASSERT((buf != NULL) || (count == 0)); /* Get free space, limit by count */ - free = mr_fifo_space_get(fifo); + free = mr_fifo_get_free(fifo); if (free < count) { count = free; @@ -355,7 +298,7 @@ size_t mr_fifo_write_force(mr_fifo_t *fifo, const void *buf, size_t count) MR_ASSERT((buf != NULL) || (count == 0)); /* Skip data that exceeds the size */ - size = mr_fifo_size_get(fifo); + size = mr_fifo_get_size(fifo); if (count > size) { buf = &((const uint8_t *)buf)[count - size]; @@ -363,7 +306,7 @@ size_t mr_fifo_write_force(mr_fifo_t *fifo, const void *buf, size_t count) } /* Discard data that will be overwritten */ - free = mr_fifo_space_get(fifo); + free = mr_fifo_get_free(fifo); if (free < count) { mr_fifo_discard(fifo, count - free); @@ -372,3 +315,60 @@ size_t mr_fifo_write_force(mr_fifo_t *fifo, const void *buf, size_t count) /* Write data */ return mr_fifo_write(fifo, buf, count); } + +/** + * @brief This function gets the used space of a fifo. + * + * @param fifo The fifo. + * + * @return The used space. + */ +size_t mr_fifo_get_used(const mr_fifo_t *fifo) +{ + uint32_t in, out; + + MR_ASSERT(fifo != NULL); + + /* Get the in and out */ + in = fifo->in; + out = fifo->out; + + /* Calculate the used space */ + return (in >= out) ? in - out : fifo->size - (out - in); +} + +/** + * @brief This function gets the free space of a fifo. + * + * @param fifo The fifo. + * + * @return The free space. + */ +size_t mr_fifo_get_free(const mr_fifo_t *fifo) +{ + uint32_t in, out; + + MR_ASSERT(fifo != NULL); + + /* Get the in and out */ + in = fifo->in; + out = fifo->out; + + /* Calculate the free space */ + return (in >= out) ? fifo->size - (in - out) - 1 : out - in - 1; +} + +/** + * @brief This function gets the size of a fifo. + * + * @param fifo The fifo. + * + * @return The size. + */ +size_t mr_fifo_get_size(const mr_fifo_t *fifo) +{ + MR_ASSERT(fifo != NULL); + + /* Return the buffer size that can be used */ + return (fifo->size == 0) ? 0 : fifo->size - 1; +} diff --git a/source/memory.c b/source/memory.c index 31a38b4..205a6e4 100644 --- a/source/memory.c +++ b/source/memory.c @@ -91,7 +91,7 @@ MR_WEAK void *mr_malloc(size_t size) size_t mask; /* Disable interrupt */ - mask = mr_interrupt_disable(); + mask = mr_irq_disable(); /* Check size and residual memory */ prev = &__heap_start; @@ -143,7 +143,7 @@ MR_WEAK void *mr_malloc(size_t size) _exit: /* Enable interrupt */ - mr_interrupt_enable(mask); + mr_irq_enable(mask); return memory; } @@ -163,7 +163,7 @@ MR_WEAK void mr_free(void *memory) } /* Disable interrupt */ - mask = mr_interrupt_disable(); + mask = mr_irq_disable(); /* Check the block */ block = (mr_heap_block_t *)((uint8_t *)memory - sizeof(mr_heap_block_t)); @@ -176,7 +176,7 @@ MR_WEAK void mr_free(void *memory) } /* Enable interrupt */ - mr_interrupt_enable(mask); + mr_irq_enable(mask); } /** diff --git a/source/service.c b/source/service.c index 05cf255..c1491df 100644 --- a/source/service.c +++ b/source/service.c @@ -41,19 +41,19 @@ void mr_auto_init(void) } /** - * @brief This function disable the interrupt. + * @brief This function disable interrupt. */ -MR_WEAK size_t mr_interrupt_disable(void) +MR_WEAK size_t mr_irq_disable(void) { return 0; } /** - * @brief This function enable the interrupt. + * @brief This function enable interrupt. * * @param mask The interrupt mask. */ -MR_WEAK void mr_interrupt_enable(MR_UNUSED size_t mask) +MR_WEAK void mr_irq_enable(MR_UNUSED size_t mask) { } diff --git a/tool.py b/tools/build.py similarity index 100% rename from tool.py rename to tools/build.py