📄 msgq.c
字号:
/*********************************************************************
* Copyright (c) 2011-2012,李士伟
* All rights reserved.
*文 件 名:msgq.c
*描 述:消息队列源文件
*当前版本:V1.00
*作 者:李士伟
*创建日期:2012.01.21
**********************************************************************/
#include <kernel\msgq.h>
#include <kernel\flag.h>
#include <kernel\sched.h>
#include <kernel\kd.h>
#include <kernel\asm.h>
#include <mm\memory.h>
/*********************************************************************
*函 数 名:API_CreateMsgQ
*描 述:创建一个消息队列
*输入参数:q_size: 消息队列可存储消息数
*输出参数:无
*返 回 值:消息队列指针
*注 意:
**********************************************************************/
OS_MSGQ *API_CreateMsgQ(INT32U q_size)
{
OS_MSGQ *pq;
pq = (OS_MSGQ *)malloc(sizeof(OS_MSGQ)+ sizeof(void *) * q_size);
if (pq == NULL)
{
return NULL;
}
pq->QStart = (void **)((INT32U)pq + sizeof(OS_MSGQ));
pq->QEnd = pq->QStart + q_size - 1;
pq->QOut = pq->QStart;
pq->QIn = pq->QStart;
pq->QSize = q_size;
pq->QCount = 0;
pq->WaitQ = NULL;
return pq;
}
/*********************************************************************
*函 数 名:API_DeleteMsgQ
*描 述:删除消息队列
*输入参数:pq: 消息队列指针
*输出参数:无
*返 回 值:0,删除失败;1,删除成功
*注 意:
**********************************************************************/
INT32U API_DeleteMsgQ(OS_MSGQ *pq)
{
if (pq == NULL)
{
return 0;
}
OS_ENTER_CRITICAL();
if (pq->WaitQ != NULL)
{
OS_EXIT_CRITICAL();
return 0;
}
free(pq);
OS_EXIT_CRITICAL();
return 1;
}
/*********************************************************************
*函 数 名:API_MsgQPend
*描 述:请求消息队列
*输入参数:pq: 消息队列指针
* timeout:等待时限
*输出参数:err: 错误标志
*返 回 值:消息指针,NULL表示未获得消息
*注 意:
**********************************************************************/
void *API_MsgQPend(OS_MSGQ *pq, INT32U timeout, INT32U *err)
{
void *msg = NULL;
if ((pq == NULL) || (OSIntNesting > 0))
{
*err = OS_ERR;
return NULL;
}
OS_ENTER_CRITICAL();
if (pq->QCount > 0)
{
msg = *(pq->QOut++);
pq->QCount--;
if (pq->QOut > pq->QEnd)
{
pq->QOut = pq->QStart;
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return msg;
}
OSTCBCur->Delay = timeout;
OS_EnterWaitQHead(&(pq->WaitQ), OSTCBCur);
OS_Sched();
if (OSTCBCur->MsgPtr != NULL) /* 获得消息 */
{
msg = OSTCBCur->MsgPtr; /* 获得消息指针 */
OSTCBCur->MsgPtr = NULL; /* 清除TCB消息指针,为下次等待消息准备 */
OSTCBCur->Delay = 0; /* 清除等待时限 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return msg;
}
/* 超时,未获得消息 */
OS_EXIT_CRITICAL();
*err = OS_OVERTIME;
return NULL;
}
/*********************************************************************
*函 数 名:API_MsgQAccept
*描 述:无等待获得消息
*输入参数:pq: 消息队列指针
*输出参数:无
*返 回 值:消息指针,NULL表示未获得消息
*注 意:
**********************************************************************/
void *API_MsgQAccept(OS_MSGQ *pq)
{
void *msg = NULL;
if (pq == NULL)
{
return NULL;
}
OS_ENTER_CRITICAL();
if (pq->QCount > 0)
{
msg = *(pq->QOut++);
pq->QCount--;
if (pq->QOut > pq->QEnd)
{
pq->QOut = pq->QStart;
}
OS_EXIT_CRITICAL();
return msg;
}
OS_EXIT_CRITICAL();
return msg;
}
/*********************************************************************
*函 数 名:API_MsgQPost
*描 述:发送消息到队尾
*输入参数:pq: 消息队列指针
* msg: 消息指针
* method: 发送方式
* OS_BASE_PRIO 基于优先级方式发送
* OS_BASE_BROADCAST 广播方式发送
*输出参数:无
*返 回 值:OS_MSGQ_INVALID 消息队列不存在,无效
* OS_MSGQ_FULL 消息队列已满,发送失败
* OS_MSGQ_SAVE 没有任务在等待消息,消息存入队列
* OS_MSGQ_SEND 消息发送到任务
*注 意:
**********************************************************************/
INT32U API_MsgQPost(OS_MSGQ *pq, void *msg, INT32U method)
{
INT32U prio = 0;
OS_TCB *ptcb;
OS_TCB *wptcb=NULL;
if (pq == NULL)
{
return OS_MSGQ_INVALID;
}
OS_ENTER_CRITICAL();
ptcb = pq->WaitQ;
wptcb = ptcb;
if (ptcb != NULL) /* 有任务在等待消息 */
{
prio = ptcb->Prio;
}
else /* 没有任务在等待消息 */
{
if (pq->QCount == pq->QSize) /* 消息队列已满, 不保存消息 */
{
OS_EXIT_CRITICAL();
return OS_MSGQ_FULL;
}
else /* 消息未满,将消息存入队列尾部 */
{
*(pq->QIn++) = msg;
if (pq->QIn > pq->QEnd)
{
pq->QIn = pq->QStart;
}
pq->QCount++;
OS_EXIT_CRITICAL();
return OS_MSGQ_SAVE;
}
}
/* 基于优先级发送消息给一个高优先级任务 */
if (method == OS_BASE_PRIO)
{
while (ptcb != NULL) /* 从等待队列查询一个高优先级任务 */
{
if (prio <= ptcb->Prio)
{
prio = ptcb->Prio;
wptcb= ptcb;
}
ptcb = ptcb->QNext;
}
wptcb->MsgPtr = msg; /* 将消息指针存入TCB中 */
OS_EnterRunQ(wptcb); /* 加入运行队列 */
}
/* 广播方式唤醒所有等待该消息队列的任务 */
else if (method == OS_BASE_BROADCAST)
{
while (ptcb != NULL)
{
ptcb->MsgPtr = msg; /* 将消息指针存入TCB中 */
wptcb = ptcb->QNext;
OS_EnterRunQ(ptcb); /* 加入运行队列 */
ptcb = wptcb;
}
}
OS_EXIT_CRITICAL();
OS_Sched();
return OS_MSGQ_SEND;
}
/*********************************************************************
*函 数 名:API_MsgQPostFront
*描 述:发送消息到队首
*输入参数:pq: 消息队列指针
* msg: 消息指针
* method: 发送方式
* OS_BASE_PRIO 基于优先级方式发送
* OS_BASE_BROADCAST 广播方式发送
*输出参数:无
*返 回 值:OS_MSGQ_INVALID 消息队列不存在,无效
* OS_MSGQ_FULL 消息队列已满,发送失败
* OS_MSGQ_SAVE 没有任务在等待消息,消息存入队列
* OS_MSGQ_SEND 消息发送到任务
*注 意:
**********************************************************************/
INT32U API_MsgQPostFront(OS_MSGQ *pq, void *msg, INT32U method)
{
INT32U prio = 0;
OS_TCB *ptcb;
OS_TCB *wptcb=NULL;
if (pq == NULL)
{
return OS_MSGQ_INVALID;
}
OS_ENTER_CRITICAL();
ptcb = pq->WaitQ;
wptcb = ptcb;
if (ptcb != NULL) /* 有任务在等待消息 */
{
prio = ptcb->Prio;
}
else /* 没有任务在等待消息 */
{
if (pq->QCount == pq->QSize) /* 消息队列已满, 不保存消息 */
{
OS_EXIT_CRITICAL();
return OS_MSGQ_FULL;
}
else /* 消息未满,将消息存入队列首部 */
{
if (pq->QOut == pq->QStart)
{
pq->QOut = pq->QEnd;
}
else
{
--(pq->QOut);
}
*(pq->QOut) = msg;
pq->QCount++;
OS_EXIT_CRITICAL();
return OS_MSGQ_SAVE;
}
}
/* 基于优先级发送消息给一个高优先级任务 */
if (method == OS_BASE_PRIO)
{
while (ptcb != NULL) /* 从等待队列查询一个高优先级任务 */
{
if (prio <= ptcb->Prio)
{
prio = ptcb->Prio;
wptcb= ptcb;
}
ptcb = ptcb->QNext;
}
wptcb->MsgPtr = msg; /* 将消息指针存入TCB中 */
OS_EnterRunQ(wptcb); /* 加入运行队列 */
}
/* 广播方式唤醒所有等待该消息队列的任务 */
else if (method == OS_BASE_BROADCAST)
{
while (ptcb != NULL)
{
ptcb->MsgPtr = msg; /* 将消息指针存入TCB中 */
wptcb = ptcb->QNext;
OS_EnterRunQ(ptcb); /* 加入运行队列 */
ptcb = wptcb;
}
}
OS_EXIT_CRITICAL();
OS_Sched();
return OS_MSGQ_SEND;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -