欢迎来到 rt-thread 学习园地
———————————————————————————————————————————————
IPC定义
/**
* Base structure of IPC object
*/
struct zs_ipc_object
{
struct zs_object parent; ///< inherit from rt_object
zs_list_t suspend_thread; ///< threads pended on this resource
};
IPC初始化
/**
* This function will initialize an IPC object
*
* @param ipc the IPC object
*
* @return the operation status, ZS_EOK on successful
*/
zs_inline zs_err_t zs_ipc_object_init(struct zs_ipc_object *ipc)
{
/* initialize ipc object */
zs_list_init(&(ipc->suspend_thread)); ///> (1)
return ZS_EOK;
}
代码段 (1):初始化一个ipc双向链表,首地址指向 ipc->suspend_thread。
在IPC总线上挂起线程
/**
* This function will suspend a thread to a specified list. IPC object or some
* double-queue object (mailbox etc.) contains this kind of list.
*
* @param list the IPC suspended thread list
* @param thread the thread object to be suspended
* @param flag the IPC object flag,
* which shall be RT_IPC_FLAG_FIFO/RT_IPC_FLAG_PRIO.
*
* @return the operation status, RT_EOK on successful
*/
rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list,
struct rt_thread *thread,
rt_uint8_t flag)
{
/* suspend thread */
rt_thread_suspend(thread); ///> (1)
switch (flag)
{
case RT_IPC_FLAG_FIFO: ///> (2)
rt_list_insert_before(list, &(thread->tlist)); ///> (3)
break;
case RT_IPC_FLAG_PRIO: ///> (4)
{
struct rt_list_node *n;
struct rt_thread *sthread;
/* find a suitable position */
for (n = list->next; n != list; n = n->next)
{
sthread = rt_list_entry(n, struct rt_thread, tlist); ///> (5)
/* find out */
if (thread->current_priority < sthread->current_priority) ///> (6)
{
/* insert this thread before the sthread */
rt_list_insert_before(&(sthread->tlist), &(thread->tlist));
break;
}
}
/*
* not found a suitable position,
* append to the end of suspend_thread list
*/
if (n == list) ///> (7)
rt_list_insert_before(list, &(thread->tlist)); ///> (8)
}
break;
}
return RT_EOK;
}
代码段(1):挂起线程。
代码段(2):使用 RT_IPC_FLAG_FIFO 先进先出 flag创建的 IPC 对象,在多个线程等待资源时,将按照先来先得的顺序获得资源。
代码段(3):在 例如 sem对象的 sem->parent.suspend_thread 插入 当前线程的链表节点。
代码段(4):使用 RT_IPC_FLAG_PRIO 优先级 flag 创建的 IPC 对象,在多个线程等待资源时,将由优先级高的线程优先获得资源。
代码段(5):根据结构体成员,找到当前线程结构体首地址。
代码段(6):如果 thread 的优先级小于 sthread 的优先级,将 thread 插入到 sthread 的前面。
代码段(7):如果 list 地址等于 list->next 地址,表示 例如 sem对象的 sem->parent.suspend_thread 没有合适的位置插入。就将例如 sem对象的 sem->parent.suspend_thread插入在链表最前面。
解挂在IPC上的线程
/**
* This function will resume the first thread in the list of a IPC object:
* - remove the thread from suspend queue of IPC object
* - put the thread into system ready queue
*
* @param list the thread list
*
* @return the operation status, RT_EOK on successful
*/
rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list)
{
struct rt_thread *thread;
/* get thread entry */
thread = rt_list_entry(list->next, struct rt_thread, tlist); ///> (1)
/* resume it */
rt_thread_resume(thread); ///> (2)
return RT_EOK;
}
代码段(1):根据 例如 sem 对象的 sem->parent.suspend_thread ,确定当前线程的结构体地址。
代码段(2):从挂起的队列中移除,插入到就绪的列表中。
解挂在IPC上的所有线程
/**
* This function will resume all suspended threads in a list, including
* suspend list of IPC object and private list of mailbox etc.
*
* @param list of the threads to resume
*
* @return the operation status, RT_EOK on successful
*/
rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
{
struct rt_thread *thread;
register rt_ubase_t temp;
/* wakeup all suspended threads */
while (!rt_list_isempty(list)) ///> (1)
{
/* disable interrupt */
temp = rt_hw_interrupt_disable(); ///> (2)
/* get next suspended thread */
thread = rt_list_entry(list->next, struct rt_thread, tlist); ///> (3)
/* set error code to RT_ERROR */
thread->error = -RT_ERROR;
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
* suspended list
*/
rt_thread_resume(thread); ///> (4)
/* enable interrupt */
rt_hw_interrupt_enable(temp); ///> (5)
}
return RT_EOK;
}
代码段:(1)检查例如 sem 对象的 sem->parent.suspend_thread 挂起列表是否为空,不为空继续执行 while 内数据。
代码段:(2)使能中断嵌套。
代码段:(3)根据 例如 sem 对象的 sem->parent.suspend_thread ,确定当前线程的结构体地址。
代码段:(4)从挂起的队列中移除,插入到就绪的列表中。
spend_thread 挂起列表是否为空,不为空继续执行 while 内数据。
代码段:(2)使能中断嵌套。
代码段:(3)根据 例如 sem 对象的 sem->parent.suspend_thread ,确定当前线程的结构体地址。
代码段:(4)从挂起的队列中移除,插入到就绪的列表中。
代码段:(5)失能中断嵌套。