当前位置: 首页 > news >正文

RT_Thread内核源码分析(二)——链表和对象管理

       

目录

1、链表

1.1 双向链表

1.1.1 链表结构

1.1.2 链表操作

1.1.3 链表遍历

1.2 单向链表

1.2.1 链表结构 

1.2.2 链表操作

1.2.3 链表遍历

2、对象

2.1 内核对象结构

2.2 内核对象分类

2.3 内核对象容器

2.4 内核对象继承 

2.5 内核对象操作

2.6 内核对象钩子


         实时操作系统基本上都是通过一些链表进行线程、信号、队列的管理,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_SEMAPHORERT_Object_Info_Semaphore,                          /**< 信号对象. */
#endif
#ifdef RT_USING_MUTEXRT_Object_Info_Mutex,                              /**< 互斥对象. */
#endif
#ifdef RT_USING_EVENTRT_Object_Info_Event,                              /**< 事件对象 */
#endif
#ifdef RT_USING_MAILBOXRT_Object_Info_MailBox,                            /**< 邮件对象 */
#endif
#ifdef RT_USING_MESSAGEQUEUERT_Object_Info_MessageQueue,                       /**< 消息对象. */
#endif
#ifdef RT_USING_MEMHEAPRT_Object_Info_MemHeap,                            /**< 堆对象*/
#endif
#ifdef RT_USING_MEMPOOLRT_Object_Info_MemPool,                            /**< 内存池对象. */
#endif
#ifdef RT_USING_DEVICERT_Object_Info_Device,                             /**< 驱动对象 */
#endifRT_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;
}

相关文章:

  • 2024.9.27 Python面试八股文
  • Linux权限解析
  • 自学网络安全(黑客技术)2024年 90天学习计划
  • 微信小程序加载H5页面及与H5页面通信的实战教程
  • 多旋翼无人机“仿鸟类”精确拦截飞行目标,助力低空安全
  • 鹏哥C语言55-57---二维数组+数组越界+数组传参(冒泡排序)
  • 婚恋交友小程序的设计思路与用户体验优化
  • JavaScript 从事件处理入手的优化
  • 《征服数据结构》哈夫曼树(Huffman Tree)
  • 鸿蒙开发(NEXT/API 12)【硬件(外设扩展驱动开发)】驱动开发服务
  • 【百日算法计划】:每日一题,见证成长(021)
  • IP地址如何与网络虚拟化技术融合?
  • AQS为什么采用双向链表
  • Linux 块设备开发学习
  • 8个前端小程序开发框架的介绍
  • 【Amaple教程】5. 插件
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • github指令
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • opencv python Meanshift 和 Camshift
  • React中的“虫洞”——Context
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 关于extract.autodesk.io的一些说明
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • Spring Batch JSON 支持
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • 湖北分布式智能数据采集方法有哪些?
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • ​油烟净化器电源安全,保障健康餐饮生活
  • #1014 : Trie树
  • #pragma 指令
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (done) 声音信号处理基础知识(2) (重点知识:pitch)(Sound Waveforms)
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (四)JPA - JQPL 实现增删改查
  • (一)插入排序
  • .net 7 上传文件踩坑
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET 设计模式初探
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .NET开源、简单、实用的数据库文档生成工具
  • .Net中间语言BeforeFieldInit
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @Slf4j idea标红Cannot resolve symbol ‘log‘
  • @SpringBootApplication 注解