diff options
| author | Shell <[email protected]> | 2023-12-23 17:59:18 +0800 |
|---|---|---|
| committer | Meco Man <[email protected]> | 2024-01-02 19:42:46 +0800 |
| commit | e7880a9713ef3efed9ad133231981761bcc3e4eb (patch) | |
| tree | 14909d6f79c1c39c89aa462a58779542e6f415d2 /include | |
| parent | 3a7903b799c9f379048368df029cac3e42c28be4 (diff) | |
[kernel] support for hook list
Signed-off-by: Shell <[email protected]>
Diffstat (limited to 'include')
| -rw-r--r-- | include/rtdef.h | 165 | ||||
| -rw-r--r-- | include/rtservice.h | 14 | ||||
| -rw-r--r-- | include/rtthread.h | 10 |
3 files changed, 163 insertions, 26 deletions
diff --git a/include/rtdef.h b/include/rtdef.h index 26b344073a..a13d8b782b 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -54,6 +54,7 @@ * 2023-10-11 zmshahaha move specific devices related and driver to components/drivers * 2023-11-21 Meco Man add RT_USING_NANO macro * 2023-12-18 xqyjlj add rt_always_inline + * 2023-12-22 Shell Support hook list */ #ifndef __RT_DEF_H__ @@ -198,6 +199,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define rt_used __attribute__((used)) #define rt_align(n) __attribute__((aligned(n))) #define rt_weak __attribute__((weak)) +#define rt_typeof typeof #define rt_noreturn #define rt_inline static __inline #define rt_always_inline rt_inline @@ -207,6 +209,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define PRAGMA(x) _Pragma(#x) #define rt_align(n) PRAGMA(data_alignment=n) #define rt_weak __weak +#define rt_typeof typeof #define rt_noreturn #define rt_inline static inline #define rt_always_inline rt_inline @@ -217,6 +220,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define rt_used __attribute__((used)) #define rt_align(n) __attribute__((aligned(n))) #define rt_weak __attribute__((weak)) +#define rt_typeof __typeof__ #define rt_noreturn __attribute__ ((noreturn)) #define rt_inline static __inline #define rt_always_inline static inline __attribute__((always_inline)) @@ -225,6 +229,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define rt_used __attribute__((used)) #define rt_align(n) __attribute__((aligned(n))) #define rt_weak __attribute__((weak)) +#define rt_typeof typeof #define rt_noreturn #define rt_inline static inline #define rt_always_inline rt_inline @@ -233,6 +238,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define rt_used #define rt_align(n) __declspec(align(n)) #define rt_weak +#define rt_typeof typeof #define rt_noreturn #define rt_inline static __inline #define rt_always_inline rt_inline @@ -253,6 +259,8 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #else #define rt_weak #endif +#define rt_typeof typeof +#define rt_noreturn #define rt_inline static inline #define rt_always_inline rt_inline #elif defined (__TASKING__) @@ -261,6 +269,8 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define PRAGMA(x) _Pragma(#x) #define rt_align(n) __attribute__((__align(n))) #define rt_weak __attribute__((weak)) +#define rt_typeof typeof +#define rt_noreturn #define rt_inline static inline #define rt_always_inline rt_inline #else @@ -593,10 +603,24 @@ struct rt_object_information * The hook function call macro */ #ifndef RT_USING_HOOK - #define __ON_HOOK_ARGS(__hook, argv) - #define RT_OBJECT_HOOK_CALL(func, argv) +#define RT_OBJECT_HOOK_CALL(func, argv) + #else - #define RT_OBJECT_HOOK_CALL(func, argv) __on_##func argv + +/** + * @brief Add hook point in the routines + * @note Usage: + * void foo() { + * do_something(); + * + * RT_OBJECT_HOOK_CALL(foo); + * + * do_other_things(); + * } + */ +#define _RT_OBJECT_HOOK_CALL(func, argv) __ON_HOOK_ARGS(func, argv) +#define RT_OBJECT_HOOK_CALL(func, argv) _RT_OBJECT_HOOK_CALL(func, argv) + #ifdef RT_HOOK_USING_FUNC_PTR #define __ON_HOOK_ARGS(__hook, argv) do {if ((__hook) != RT_NULL) __hook argv; } while (0) #else @@ -604,22 +628,127 @@ struct rt_object_information #endif /* RT_HOOK_USING_FUNC_PTR */ #endif /* RT_USING_HOOK */ -#ifndef __on_rt_interrupt_switch_hook - #define __on_rt_interrupt_switch_hook() __ON_HOOK_ARGS(rt_interrupt_switch_hook, ()) -#endif -#ifndef __on_rt_malloc_hook - #define __on_rt_malloc_hook(addr, size) __ON_HOOK_ARGS(rt_malloc_hook, (addr, size)) -#endif -#ifndef __on_rt_realloc_entry_hook - #define __on_rt_realloc_entry_hook(addr, size) __ON_HOOK_ARGS(rt_realloc_entry_hook, (addr, size)) -#endif -#ifndef __on_rt_realloc_exit_hook - #define __on_rt_realloc_exit_hook(addr, size) __ON_HOOK_ARGS(rt_realloc_exit_hook, (addr, size)) -#endif -#ifndef __on_rt_free_hook - #define __on_rt_free_hook(rmem) __ON_HOOK_ARGS(rt_free_hook, (rmem)) -#endif +#ifdef RT_USING_HOOKLIST + +/** + * @brief Add declaration for hook list types. + * + * @note Usage: + * This is typically used in your header. In foo.h using this like: + * + * ```foo.h + * typedef void (*bar_hook_proto_t)(arguments...); + * RT_OBJECT_HOOKLIST_DECLARE(bar_hook_proto_t, bar_myhook); + * ``` + */ +#define RT_OBJECT_HOOKLIST_DECLARE(handler_type, name) \ + typedef struct name##_hooklistnode \ + { \ + handler_type handler; \ + rt_list_t list_node; \ + } *name##_hooklistnode_t; \ + extern volatile rt_ubase_t name##_nested; \ + void name##_sethook(name##_hooklistnode_t node); \ + void name##_rmhook(name##_hooklistnode_t node) + +/** + * @brief Add declaration for hook list node. + * + * @note Usage + * You can add a hook like this. + * + * ```addhook.c + * void myhook(arguments...) { do_something(); } + * RT_OBJECT_HOOKLIST_DEFINE_NODE(bar_myhook, myhook_node, myhook); + * + * void addhook(void) + * { + * bar_myhook_sethook(myhook); + * } + * ``` + * + * BTW, you can also find examples codes under + * `examples/utest/testcases/kernel/hooklist_tc.c`. + */ +#define RT_OBJECT_HOOKLIST_DEFINE_NODE(hookname, nodename, hooker_handler) \ + struct hookname##_hooklistnode nodename = { \ + .handler = hooker_handler, \ + .list_node = RT_LIST_OBJECT_INIT(nodename.list_node), \ + }; + +/** + * @note Usage + * Add this macro to the source file where your hook point is inserted. + */ +#define RT_OBJECT_HOOKLIST_DEFINE(name) \ + static rt_list_t name##_hooklist = RT_LIST_OBJECT_INIT(name##_hooklist); \ + static struct rt_spinlock name##lock = RT_SPINLOCK_INIT; \ + volatile rt_ubase_t name##_nested = 0; \ + void name##_sethook(name##_hooklistnode_t node) \ + { \ + rt_ubase_t level = rt_spin_lock_irqsave(&name##lock); \ + while (name##_nested) \ + { \ + rt_spin_unlock_irqrestore(&name##lock, level); \ + level = rt_spin_lock_irqsave(&name##lock); \ + } \ + rt_list_insert_before(&name##_hooklist, &node->list_node); \ + rt_spin_unlock_irqrestore(&name##lock, level); \ + } \ + void name##_rmhook(name##_hooklistnode_t node) \ + { \ + rt_ubase_t level = rt_spin_lock_irqsave(&name##lock); \ + while (name##_nested) \ + { \ + rt_spin_unlock_irqrestore(&name##lock, level); \ + level = rt_spin_lock_irqsave(&name##lock); \ + } \ + rt_list_remove(&node->list_node); \ + rt_spin_unlock_irqrestore(&name##lock, level); \ + } + +/** + * @brief Add hook list point in the routines. Multiple hookers in the list will + * be called one by one starting from head node. + * + * @note Usage: + * void foo() { + * do_something(); + * + * RT_OBJECT_HOOKLIST_CALL(foo); + * + * do_other_things(); + * } + */ +#define _RT_OBJECT_HOOKLIST_CALL(nodetype, nested, list, lock, argv) \ + do \ + { \ + nodetype iter; \ + rt_ubase_t level = rt_spin_lock_irqsave(&lock); \ + nested += 1; \ + rt_spin_unlock_irqrestore(&lock, level); \ + if (!rt_list_isempty(&list)) \ + { \ + rt_list_for_each_entry(iter, &list, list_node) \ + { \ + iter->handler argv; \ + } \ + } \ + level = rt_spin_lock_irqsave(&lock); \ + nested -= 1; \ + rt_spin_unlock_irqrestore(&lock, level); \ + } while (0) +#define RT_OBJECT_HOOKLIST_CALL(name, argv) \ + _RT_OBJECT_HOOKLIST_CALL(name##_hooklistnode_t, name##_nested, \ + name##_hooklist, name##lock, argv) + +#else +#define RT_OBJECT_HOOKLIST_DECLARE(handler_type, name) +#define RT_OBJECT_HOOKLIST_DEFINE_NODE(hookname, nodename, hooker_handler) +#define RT_OBJECT_HOOKLIST_DEFINE(name) +#define RT_OBJECT_HOOKLIST_CALL(name, argv) +#endif /* RT_USING_HOOKLIST */ /**@}*/ diff --git a/include/rtservice.h b/include/rtservice.h index 03301aa99a..83faf640f7 100644 --- a/include/rtservice.h +++ b/include/rtservice.h @@ -151,9 +151,9 @@ rt_inline unsigned int rt_list_len(const rt_list_t *l) * @param member the name of the list_struct within the struct. */ #define rt_list_for_each_entry(pos, head, member) \ - for (pos = rt_list_entry((head)->next, typeof(*pos), member); \ + for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member); \ &pos->member != (head); \ - pos = rt_list_entry(pos->member.next, typeof(*pos), member)) + pos = rt_list_entry(pos->member.next, rt_typeof(*pos), member)) /** * rt_list_for_each_entry_safe - iterate over list of given type safe against removal of list entry @@ -163,10 +163,10 @@ rt_inline unsigned int rt_list_len(const rt_list_t *l) * @param member the name of the list_struct within the struct. */ #define rt_list_for_each_entry_safe(pos, n, head, member) \ - for (pos = rt_list_entry((head)->next, typeof(*pos), member), \ - n = rt_list_entry(pos->member.next, typeof(*pos), member); \ + for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member), \ + n = rt_list_entry(pos->member.next, rt_typeof(*pos), member); \ &pos->member != (head); \ - pos = n, n = rt_list_entry(n->member.next, typeof(*n), member)) + pos = n, n = rt_list_entry(n->member.next, rt_typeof(*n), member)) /** * rt_list_first_entry - get the first element from a list @@ -280,9 +280,9 @@ rt_inline int rt_slist_isempty(rt_slist_t *l) * @param member the name of the list_struct within the struct. */ #define rt_slist_for_each_entry(pos, head, member) \ - for (pos = ((head)->next == (RT_NULL) ? (RT_NULL) : rt_slist_entry((head)->next, typeof(*pos), member)); \ + for (pos = ((head)->next == (RT_NULL) ? (RT_NULL) : rt_slist_entry((head)->next, rt_typeof(*pos), member)); \ pos != (RT_NULL) && &pos->member != (RT_NULL); \ - pos = (pos->member.next == (RT_NULL) ? (RT_NULL) : rt_slist_entry(pos->member.next, typeof(*pos), member))) + pos = (pos->member.next == (RT_NULL) ? (RT_NULL) : rt_slist_entry(pos->member.next, rt_typeof(*pos), member))) /** * rt_slist_first_entry - get the first element from a slist diff --git a/include/rtthread.h b/include/rtthread.h index fc14e50de1..93fd138334 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -179,7 +179,15 @@ int rt_thread_kill(rt_thread_t tid, int sig); #ifdef RT_USING_HOOK void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread)); void rt_thread_resume_sethook (void (*hook)(rt_thread_t thread)); -void rt_thread_inited_sethook (void (*hook)(rt_thread_t thread)); + +/** + * @brief Sets a hook function when a thread is initialized. + * + * @param thread is the target thread that initializing + */ +typedef void (*rt_thread_inited_hookproto_t)(rt_thread_t thread); +RT_OBJECT_HOOKLIST_DECLARE(rt_thread_inited_hookproto_t, rt_thread_inited); + #endif /* RT_USING_HOOK */ /* |
