/*************************************************************************************************/
|
/*!
|
* \file wsf_msg.c
|
*
|
* \brief Message passing service.
|
*
|
* Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved.
|
*
|
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
/*************************************************************************************************/
|
|
#include "wsf_types.h"
|
#include "wsf_msg.h"
|
#include "wsf_assert.h"
|
#include "wsf_trace.h"
|
#include "wsf_buf.h"
|
#include "wsf_queue.h"
|
#include "wsf_os.h"
|
|
/**************************************************************************************************
|
Data Types
|
**************************************************************************************************/
|
|
/* Internal message buf structure */
|
typedef struct wsfMsg_tag
|
{
|
struct wsfMsg_tag *pNext;
|
wsfHandlerId_t handlerId;
|
} wsfMsg_t;
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Allocate a data message buffer to be sent with WsfMsgSend().
|
*
|
* \param len Message length in bytes.
|
* \param tailroom Tailroom length in bytes.
|
*
|
* \return Pointer to data message buffer or NULL if allocation failed.
|
*/
|
/*************************************************************************************************/
|
void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom)
|
{
|
return WsfMsgAlloc(len + tailroom);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Allocate a message buffer to be sent with WsfMsgSend().
|
*
|
* \param len Message length in bytes.
|
*
|
* \return Pointer to message buffer or NULL if allocation failed.
|
*/
|
/*************************************************************************************************/
|
void *WsfMsgAlloc(uint16_t len)
|
{
|
wsfMsg_t *pMsg;
|
|
pMsg = WsfBufAlloc(len + sizeof(wsfMsg_t));
|
|
/* hide header */
|
if (pMsg != NULL)
|
{
|
pMsg++;
|
}
|
|
return pMsg;
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Free a message buffer allocated with WsfMsgAlloc().
|
*
|
* \param pMsg Pointer to message buffer.
|
*/
|
/*************************************************************************************************/
|
void WsfMsgFree(void *pMsg)
|
{
|
WsfBufFree(((wsfMsg_t *)pMsg) - 1);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Send a message to an event handler.
|
*
|
* \param handlerId Event handler ID.
|
* \param pMsg Pointer to message buffer.
|
*/
|
/*************************************************************************************************/
|
void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg)
|
{
|
WSF_TRACE_MSG1("WsfMsgSend handlerId:%u", handlerId);
|
|
/* get queue for this handler and enqueue message */
|
WsfMsgEnq(WsfTaskMsgQueue(handlerId), handlerId, pMsg);
|
|
/* set task for this handler as ready to run */
|
WsfTaskSetReady(handlerId, WSF_MSG_QUEUE_EVENT);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Enqueue a message.
|
*
|
* \param pQueue Pointer to queue.
|
* \param handerId Set message handler ID to this value.
|
* \param pElem Pointer to message buffer.
|
*/
|
/*************************************************************************************************/
|
void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg)
|
{
|
wsfMsg_t *p;
|
|
WSF_ASSERT(pMsg != NULL);
|
|
/* get message header */
|
p = ((wsfMsg_t *)pMsg) - 1;
|
|
/* set handler ID */
|
p->handlerId = handlerId;
|
|
WsfQueueEnq(pQueue, p);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Dequeue a message.
|
*
|
* \param pQueue Pointer to queue.
|
* \param pHandlerId Handler ID of returned message; this is a return parameter.
|
*
|
* \return Pointer to message that has been dequeued or NULL if queue is empty.
|
*/
|
/*************************************************************************************************/
|
void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId)
|
{
|
wsfMsg_t *pMsg;
|
|
if ((pMsg = WsfQueueDeq(pQueue)) != NULL)
|
{
|
*pHandlerId = pMsg->handlerId;
|
|
/* hide header */
|
pMsg++;
|
}
|
|
return pMsg;
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Get the next message without removing it from the queue.
|
*
|
* \param pQueue Pointer to queue.
|
* \param pHandlerId Handler ID of returned message; this is a return parameter.
|
*
|
* \return Pointer to the next message on the queue or NULL if queue is empty.
|
*/
|
/*************************************************************************************************/
|
void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId)
|
{
|
wsfMsg_t *pMsg = pQueue->pHead;
|
|
if (pMsg != NULL)
|
{
|
*pHandlerId = pMsg->handlerId;
|
|
/* hide header */
|
pMsg++;
|
}
|
|
return pMsg;
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Get the Nth message without removing it from the queue.
|
*
|
* \param pQueue Pointer to queue.
|
* \param n Nth item from the top (0 = top element).
|
* \param pHandlerId Handler ID of returned message; this is a return parameter.
|
*
|
* \return Pointer to the next message on the queue or NULL if queue is empty.
|
*/
|
/*************************************************************************************************/
|
void *WsfMsgNPeek(wsfQueue_t *pQueue, uint8_t n, wsfHandlerId_t *pHandlerId)
|
{
|
wsfMsg_t *pMsg = pQueue->pHead;
|
|
while (pMsg && n--)
|
{
|
pMsg = pMsg->pNext;
|
}
|
|
if (pMsg != NULL)
|
{
|
*pHandlerId = pMsg->handlerId;
|
|
/* hide header */
|
pMsg++;
|
}
|
|
return pMsg;
|
}
|