2 rt-thread之IPC分析
技術標籤:RT-Thread
歡迎來到 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)失能中斷巢狀。