1. 程式人生 > >建立一個訊息佇列,OSQCreate()

建立一個訊息佇列,OSQCreate()

程式清單 L6.21是OSQCreate()函式的原始碼。該函式需要一個指標陣列來容納指向各個訊息的指標。該指標陣列必須聲名為void型別。
OSQCreate()首先從空閒事件控制塊連結串列中取得一個事件控制塊(見圖F6.3)[L6.21(1)],並對剩下的空閒事件控制塊列表的指標做相應的調整,使它指向下一個空閒事件控制塊[L6.21(2)]。接著,OSQCreate()函式從空閒佇列控制塊列表中取出一個佇列控制塊[L6.21(3)]。如果有空閒佇列控制塊是可以的,就對其進行初始化[L6.21(4)]。然後該函式將事件控制塊的型別設定為OS_EVENT_TYPE_Q [L6.21(5)],並使其.OSEventPtr指標指向佇列控制塊[L6.21(6)]。OSQCreate()還要呼叫OSEventWaitListInit()函式對事件控制塊的等待任務列表初始化[見6.01節,初始化一個事件控制塊,OSEventWaitListInit()] [L6.21(7)]。因為此時訊息佇列正在初始化,顯然它的等待任務列表是空的。最後,OSQCreate()向它的呼叫函式返回一個指向事件控制塊的指標[L6.21(9)]。該指標將在呼叫OSQPend(),OSQPost(),OSQPostFront(),OSQFlush(),OSQAccept()和OSQQuery()等訊息佇列處理函式時使用。因此,該指標可以被看作是對應訊息佇列的控制代碼。值得注意的是,如果此時沒有空閒的事件控制塊,OSQCreate()函式將返回一個NULL指標。如果沒有佇列控制塊可以使用,為了不浪費事件控制塊資源,OSQCreate()函式將把剛剛取得的事件控制塊重新返還給空閒事件控制塊列表 [L6.21(8)]。
另外,訊息佇列一旦建立就不能再刪除了。試想,如果有任務正在等待某個訊息佇列中的訊息,而此時又刪除該訊息佇列,將是很危險的。

程式清單 L6.21 建立一個訊息佇列
OS_EVENT *OSQCreate (void **start, INT16U size)
{
    OS_EVENT *pevent;
    OS_Q     *pq;


    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;	                                        (1)
    if (OSEventFreeList != (OS_EVENT *)0) {
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;	   (2)
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {
        OS_ENTER_CRITICAL();
        pq = OSQFreeList;	                                            (3)
        if (OSQFreeList != (OS_Q *)0) {
            OSQFreeList = OSQFreeList->OSQPtr;
        }
        OS_EXIT_CRITICAL();
        if (pq != (OS_Q *)0) {
            pq->OSQStart        = start;	                             (4)
            pq->OSQEnd          = &start[size];
            pq->OSQIn           = start;
            pq->OSQOut          = start;
            pq->OSQSize         = size;
            pq->OSQEntries      = 0;
            pevent->OSEventType = OS_EVENT_TYPE_Q;	                   (5)
            pevent->OSEventPtr  = pq;	                                (6)
            OSEventWaitListInit(pevent);	                             (7)
        } else {
            OS_ENTER_CRITICAL();
            pevent->OSEventPtr = (void *)OSEventFreeList;	            (8)            OSEventFreeList    = pevent;
            OS_EXIT_CRITICAL();
            pevent = (OS_EVENT *)0;
        }
    }
    return (pevent);	                                                 (9)
}