📄 msgq.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 *)¶ms[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 *)¶ms[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 + -