[kernel] support for hook list

Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
Shell
2024-01-02 19:42:46 +08:00
committed by Meco Man
parent 3a7903b799
commit e7880a9713
17 changed files with 280 additions and 124 deletions
+147 -18
View File
@@ -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 */
/**@}*/
+7 -7
View File
@@ -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
+9 -1
View File
@@ -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 */
/*