⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msgq.c

📁 介绍ROCK OS操作系统.一般用于汽车电子,类似OCVX.里面是个DEMO文档,内附说明.
💻 C
字号:
/******************************************************************************
    Copyright (c) 2006 by RockOS.
    All rights reserved.

    This software is supported by the Rock Software Workroom only.

    Any bugs please contact the author with e-mail or QQ:
     E-mail : baobaoba520@yahoo.com.cn
         QQ : 59681888
*******************************************************************************
File name   : msgq.c
Description : message queue management for RockOS.
            : 
            : 
Auther      : sunxinqiu
History     :
  2006-01-31   first release.
******************************************************************************/

#include "os.h"

/******************************************************************************
Global var  : MSGQCB g_msgQCB[MAX_SYS_TASK];
Description : the msg queue's control block. In RockOS, msg queue is a private
            : resource owned by task.
******************************************************************************/
MSGQCB g_msgQCB[MAX_SYS_MSGQ];


/******************************************************************************
Function    : STATUS msgQ_init (void)
Params      : N/A
            : 
            : 
            : 
Return      : NO_ERROR or other error code.
Description : This function should only be called during system starting up.
            : 
******************************************************************************/
STATUS msgQ_init (void)
{
    HANDLE handle;

    if (g_OSRunning != OS_PHASE_INIT)
    {
        OS_error("msgQ_init(): this function can't be called after system in scheduling!!!\n");
        return OS_FAIL;
    }

    for (handle = 0; handle < MAX_SYS_MSGQ; handle++)
    {
        memset (&g_msgQCB[handle], 0, sizeof(MSGQCB));

        g_msgQCB[handle].state = OS_MSGQ_FREE;
        g_msgQCB[handle].owner = NULL_TASK;
        g_msgQCB[handle].runningPriority = LOWEST_TASK_PRIO;
    }

    return OS_SUCCESS;
}

/******************************************************************************
Function    : HMSGQ msgQCreate (HTASK owner, U32 size)
Params      : owner - the owner task.
            : total - the total msg could be contained in the msg queue.
            : 
            : 
Return      : the msg queue or NULL_HANLDE if any error.
Description : create the msg queue for task when a task is creating.
            : 
******************************************************************************/
HMSGQ msgQCreate (HTASK owner, U32 total)
{
    HANDLE handle;
    HMSGQ hMsgQ;

    U32 size;
    char name[MAX_NAME_LEN+1];

    hMsgQ = NULL_HANDLE;

    OS_ENTER_CRITICAL();
    for (handle = 0; handle < MAX_SYS_MSGQ; handle++)
    {
        if (g_msgQCB[handle].state == OS_MSGQ_FREE)
        {
            g_msgQCB[handle].state = OS_MSGQ_BUSY;
            hMsgQ = handle;
            break;
        }
    }
    OS_LEAVE_CRITICAL();

    if (hMsgQ != NULL_HANDLE)
    {
        /* msg queue's attributes. */
        g_msgQCB[hMsgQ].owner = owner;
        g_msgQCB[hMsgQ].total = total;
        g_msgQCB[hMsgQ].current = 0;

        /* build msg queue's queue. */
        size = total * sizeof(HMSG);
        g_msgQCB[hMsgQ].head = 0;
        g_msgQCB[hMsgQ].tail = 0;
        g_msgQCB[hMsgQ].pBuffer = (HMSG *)memAlloc(size, owner, "msg queue");

        /* build msg queue's pend task queue. */
        sprintf(&name[0], "msgQ %d's penders", hMsgQ);
        g_msgQCB[hMsgQ].pendTaskQ = q_create(OS_QUEUE_PRIO, MAX_SYS_TASK, owner, &name[0]);

        if ((g_msgQCB[hMsgQ].pBuffer == NULL)||(g_msgQCB[hMsgQ].pendTaskQ == NULL_QUEUE))
        {
            OS_error("msgQCreate(): fail to create msg queue for task [%d]!!!\n", owner);

            OS_ENTER_CRITICAL();
            memset (&g_msgQCB[hMsgQ], 0, sizeof(MSGQCB));
            g_msgQCB[handle].state = OS_MSGQ_FREE;
            OS_LEAVE_CRITICAL();

            hMsgQ = NULL_HANDLE;
        }
    }

    return hMsgQ;
}

/******************************************************************************
Function    : STATUS msgQSend (HTASK task, HMSG hmsg, U32 timeout)
Params      : task    - the dest task which will recive this msg.
            : hmsg    - the msg handle.
            : timeout - wait ticks for sending the message if sender is pending,
            :           zero means no waiting and return OS_FAIL immediately.
Return      : OS_SUCCESS or OS_FAIL.
Description : send a msg to dest task.
            : 
******************************************************************************/
STATUS msgQSend (HMSG hmsg, HTASK task, U32 timeout)
{
    U16   selfPriority;
    HTASK selfTask;

    HMSGQ hMsgQ;
    U32 tail;

    U16 trigger;
    STATUS nret;

    U32 params[2];

    /* params check. */
    if (task >= MAX_SYS_TASK)
    {
        OS_error("msgQSend(): task [%d] is invalid!!!\n", task);
        msgFree(hmsg);
        return OS_FAIL;
    }

    if (hmsg == NULL_HANDLE)
    {
        OS_error("msgQSend(): hmsg [%d] is invalid!!!\n", hmsg);
        msgFree(hmsg);
        return OS_FAIL;
    }

    if (g_sysTcb[task].state == OS_TASK_FREE)
    {
        OS_error("msgQSend(): dest task [%d] is free!!!\n", task);
        msgFree(hmsg);
        return OS_FAIL;
    }

    hMsgQ = g_sysTcb[task].hMsgQ;
    if (hMsgQ == NULL_HANDLE)
    {
        OS_error("msgQSend(): dest task [%d] has no msg queue!!!\n", task);
        msgFree(hmsg);
        return OS_FAIL;
    }
    if (hMsgQ >= MAX_SYS_MSGQ)
    {
        OS_error("msgQSend(): dest task [%d]'s msg queue is invlaid [%d]!!!\n", task, hMsgQ);
        msgFree(hmsg);
        return OS_FAIL;
    }

    selfTask = taskIdSelf();
    selfPriority = taskRunningPrioritySelf();

    OS_ENTER_CRITICAL();
    /* if msg queue is full. */
    if (g_msgQCB[hMsgQ].current == g_msgQCB[hMsgQ].total)
    {
        if (timeout == OS_NO_WAIT)
        {
            OS_LEAVE_CRITICAL();
            nret = OS_FAIL;
        }
        else
        {
            /* the sender task pend on this msg queue. */
            q_add (g_msgQCB[hMsgQ].pendTaskQ, (HANDLE)selfTask, selfPriority);
            OS_LEAVE_CRITICAL();

            /* change the task's priority if necessary. */
            taskSetPriorityAuto(task);

            /* pend current task. */
            params[0] = hMsgQ;
            params[1] = timeout;
            taskSetTrigger(selfTask, T_TRIG_SEND_MSGQ_PEND, (void *)&params[0]);

            OS_ENTER_CRITICAL();

            /* now the send task continue, but may be timeout or send msg successfully. */
            trigger = getCoreEvent(selfTask);
            if (trigger == OS_EVENT_DELAY_TMO)
            {
                g_sysTcb[selfTask].bWaitTimeout = OS_FALSE;
                OS_LEAVE_CRITICAL();
                taskSetPriorityAuto(task);
                nret = OS_FAIL;
            }
            else
            {
                /* add msg to msg queue. */
                tail = g_msgQCB[hMsgQ].tail;
                g_msgQCB[hMsgQ].pBuffer[tail] = hmsg;
                g_msgQCB[hMsgQ].tail = (tail + 1)%g_msgQCB[hMsgQ].total;
                g_msgQCB[hMsgQ].current++;
                setmsgState(hmsg, OS_MSG_SENT);

                OS_LEAVE_CRITICAL();
                nret = OS_SUCCESS;
            }
        }
    }
    else
    {
        /* add msg to msg queue. */
        tail = g_msgQCB[hMsgQ].tail;
        g_msgQCB[hMsgQ].pBuffer[tail] = hmsg;
        g_msgQCB[hMsgQ].tail = (tail + 1)%g_msgQCB[hMsgQ].total;
        g_msgQCB[hMsgQ].current++;

        setmsgState(hmsg, OS_MSG_SENT);
        OS_LEAVE_CRITICAL();

        /* msg send successfully(for the sender). */
        if (g_cpuIntDepth == 0)
        {
            taskSetTrigger(selfTask, T_TRIG_SEND_MSGQ_DONE, NULL);
        }

        /* msg arrived (for the reciver). */
        taskSetTrigger(task, T_TRIG_RECV_MSGQ_DONE, NULL);

        nret = OS_SUCCESS;
    }

    /* free the message if sending failure. */
    if (nret == OS_FAIL)
    {
        msgFree(hmsg);
    }
    return nret;
}

/******************************************************************************
Function    : STATUS msgQReceive (HMSG * phmsg, U32 timeout)
Params      : phmsg   - to save the msg handle.
            : timeout - wait ticks when task is pending on the msg queue.
            : 
            : 
Return      : OS_SUCCESS or OS_FAIL
Description : receive a msg from task's msg queue.
            : 
******************************************************************************/
STATUS msgQReceive (HMSG * phmsg, U32 timeout)
{
    U16   selfPriority;
    HTASK selfTask;

    HTASK pendTask;

    HMSGQ hMsgQ;
    U32 head;

    U16 trigger;
    STATUS nret;

    U32 params[2];

    if (phmsg == NULL)
    {
        OS_error("msgQReceive(): pHmsg should not be NULL!!!\n");
        return OS_FAIL;
    }

    selfTask = taskIdSelf();
    selfPriority = taskPrioritySelf();

    hMsgQ = g_runningTcb->hMsgQ;
    if (hMsgQ == NULL_HANDLE)
    {
        OS_error("msgQReceive(): current task [%d] has no msg queue!!!\n", selfTask);
        return OS_FAIL;
    }

    if (hMsgQ >= MAX_SYS_MSGQ)
    {
        OS_error("msgQReceive(): current task [%d]'s msg queue is invlaid [%d]!!!\n", selfTask, hMsgQ);
        return OS_FAIL;
    }

    OS_ENTER_CRITICAL();

    /* if msg queue is empty. */
    if (g_msgQCB[hMsgQ].current == 0)
    {
        if (timeout == OS_NO_WAIT)
        {
            OS_LEAVE_CRITICAL();
            nret = OS_FAIL;
        }
        else
        {
            OS_LEAVE_CRITICAL();
            /* now the task is pending on its own msg queue. */
            params[0] = hMsgQ;
            params[1] = timeout;
            taskSetTrigger(selfTask, T_TRIG_RECV_MSGQ_PEND, (void *)&params[0]);

            OS_ENTER_CRITICAL();

            /* now the task continue, but may be waiting timeout or a msg arrived. */
            trigger = getCoreEvent(selfTask);
            if (trigger == OS_EVENT_DELAY_TMO)
            {
                *phmsg = NULL_HANDLE;
                g_sysTcb[selfTask].bWaitTimeout = OS_FALSE;

                OS_LEAVE_CRITICAL();
                nret = OS_FAIL;
            }
            else
            {
                /* get msg from msg queue. */
                head = g_msgQCB[hMsgQ].head;
                *phmsg = g_msgQCB[hMsgQ].pBuffer[head];
                g_msgQCB[hMsgQ].head = (head+1)%g_msgQCB[hMsgQ].total;
                g_msgQCB[hMsgQ].current--;
                OS_LEAVE_CRITICAL();

                nret = OS_SUCCESS;
            }
        }
    }
    else
    {
        /* get a msg from msg queue. */
        head = g_msgQCB[hMsgQ].head;
        *phmsg = g_msgQCB[hMsgQ].pBuffer[head];
        g_msgQCB[hMsgQ].head = (head+1)%g_msgQCB[hMsgQ].total;
        g_msgQCB[hMsgQ].current--;

        /* if there are some tasks pending on this msg queue. */
        if (q_enum(g_msgQCB[hMsgQ].pendTaskQ, (HANDLE *)&pendTask) == OS_SUCCESS)
        {
            OS_LEAVE_CRITICAL();

            /* the first task is now continue. */
            taskSetTrigger(pendTask, T_TRIG_SEND_MSGQ_DONE, NULL);

            /* set the task's priority to the next task's priority*/
            taskSetPriorityAuto(selfTask);
        }
        else
        {
            OS_LEAVE_CRITICAL();
        }

        taskSetTrigger(selfTask, T_TRIG_RECV_MSGQ_DONE, NULL);
        nret = OS_SUCCESS;
    }

    return nret;
}

/******************************************************************************
Function    : STATUS msgQDestroy (HMSGQ hMsgQ)
Params      : hMsgQ - the msg queue.
            : 
            : 
            : 
Return      : OS_SUCCESS or OS_FAIL
Description : remove the msg queue when its owner task is removed.
            : 
******************************************************************************/
STATUS msgQDestroy (HMSGQ hMsgQ)
{
    if (hMsgQ >= MAX_SYS_MSGQ)
    {
        OS_error("msgQDestroy(): msg queue [%d] is invlaid!!!\n", hMsgQ);
        return OS_FAIL;
    }

    OS_ENTER_CRITICAL();
    q_destroy(g_msgQCB[hMsgQ].pendTaskQ);
    memFree(g_msgQCB[hMsgQ].pBuffer);

    memset (&g_msgQCB[hMsgQ], 0, sizeof(MSGQCB));
    g_msgQCB[hMsgQ].state = OS_MSGQ_FREE;
    g_msgQCB[hMsgQ].owner = NULL_TASK;
    OS_LEAVE_CRITICAL();

    return OS_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -