实时操作系统基本上都是通过一些链表进行线程、信号、队列的管理,RT_Thread也不例外,本章主要讲解RT_Thread的链表结构和对象管理。
本章基于RT_Thread Nano V3.1.5版本分析
1、链表
RT_Thread使用的链表非常简单,链表节点只有节点指针,各节点在实例结构体中定义,可以通过头节点定位链表,可以通过节点在结构体中的偏移定位实例结构体。
1.1 双向链表
1.1.1 链表结构
双向链表结构声明如下
struct rt_list_node
{
struct rt_list_node *next; /**< 指向下一个节点. */
struct rt_list_node *prev; /**< 指向上一个节点. */
};
双向链表通过一个头节点对整个链表管理,如下所示,NODE1为头节点,用于定位链表,NODE2~NODEn为被链表管理的节点。
双向链表主要用于对象、线程、定时器等实例管理,这些管理均需要提前设置头节点,如下所示,为系统内核定义的双链表头节点,还有一些头节点在结构体中定义,此处不再详述。
/********线程全局变量********/
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX]; // 就绪线程链表数组
extern rt_list_t rt_thread_defunct; // 失效线程链表
/* 软件定时器链表 soft timer list */
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
/* 硬件定时器 hard timer list */
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
1.1.2 链表操作
链表操作采用内联函数和宏定义的方式,可以免去操作时的环境存储与恢复,提高运行效率。操作接口主要有初始化、插入节点(表头或表尾)、删除节点。
初始化
/*节点初始化(节点指针均指向自己)*/
#define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }
/*链表头节点初始化(节点指针均指向自己)*/
rt_inline void rt_list_init(rt_list_t *l)
{
l->next = l->prev = l;
}
插入节点至表头
/*节点n插入到链表l的头部*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
l->next->prev = n;
n->next = l->next;
l->next = n;
n->prev = l;
}
NODE1为头节点,用于定位链表,NODE2~NODEn为链表管理的节点,NewNode为新插入的节点。
插入节点至表尾
/*节点n插入到链表l的尾部*/
rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
l->prev->next = n;
n->prev = l->prev;
l->prev = n;
n->next = l;
}
NODE1为头节点,用于定位链表,NODE2~NODEn为链表管理的节点,NewNode为新插入的节点。
删除节点
/*链表移除节点n*/
rt_inline void rt_list_remove(rt_list_t *n)
{
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = n->prev = n;
}
NODE1为头节点,用于定位链表,DeleteNode、NODE2~NODEn为链表管理的节点,该图为删除节点DeleteNode。
1.1.3 链表遍历
链表遍历接口采用内联函数和宏定义的方式,可以免去操作时的环境存储与恢复,提高运行效率。
链表节点多数存储在各类对象的结构体中,当遍历到一个节点时,可通过节点在结构体中的偏移获取结构体指针。所以链表本质上是对对象(结构体)的管理,因此,链表遍历不仅可以遍历节点,还可以遍历对象(结构体)。
/****判断链表条目数为空****/
rt_inline int rt_list_isempty(const rt_list_t *l)
{
return l->next == l;
}
/****获取链表长度****/
rt_inline unsigned int rt_list_len(const rt_list_t *l)
{
unsigned int len = 0;
const rt_list_t *p = l;
while (p->next != l)
{
p = p->next;
len ++;
}
return len;
}
/****遍历链表节点(pos为遍历出的节点,head为头节点)*/
#define rt_list_for_each(pos, head) \
for(pos=(head)->next;pos!= (head);pos = pos->next)
/*****遍历链表节点(安全模式,防止误删除,pos为遍历出的节点,n指向pos下个节点,head为头节点) */
#define rt_list_for_each_safe(pos, n, head) \
for(pos=(head)->next,n=pos->next; pos!=(head); pos=n, n=pos->next)
/****定位对象(根据节点定位)***/
#define rt_container_of(ptr,type,member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/****获取元素*/
#define rt_list_entry(node, type, member) rt_container_of(node, type, member)
/*****遍历对象*/
#define rt_list_for_each_entry(pos, head, member) \
for(pos=rt_list_entry((head)->next,typeof(*pos),member);&pos->member!=(head);pos = rt_list_entry(pos->member.next, typeof(*pos), member)
/******遍历对象(安全模式,防止误删除) */
#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); \
&pos->member != (head); \
pos = n, n = rt_list_entry(n->member.next, typeof(*n), member))
/*****获取链表第一个对象*/
#define rt_list_first_entry(ptr, type, member) rt_list_entry((ptr)->next, type, member)
举例,比如遍历定时器,定时器结构体和链表如下所示:
/* 软件定时器链表 */
static rt_list_t rt_soft_timer_list;
/* 定时器结构体 */
struct rt_timer
{
struct rt_object parent; /**< 基类对象*/
rt_list_t row; /**< 定时器链表节点*/
void (*timeout_func)(void *parameter); /**< 定时器函数指针 */
void *parameter; /**< 定时器函数参数*/
rt_tick_t init_tick; /**< 定时器定时时间*/
rt_tick_t timeout_tick; /**< 定时器定时时刻*/
};
typedef struct rt_timer *rt_timer_t;
/*临时定时器*/
rt_timer_t timerTemp;
定时器链表节点在定时器结构体上的内存偏移为((struct rt_timer*)(0x0)->row),假设节点n为某个定时器的链表节点,获取定时器指针方法如下:
// 直接计算
struct rt_timer* pTimer=&n-((struct rt_timer*)(0x0)->row);
// 使用系统接口
struct rt_timer* pTimer=rt_container_of(&n,struct rt_timer*,row);
假设定时器timerTemp已经插入到了链表rt_soft_timer_list中,在链表rt_soft_timer_list中定位到timerTemp的方法如下
/*在链表中定位定时器链表节点timerTemp.row*/
rt_list_for_each(&timerTemp->row, rt_soft_timer_list, row)
/*在链表中定位定时器timerTemp*/
rt_list_for_each_entry(&timerTemp, rt_soft_timer_list, row)
由上述代码可见,rt_list_for_each与rt_list_for_each_entry接口作用相同,rt_list_for_each无疑性能更优,所以内核代码中并未使用rt_list_for_each_entry,而rt_list_for_each主要用于计算节点个数或判断节点是否连接在链表。
1.2 单向链表
单向链表主要在内存池管理中使用,本章只罗列单向链表接口,其详细使用过程可以参考双向链表,二者接口相似。
1.2.1 链表结构
struct rt_slist_node
{
struct rt_slist_node *next; /**< 指向下一个节点*/
};
1.2.2 链表操作
/*****对象节点初始化(初始化被管理的节点)*****/
#define RT_SLIST_OBJECT_INIT(object) { RT_NULL }
/****链表头节点初始化***/
rt_inline void rt_slist_init(rt_slist_t *l)
{
l->next = RT_NULL;
}
/*****节点n插入到链表l的尾部*****/
rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n)
{
struct rt_slist_node *node;
node = l;
while (node->next) node = node->next;
node->next = n;
n->next = RT_NULL;
}
/*****节点n插入到链表l的头部*****/
rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)
{
n->next = l->next;
l->next = n;
}
/*****从链表l移除节点n*****/
rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)
{
struct rt_slist_node *node = l;
while (node->next && node->next != n) node = node->next;
if (node->next != (rt_slist_t *)0) node->next = node->next->next;
return l;
}
1.2.3 链表遍历
/********定位元素member所在的结构体指针,结构体类型为type**********/
#define rt_container_of(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
/******链表节点个数******/
rt_inline unsigned int rt_slist_len(const rt_slist_t *l)
{
unsigned int len = 0;
const rt_slist_t *list = l->next;
while (list != RT_NULL)
{
list = list->next;
len ++;
}
return len;
}
/*******单链表第一个节点*******/
rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l)
{
return l->next;
}
/*******单链表最后一个节点*******/
rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l)
{
while (l->next) l = l->next;
return l;
}
/*******节点n的下一个节点*******/
rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)
{
return n->next;
}
/*******单链表为空*******/
rt_inline int rt_slist_isempty(rt_slist_t *l)
{
return l->next == RT_NULL;
}
/********获取节点所在的结构体*******/
#define rt_slist_entry(node, type, member) rt_container_of(node, type, member)
/********遍历链表的节点********/
#define rt_slist_for_each(pos, head) for(pos=(head)->next; pos!=RT_NULL; pos=pos->next)
/*********遍历链表节点对应的结构体****/
#define rt_slist_for_each_entry(pos, head, member) \
for(pos=rt_slist_entry((head)->next,typeof(*pos),member); &pos->member!=(RT_NULL); \
pos=rt_slist_entry(pos->member.next,typeof(*pos),member))
/**********获取链表第一个节点对应的结构体 *********/
#define rt_slist_first_entry(ptr, type, member) rt_slist_entry((ptr)->next, type, member)
/**********获取链表最后一个节点对应的结构体*********/
#define rt_slist_tail_entry(ptr,type,member) rt_slist_entry(rt_slist_tail(ptr),type,member)
2、对象
RT_Thread操作系统为方便统一管理,采用的面相对象的思想,系统定义了内核对象(等同于C++中的基类),线程、信号、消息、内存池等继承内核对象(线程、信号、消息等同于派生类)。
2.1 内核对象结构
内核对象节点list用于链表管理,flag参数在不同对象中起着不同的含义,比如在定时器对象中表示定时器状态和定时器类型。type参数表示对象类型,见【2.2内核对象分类】。
/*基类 内核对象*/
struct rt_object
{
char name[RT_NAME_MAX]; /**< 内核对象名称 */
rt_uint8_t type; /**< 内核对象类型 */
rt_uint8_t flag; /**< 内核对象标志 */
rt_list_t list; /**< 内核对象链表节点 */
};
2.2 内核对象分类
内核结构中type元素表示对象类型,对象类型如下所示,其中【静态对象掩码】并不是一类独立对象,而是表示对象的属性,即对象是静态对象(静态存储)还是动态对象(申请动态内存存储)。例如:静态内存创建的线程,其类型为RT_Object_Class_Thread+RT_Object_Class_Static=0x81
/*对象类型枚举*/
enum rt_object_class_type
{
RT_Object_Class_Null = 0x00, /**< 未使用. */
RT_Object_Class_Thread = 0x01, /**< 线程对象. */
RT_Object_Class_Semaphore = 0x02, /**< 信号对象. */
RT_Object_Class_Mutex = 0x03, /**< 互斥对象. */
RT_Object_Class_Event = 0x04, /**< 事件对象. */
RT_Object_Class_MailBox = 0x05, /**< 邮件对象 */
RT_Object_Class_MessageQueue = 0x06, /**< 消息对象. */
RT_Object_Class_MemHeap = 0x07, /**< 内存堆对象. */
RT_Object_Class_MemPool = 0x08, /**< 内存池对象. */
RT_Object_Class_Device = 0x09, /**< 设备驱动对象. */
RT_Object_Class_Timer = 0x0a, /**< 定时器对象. */
RT_Object_Class_Unknown = 0x0c, /**< 未知对象. */
RT_Object_Class_Static = 0x80 /**< 静态对象掩码. */
};
2.3 内核对象容器
内核对象容器,主要通过双向链表管理对象,其结构体中的链表节点即为链表头节点。
对象容器结构体
struct rt_object_information
{
enum rt_object_class_type type; /**< 对象类型 */
rt_list_t object_list; /**< 对象链表 */
rt_size_t object_size; /**< 对象大小 */
};
对象容器定义
通过定义可见,对象容器是一数组,可根据宏定义自动裁剪。
/*对象容器枚举*/
enum rt_object_info_type
{
RT_Object_Info_Thread = 0, /**< 线程对象. */
#ifdef RT_USING_SEMAPHORE
RT_Object_Info_Semaphore, /**< 信号对象. */
#endif
#ifdef RT_USING_MUTEX
RT_Object_Info_Mutex, /**< 互斥对象. */
#endif
#ifdef RT_USING_EVENT
RT_Object_Info_Event, /**< 事件对象 */
#endif
#ifdef RT_USING_MAILBOX
RT_Object_Info_MailBox, /**< 邮件对象 */
#endif
#ifdef RT_USING_MESSAGEQUEUE
RT_Object_Info_MessageQueue, /**< 消息对象. */
#endif
#ifdef RT_USING_MEMHEAP
RT_Object_Info_MemHeap, /**< 堆对象*/
#endif
#ifdef RT_USING_MEMPOOL
RT_Object_Info_MemPool, /**< 内存池对象. */
#endif
#ifdef RT_USING_DEVICE
RT_Object_Info_Device, /**< 驱动对象 */
#endif
RT_Object_Info_Timer, /**< 定时器对象 */
RT_Object_Info_Unknown, /**< 未知对象. */
};
// 对象监视器初始化(指针指向自己)
#define _OBJ_CONTAINER_LIST_INIT(c) \
{&(rt_object_container[c].object_list),&(rt_object_container[c].object_list)}
// 对象容器
static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
{
/* 初始化对象容器(线程) */
{RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
#ifdef RT_USING_SEMAPHORE
/* 初始化对象容器(信号) */
{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
#endif
#ifdef RT_USING_MUTEX
/* 初始化对象容器(互斥信号) */
{RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
#endif
#ifdef RT_USING_EVENT
/* 初始化对象容器(事件) */
{RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
#endif
#ifdef RT_USING_MAILBOX
/* 初始化对象容器(邮件) */
{RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
#endif
#ifdef RT_USING_MESSAGEQUEUE
/* 初始化对象容器(队列) */
{RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
#endif
#ifdef RT_USING_MEMHEAP
/* 初始化对象容器(内存堆) */
{RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
#endif
#ifdef RT_USING_MEMPOOL
/* 初始化对象容器(内存池) */
{RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
#endif
#ifdef RT_USING_DEVICE
/* 初始化对象容器(驱动) */
{RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
#endif
/* 初始化对象容器(定时器) */
{RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
};
对象容器管理图示,容器有2个线程对象。
2.4 内核对象继承
线程、信号、互斥等对象的结构体,第一个成员必须是内核对象,等同于C++的public继承;如下例所示:
2.5 内核对象操作
/*系统对象(静态对象)初始化*/
void rt_system_object_init(void){}
/*获取对象所在的容器(依据类型枚举)*/
struct rt_object_information *rt_object_get_information(enum rt_object_class_type type)
{
int index;
for (index = 0; index < RT_Object_Info_Unknown; index ++)
if (rt_object_container[index].type == type) return &rt_object_container[index];
return RT_NULL;
}
/*获取对象所在链表长度,既同类对象个数 (依据类型枚举)*/
int rt_object_get_length(enum rt_object_class_type type)
{
int count = 0;
rt_ubase_t level;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;
information = rt_object_get_information((enum rt_object_class_type)type);
if (information == RT_NULL) return 0;
// 进入临界区
level = rt_hw_interrupt_disable();
/*计算有效对象个数*/
rt_list_for_each(node, &(information->object_list))
{
count ++;
}
// 退出临界区
rt_hw_interrupt_enable(level);
return count;
}
/* 复制type类型的对象指针至pointers中,最大maxlen个*/
int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
{
int index = 0;
rt_ubase_t level;
struct rt_object *object;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;
if (maxlen <= 0) return 0;
// 获取对应容器
information = rt_object_get_information((enum rt_object_class_type)type);
if (information == RT_NULL) return 0;
// 进入临界区
level = rt_hw_interrupt_disable();
/* 检索节点,并复制对象指针*/
rt_list_for_each(node, &(information->object_list))
{
/*根据节点获取对象指针*/
object = rt_list_entry(node, struct rt_object, list);
pointers[index] = object;
index ++;
if (index >= maxlen) break;
}
// 退出临界区
rt_hw_interrupt_enable(level);
return index;
}
/*初始化静态内核对象 */
void rt_object_init(struct rt_object *object,
enum rt_object_class_type type,
const char *name)
{
register rt_base_t temp;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information;
/*获取对象容器*/
information = rt_object_get_information(type);
RT_ASSERT(information != RT_NULL);
/* 退出线程调度*/
rt_enter_critical();
/* 检查对象,避免重复初始化*/
for(node=information->object_list.next;node!=&(information->object_list);node=node->next)
{
struct rt_object *obj;
obj = rt_list_entry(node, struct rt_object, list);
if (obj)
{
/*检查是否存在重复初始化*/
RT_ASSERT(obj != object);
}
}
/* 恢复线程调度*/
rt_exit_critical();
/* 设置静态标识*/
object->type = type | RT_Object_Class_Static;
/* 设置名称 */
rt_strncpy(object->name, name, RT_NAME_MAX);
/* 对象新增函数调用钩子*/
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
/* 进入临界区lock interrupt */
temp = rt_hw_interrupt_disable();
/*对象插入值链表头部*/
rt_list_insert_after(&(information->object_list), &(object->list));
/* 退出临界区*/
rt_hw_interrupt_enable(temp);
}
/*移除静态内核对象*/
void rt_object_detach(rt_object_t object)
{
register rt_base_t temp;
/* 断言*/
RT_ASSERT(object != RT_NULL);
/* 执行对象移除钩子 */
RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
/*清除对象类型*/
object->type = 0;
/* 进入临界区*/
temp = rt_hw_interrupt_disable();
/* 从链表 移除对象*/
rt_list_remove(&(object->list));
/* 退出临界区 */
rt_hw_interrupt_enable(temp);
}
/*初始化动态内核对象(依据类型分配)*/
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
{
struct rt_object *object;
register rt_base_t temp;
struct rt_object_information *information;
/*中断断言*/
RT_DEBUG_NOT_IN_INTERRUPT;
/* 获取对象容器*/
information = rt_object_get_information(type);
//断言
RT_ASSERT(information != RT_NULL);
/*动态内存申请*/
object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
if (object == RT_NULL)
{
/*动态内存申请失败*/
return RT_NULL;
}
/* 动态内存初始化为0*/
rt_memset(object, 0x0, information->object_size);
/* 设置对象类型 */
object->type = type;
/* 清除对象标志 */
object->flag = 0;
/* 设置名称 */
rt_strncpy(object->name, name, RT_NAME_MAX);
/* 执行钩子 */
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
/* 进入临界区*/
temp = rt_hw_interrupt_disable();
/* 插入对象至管理器链表头部*/
rt_list_insert_after(&(information->object_list), &(object->list));
/* 退出临界区*/
rt_hw_interrupt_enable(temp);
/* 返回对象指针*/
return object;
}
/**删除并释放动态对象*/
void rt_object_delete(rt_object_t object)
{
register rt_base_t temp;
/* 断言 */
RT_ASSERT(object != RT_NULL);
RT_ASSERT(!(object->type & RT_Object_Class_Static));
RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
/* 清除类型 */
object->type = RT_Object_Class_Null;
/* 进入临界区 */
temp = rt_hw_interrupt_disable();
/* 从链表移除*/
rt_list_remove(&(object->list));
/* 退出临界区*/
rt_hw_interrupt_enable(temp);
/* 释放对象内存 */
RT_KERNEL_FREE(object);
}
#endif
/**检查对象类型是否为系统类型(静态类型)*/
rt_bool_t rt_object_is_systemobject(rt_object_t object)
{
/* 对象断言*/
RT_ASSERT(object != RT_NULL);
if (object->type & RT_Object_Class_Static)
return RT_TRUE;
return RT_FALSE;
}
/**获取对象类型*/
rt_uint8_t rt_object_get_type(rt_object_t object)
{
/*断言*/
RT_ASSERT(object != RT_NULL);
return object->type & ~RT_Object_Class_Static;
}
/*查找对象(name对象名称,type对象类型,依据对象名称和类型,该函数不能在中断调用)*/
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
{
struct rt_object *object = RT_NULL;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;
/*获取对象容器*/
information = rt_object_get_information((enum rt_object_class_type)type);
/* 参数检查 */
if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
/* which is invoke in interrupt status */
RT_DEBUG_NOT_IN_INTERRUPT;
/* 退出线程调度*/
rt_enter_critical();
/* 遍历对象节点 */
rt_list_for_each(node, &(information->object_list))
{
/*获取对象*/
object = rt_list_entry(node, struct rt_object, list);
/*判断对象*/
if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
{
/* 恢复线程调度*/
rt_exit_critical();
return object;
}
}
/* 恢复线程调度 */
rt_exit_critical();
return RT_NULL;
}
2.6 内核对象钩子
操作系统通过钩子(函数指针)给用户侧提供调试、监视或其他用途的接口,这些接口分布在对象操作的重要位置,用户侧可以根据需求选配使用。
/*****对象钩子*****/
static void (*rt_object_attach_hook)(struct rt_object *object); // 对象增加调用钩子
static void (*rt_object_detach_hook)(struct rt_object *object); // 对象移除调用钩子
void (*rt_object_trytake_hook)(struct rt_object *object); // 对象将被占用调用钩子
void (*rt_object_take_hook)(struct rt_object *object); // 对象已经被占用调用钩子
void (*rt_object_put_hook)(struct rt_object *object); // 对象被释放调用钩子
/*****对象动态增加调用钩子设置*****/
void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
{
rt_object_attach_hook = hook;
}
/*****对象移除调用钩子设置*****/
void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
{
rt_object_detach_hook = hook;
}
/*****对象将要占用调用钩子设置,主要应用于信号、互斥信号、事件、邮件、消息队列将要阻塞线程时*****/
void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
{
rt_object_trytake_hook = hook;
}
/*****对象已经占用调用钩子设置,主要应用于信号、互斥信号、事件、邮件、消息队列、定时器返回线程,检测阻塞***/
void rt_object_take_sethook(void (*hook)(struct rt_object *object))
{
rt_object_take_hook = hook;
}
/****对象释放调用钩子设置,比如消息对象发送消息,释放线程****/
void rt_object_put_sethook(void (*hook)(struct rt_object *object))
{
rt_object_put_hook = hook;
}