1. 程式人生 > 其它 >2 rt-thread之IPC分析

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)失能中斷巢狀。