[kernel] support for hook list
Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
parent
3a7903b799
commit
e7880a9713
|
@ -60,4 +60,9 @@ config UTEST_ATOMIC_TC
|
||||||
bool "atomic test"
|
bool "atomic test"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config UTEST_HOOKLIST_TC
|
||||||
|
bool "hook list test"
|
||||||
|
select RT_USING_HOOKLIST
|
||||||
|
default n
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -44,6 +44,9 @@ if GetDepend(['UTEST_THREAD_TC']):
|
||||||
if GetDepend(['UTEST_ATOMIC_TC']):
|
if GetDepend(['UTEST_ATOMIC_TC']):
|
||||||
src += ['atomic_tc.c']
|
src += ['atomic_tc.c']
|
||||||
|
|
||||||
|
if GetDepend(['UTEST_HOOKLIST_TC']):
|
||||||
|
src += ['hooklist_tc.c']
|
||||||
|
|
||||||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
Return('group')
|
Return('group')
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2023-12-22 Shell Support hook list
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include "rtconfig.h"
|
||||||
|
#include "utest.h"
|
||||||
|
#include "utest_assert.h"
|
||||||
|
|
||||||
|
static int hooker1_ent_count;
|
||||||
|
static int hooker2_ent_count;
|
||||||
|
static struct rt_thread thr_tobe_inited;
|
||||||
|
|
||||||
|
static void thread_inited_hooker1(rt_thread_t thread)
|
||||||
|
{
|
||||||
|
LOG_D("%s: count %d", __func__, hooker1_ent_count);
|
||||||
|
hooker1_ent_count += 1;
|
||||||
|
}
|
||||||
|
RT_OBJECT_HOOKLIST_DEFINE_NODE(rt_thread_inited, hooker1_node, thread_inited_hooker1);
|
||||||
|
|
||||||
|
static void thread_inited_hooker2(rt_thread_t thread)
|
||||||
|
{
|
||||||
|
LOG_D("%s: count %d", __func__, hooker2_ent_count);
|
||||||
|
hooker2_ent_count += 1;
|
||||||
|
}
|
||||||
|
RT_OBJECT_HOOKLIST_DEFINE_NODE(rt_thread_inited, hooker2_node, thread_inited_hooker2);
|
||||||
|
|
||||||
|
static char _thr_stack[UTEST_THR_STACK_SIZE];
|
||||||
|
static void thr_tobe_inited_entry(void *param)
|
||||||
|
{
|
||||||
|
rt_kprintf("Hello!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hooklist_test(void)
|
||||||
|
{
|
||||||
|
hooker1_ent_count = 0;
|
||||||
|
hooker2_ent_count = 0;
|
||||||
|
rt_thread_inited_sethook(&hooker1_node);
|
||||||
|
rt_thread_inited_sethook(&hooker2_node);
|
||||||
|
|
||||||
|
/* run 1 */
|
||||||
|
rt_thread_init(&thr_tobe_inited,
|
||||||
|
"thr_tobe_inited",
|
||||||
|
thr_tobe_inited_entry,
|
||||||
|
NULL,
|
||||||
|
_thr_stack,
|
||||||
|
sizeof(_thr_stack),
|
||||||
|
25,
|
||||||
|
100);
|
||||||
|
|
||||||
|
uassert_int_equal(hooker1_ent_count, 1);
|
||||||
|
uassert_int_equal(hooker2_ent_count, 1);
|
||||||
|
|
||||||
|
rt_thread_detach(&thr_tobe_inited);
|
||||||
|
rt_thread_mdelay(1); /* wait recycling done */
|
||||||
|
|
||||||
|
/* run 2 */
|
||||||
|
rt_thread_inited_rmhook(&hooker2_node);
|
||||||
|
|
||||||
|
rt_thread_init(&thr_tobe_inited,
|
||||||
|
"thr_tobe_inited",
|
||||||
|
thr_tobe_inited_entry,
|
||||||
|
NULL,
|
||||||
|
_thr_stack,
|
||||||
|
sizeof(_thr_stack),
|
||||||
|
25,
|
||||||
|
100);
|
||||||
|
|
||||||
|
uassert_int_equal(hooker1_ent_count, 2);
|
||||||
|
uassert_int_equal(hooker2_ent_count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t utest_tc_init(void)
|
||||||
|
{
|
||||||
|
hooker1_ent_count = 0;
|
||||||
|
hooker2_ent_count = 0;
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t utest_tc_cleanup(void)
|
||||||
|
{
|
||||||
|
rt_thread_detach(&thr_tobe_inited);
|
||||||
|
rt_thread_inited_rmhook(&hooker1_node);
|
||||||
|
rt_thread_inited_rmhook(&hooker2_node);
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testcase(void)
|
||||||
|
{
|
||||||
|
UTEST_UNIT_RUN(hooklist_test);
|
||||||
|
}
|
||||||
|
UTEST_TC_EXPORT(testcase, "testcases.kernel.hooklist_tc", utest_tc_init, utest_tc_cleanup, 10);
|
165
include/rtdef.h
165
include/rtdef.h
|
@ -54,6 +54,7 @@
|
||||||
* 2023-10-11 zmshahaha move specific devices related and driver to components/drivers
|
* 2023-10-11 zmshahaha move specific devices related and driver to components/drivers
|
||||||
* 2023-11-21 Meco Man add RT_USING_NANO macro
|
* 2023-11-21 Meco Man add RT_USING_NANO macro
|
||||||
* 2023-12-18 xqyjlj add rt_always_inline
|
* 2023-12-18 xqyjlj add rt_always_inline
|
||||||
|
* 2023-12-22 Shell Support hook list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RT_DEF_H__
|
#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_used __attribute__((used))
|
||||||
#define rt_align(n) __attribute__((aligned(n)))
|
#define rt_align(n) __attribute__((aligned(n)))
|
||||||
#define rt_weak __attribute__((weak))
|
#define rt_weak __attribute__((weak))
|
||||||
|
#define rt_typeof typeof
|
||||||
#define rt_noreturn
|
#define rt_noreturn
|
||||||
#define rt_inline static __inline
|
#define rt_inline static __inline
|
||||||
#define rt_always_inline rt_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 PRAGMA(x) _Pragma(#x)
|
||||||
#define rt_align(n) PRAGMA(data_alignment=n)
|
#define rt_align(n) PRAGMA(data_alignment=n)
|
||||||
#define rt_weak __weak
|
#define rt_weak __weak
|
||||||
|
#define rt_typeof typeof
|
||||||
#define rt_noreturn
|
#define rt_noreturn
|
||||||
#define rt_inline static inline
|
#define rt_inline static inline
|
||||||
#define rt_always_inline rt_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_used __attribute__((used))
|
||||||
#define rt_align(n) __attribute__((aligned(n)))
|
#define rt_align(n) __attribute__((aligned(n)))
|
||||||
#define rt_weak __attribute__((weak))
|
#define rt_weak __attribute__((weak))
|
||||||
|
#define rt_typeof __typeof__
|
||||||
#define rt_noreturn __attribute__ ((noreturn))
|
#define rt_noreturn __attribute__ ((noreturn))
|
||||||
#define rt_inline static __inline
|
#define rt_inline static __inline
|
||||||
#define rt_always_inline static inline __attribute__((always_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_used __attribute__((used))
|
||||||
#define rt_align(n) __attribute__((aligned(n)))
|
#define rt_align(n) __attribute__((aligned(n)))
|
||||||
#define rt_weak __attribute__((weak))
|
#define rt_weak __attribute__((weak))
|
||||||
|
#define rt_typeof typeof
|
||||||
#define rt_noreturn
|
#define rt_noreturn
|
||||||
#define rt_inline static inline
|
#define rt_inline static inline
|
||||||
#define rt_always_inline rt_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_used
|
||||||
#define rt_align(n) __declspec(align(n))
|
#define rt_align(n) __declspec(align(n))
|
||||||
#define rt_weak
|
#define rt_weak
|
||||||
|
#define rt_typeof typeof
|
||||||
#define rt_noreturn
|
#define rt_noreturn
|
||||||
#define rt_inline static __inline
|
#define rt_inline static __inline
|
||||||
#define rt_always_inline rt_inline
|
#define rt_always_inline rt_inline
|
||||||
|
@ -253,6 +259,8 @@ typedef rt_base_t rt_off_t; /**< Type for offset */
|
||||||
#else
|
#else
|
||||||
#define rt_weak
|
#define rt_weak
|
||||||
#endif
|
#endif
|
||||||
|
#define rt_typeof typeof
|
||||||
|
#define rt_noreturn
|
||||||
#define rt_inline static inline
|
#define rt_inline static inline
|
||||||
#define rt_always_inline rt_inline
|
#define rt_always_inline rt_inline
|
||||||
#elif defined (__TASKING__)
|
#elif defined (__TASKING__)
|
||||||
|
@ -261,6 +269,8 @@ typedef rt_base_t rt_off_t; /**< Type for offset */
|
||||||
#define PRAGMA(x) _Pragma(#x)
|
#define PRAGMA(x) _Pragma(#x)
|
||||||
#define rt_align(n) __attribute__((__align(n)))
|
#define rt_align(n) __attribute__((__align(n)))
|
||||||
#define rt_weak __attribute__((weak))
|
#define rt_weak __attribute__((weak))
|
||||||
|
#define rt_typeof typeof
|
||||||
|
#define rt_noreturn
|
||||||
#define rt_inline static inline
|
#define rt_inline static inline
|
||||||
#define rt_always_inline rt_inline
|
#define rt_always_inline rt_inline
|
||||||
#else
|
#else
|
||||||
|
@ -593,10 +603,24 @@ struct rt_object_information
|
||||||
* The hook function call macro
|
* The hook function call macro
|
||||||
*/
|
*/
|
||||||
#ifndef RT_USING_HOOK
|
#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
|
#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
|
#ifdef RT_HOOK_USING_FUNC_PTR
|
||||||
#define __ON_HOOK_ARGS(__hook, argv) do {if ((__hook) != RT_NULL) __hook argv; } while (0)
|
#define __ON_HOOK_ARGS(__hook, argv) do {if ((__hook) != RT_NULL) __hook argv; } while (0)
|
||||||
#else
|
#else
|
||||||
|
@ -604,22 +628,127 @@ struct rt_object_information
|
||||||
#endif /* RT_HOOK_USING_FUNC_PTR */
|
#endif /* RT_HOOK_USING_FUNC_PTR */
|
||||||
#endif /* RT_USING_HOOK */
|
#endif /* RT_USING_HOOK */
|
||||||
|
|
||||||
#ifndef __on_rt_interrupt_switch_hook
|
#ifdef RT_USING_HOOKLIST
|
||||||
#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
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 */
|
||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* @param member the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define rt_list_for_each_entry(pos, head, member) \
|
#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->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
|
* 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.
|
* @param member the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define rt_list_for_each_entry_safe(pos, n, head, member) \
|
#define rt_list_for_each_entry_safe(pos, n, head, member) \
|
||||||
for (pos = rt_list_entry((head)->next, typeof(*pos), member), \
|
for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member), \
|
||||||
n = rt_list_entry(pos->member.next, typeof(*pos), member); \
|
n = rt_list_entry(pos->member.next, rt_typeof(*pos), member); \
|
||||||
&pos->member != (head); \
|
&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
|
* 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.
|
* @param member the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define rt_slist_for_each_entry(pos, head, member) \
|
#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 != (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
|
* rt_slist_first_entry - get the first element from a slist
|
||||||
|
|
|
@ -179,7 +179,15 @@ int rt_thread_kill(rt_thread_t tid, int sig);
|
||||||
#ifdef RT_USING_HOOK
|
#ifdef RT_USING_HOOK
|
||||||
void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread));
|
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_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 */
|
#endif /* RT_USING_HOOK */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -132,6 +132,13 @@ config RT_USING_HOOK
|
||||||
default y
|
default y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
config RT_USING_HOOKLIST
|
||||||
|
bool "Enable hook list"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable the hook list feature for rt-thread packages. With this, they can
|
||||||
|
plug in to the system on run-time.
|
||||||
|
|
||||||
config RT_USING_IDLE_HOOK
|
config RT_USING_IDLE_HOOK
|
||||||
bool "Enable IDLE Task hook"
|
bool "Enable IDLE Task hook"
|
||||||
default y if RT_USING_HOOK
|
default y if RT_USING_HOOK
|
||||||
|
|
|
@ -29,10 +29,6 @@
|
||||||
static volatile rt_atomic_t rt_tick = 0;
|
static volatile rt_atomic_t rt_tick = 0;
|
||||||
#endif /* RT_USING_SMP */
|
#endif /* RT_USING_SMP */
|
||||||
|
|
||||||
#ifndef __on_rt_tick_hook
|
|
||||||
#define __on_rt_tick_hook() __ON_HOOK_ARGS(rt_tick_hook, ())
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_tick_hook)(void);
|
static void (*rt_tick_hook)(void);
|
||||||
|
|
||||||
|
|
10
src/ipc.c
10
src/ipc.c
|
@ -55,16 +55,6 @@
|
||||||
#define DBG_LVL DBG_INFO
|
#define DBG_LVL DBG_INFO
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#ifndef __on_rt_object_trytake_hook
|
|
||||||
#define __on_rt_object_trytake_hook(parent) __ON_HOOK_ARGS(rt_object_trytake_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_take_hook
|
|
||||||
#define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_put_hook
|
|
||||||
#define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GET_MESSAGEBYTE_ADDR(msg) ((struct rt_mq_message *) msg + 1)
|
#define GET_MESSAGEBYTE_ADDR(msg) ((struct rt_mq_message *) msg + 1)
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
extern void (*rt_object_trytake_hook)(struct rt_object *object);
|
extern void (*rt_object_trytake_hook)(struct rt_object *object);
|
||||||
|
|
|
@ -22,13 +22,6 @@
|
||||||
#define DBG_LVL DBG_INFO
|
#define DBG_LVL DBG_INFO
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#ifndef __on_rt_interrupt_enter_hook
|
|
||||||
#define __on_rt_interrupt_enter_hook() __ON_HOOK_ARGS(rt_interrupt_enter_hook, ())
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_interrupt_leave_hook
|
|
||||||
#define __on_rt_interrupt_leave_hook() __ON_HOOK_ARGS(rt_interrupt_leave_hook, ())
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
|
|
||||||
static void (*rt_interrupt_enter_hook)(void);
|
static void (*rt_interrupt_enter_hook)(void);
|
||||||
|
|
|
@ -1579,7 +1579,7 @@ rt_err_t rt_backtrace_frame(struct rt_hw_backtrace_frame *frame)
|
||||||
{
|
{
|
||||||
long nesting = 0;
|
long nesting = 0;
|
||||||
|
|
||||||
rt_kprintf("please use: addr2line -e rtthread.elf -a -f\n");
|
rt_kprintf("please use: addr2line -e rtthread.elf -a -f");
|
||||||
|
|
||||||
while (nesting < RT_BACKTRACE_LEVEL_MAX_NR)
|
while (nesting < RT_BACKTRACE_LEVEL_MAX_NR)
|
||||||
{
|
{
|
||||||
|
@ -2177,10 +2177,6 @@ int __rt_ffs(int value)
|
||||||
#endif /* RT_USING_TINY_FFS */
|
#endif /* RT_USING_TINY_FFS */
|
||||||
#endif /* RT_USING_CPU_FFS */
|
#endif /* RT_USING_CPU_FFS */
|
||||||
|
|
||||||
#ifndef __on_rt_assert_hook
|
|
||||||
#define __on_rt_assert_hook(ex, func, line) __ON_HOOK_ARGS(rt_assert_hook, (ex, func, line))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RT_USING_DEBUG
|
#ifdef RT_USING_DEBUG
|
||||||
/* RT_ASSERT(EX)'s hook */
|
/* RT_ASSERT(EX)'s hook */
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,6 @@
|
||||||
|
|
||||||
#ifdef RT_USING_MEMPOOL
|
#ifdef RT_USING_MEMPOOL
|
||||||
|
|
||||||
#ifndef __on_rt_mp_alloc_hook
|
|
||||||
#define __on_rt_mp_alloc_hook(mp, block) __ON_HOOK_ARGS(rt_mp_alloc_hook, (mp, block))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_mp_free_hook
|
|
||||||
#define __on_rt_mp_free_hook(mp, block) __ON_HOOK_ARGS(rt_mp_free_hook, (mp, block))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_mp_alloc_hook)(struct rt_mempool *mp, void *block);
|
static void (*rt_mp_alloc_hook)(struct rt_mempool *mp, void *block);
|
||||||
static void (*rt_mp_free_hook)(struct rt_mempool *mp, void *block);
|
static void (*rt_mp_free_hook)(struct rt_mempool *mp, void *block);
|
||||||
|
|
16
src/object.c
16
src/object.c
|
@ -137,22 +137,6 @@ static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef __on_rt_object_attach_hook
|
|
||||||
#define __on_rt_object_attach_hook(obj) __ON_HOOK_ARGS(rt_object_attach_hook, (obj))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_detach_hook
|
|
||||||
#define __on_rt_object_detach_hook(obj) __ON_HOOK_ARGS(rt_object_detach_hook, (obj))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_trytake_hook
|
|
||||||
#define __on_rt_object_trytake_hook(parent) __ON_HOOK_ARGS(rt_object_trytake_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_take_hook
|
|
||||||
#define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_put_hook
|
|
||||||
#define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_object_attach_hook)(struct rt_object *object);
|
static void (*rt_object_attach_hook)(struct rt_object *object);
|
||||||
static void (*rt_object_detach_hook)(struct rt_object *object);
|
static void (*rt_object_detach_hook)(struct rt_object *object);
|
||||||
|
|
|
@ -48,13 +48,6 @@ rt_uint32_t rt_thread_ready_priority_group;
|
||||||
rt_uint8_t rt_thread_ready_table[32];
|
rt_uint8_t rt_thread_ready_table[32];
|
||||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||||
|
|
||||||
#ifndef __on_rt_scheduler_hook
|
|
||||||
#define __on_rt_scheduler_hook(from, to) __ON_HOOK_ARGS(rt_scheduler_hook, (from, to))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_scheduler_switch_hook
|
|
||||||
#define __on_rt_scheduler_switch_hook(tid) __ON_HOOK_ARGS(rt_scheduler_switch_hook, (tid))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
|
static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
|
||||||
static void (*rt_scheduler_switch_hook)(struct rt_thread *tid);
|
static void (*rt_scheduler_switch_hook)(struct rt_thread *tid);
|
||||||
|
|
|
@ -51,13 +51,6 @@ static rt_int16_t rt_scheduler_lock_nest;
|
||||||
struct rt_thread *rt_current_thread = RT_NULL;
|
struct rt_thread *rt_current_thread = RT_NULL;
|
||||||
rt_uint8_t rt_current_priority;
|
rt_uint8_t rt_current_priority;
|
||||||
|
|
||||||
#ifndef __on_rt_scheduler_hook
|
|
||||||
#define __on_rt_scheduler_hook(from, to) __ON_HOOK_ARGS(rt_scheduler_hook, (from, to))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_scheduler_switch_hook
|
|
||||||
#define __on_rt_scheduler_switch_hook(tid) __ON_HOOK_ARGS(rt_scheduler_switch_hook, (tid))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
|
static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
|
||||||
static void (*rt_scheduler_switch_hook)(struct rt_thread *tid);
|
static void (*rt_scheduler_switch_hook)(struct rt_thread *tid);
|
||||||
|
|
23
src/thread.c
23
src/thread.c
|
@ -45,20 +45,9 @@
|
||||||
#define DBG_LVL DBG_INFO
|
#define DBG_LVL DBG_INFO
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#ifndef __on_rt_thread_inited_hook
|
|
||||||
#define __on_rt_thread_inited_hook(thread) __ON_HOOK_ARGS(rt_thread_inited_hook, (thread))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_thread_suspend_hook
|
|
||||||
#define __on_rt_thread_suspend_hook(thread) __ON_HOOK_ARGS(rt_thread_suspend_hook, (thread))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_thread_resume_hook
|
|
||||||
#define __on_rt_thread_resume_hook(thread) __ON_HOOK_ARGS(rt_thread_resume_hook, (thread))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
static void (*rt_thread_suspend_hook)(rt_thread_t thread);
|
static void (*rt_thread_suspend_hook)(rt_thread_t thread);
|
||||||
static void (*rt_thread_resume_hook) (rt_thread_t thread);
|
static void (*rt_thread_resume_hook) (rt_thread_t thread);
|
||||||
static void (*rt_thread_inited_hook) (rt_thread_t thread);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function sets a hook function when the system suspend a thread.
|
* @brief This function sets a hook function when the system suspend a thread.
|
||||||
|
@ -84,15 +73,7 @@ void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread))
|
||||||
rt_thread_resume_hook = hook;
|
rt_thread_resume_hook = hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
RT_OBJECT_HOOKLIST_DEFINE(rt_thread_inited);
|
||||||
* @brief This function sets a hook function when a thread is initialized.
|
|
||||||
*
|
|
||||||
* @param hook is the specified hook function.
|
|
||||||
*/
|
|
||||||
void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
|
|
||||||
{
|
|
||||||
rt_thread_inited_hook = hook;
|
|
||||||
}
|
|
||||||
#endif /* defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR) */
|
#endif /* defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR) */
|
||||||
|
|
||||||
static void _thread_exit(void)
|
static void _thread_exit(void)
|
||||||
|
@ -313,7 +294,7 @@ static rt_err_t _thread_init(struct rt_thread *thread,
|
||||||
rt_atomic_store(&thread->ref_count, 0);
|
rt_atomic_store(&thread->ref_count, 0);
|
||||||
rt_spin_lock_init(&thread->spinlock);
|
rt_spin_lock_init(&thread->spinlock);
|
||||||
|
|
||||||
RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
|
RT_OBJECT_HOOKLIST_CALL(rt_thread_inited, (thread));
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
|
13
src/timer.c
13
src/timer.c
|
@ -57,19 +57,6 @@ rt_align(RT_ALIGN_SIZE)
|
||||||
static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE];
|
static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE];
|
||||||
#endif /* RT_USING_TIMER_SOFT */
|
#endif /* RT_USING_TIMER_SOFT */
|
||||||
|
|
||||||
#ifndef __on_rt_object_take_hook
|
|
||||||
#define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_object_put_hook
|
|
||||||
#define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_timer_enter_hook
|
|
||||||
#define __on_rt_timer_enter_hook(t) __ON_HOOK_ARGS(rt_timer_enter_hook, (t))
|
|
||||||
#endif
|
|
||||||
#ifndef __on_rt_timer_exit_hook
|
|
||||||
#define __on_rt_timer_exit_hook(t) __ON_HOOK_ARGS(rt_timer_exit_hook, (t))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
|
||||||
extern void (*rt_object_take_hook)(struct rt_object *object);
|
extern void (*rt_object_take_hook)(struct rt_object *object);
|
||||||
extern void (*rt_object_put_hook)(struct rt_object *object);
|
extern void (*rt_object_put_hook)(struct rt_object *object);
|
||||||
|
|
Loading…
Reference in New Issue