ssize_t mq_timedreceive()

in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_mqueue.c [631:720]


ssize_t mq_timedreceive( mqd_t mqdes,
                         char * msg_ptr,
                         size_t msg_len,
                         unsigned * msg_prio,
                         const struct timespec * abstime )
{
    ssize_t xStatus = 0;
    int iCalculateTimeoutReturn = 0;
    TickType_t xTimeoutTicks = 0;
    QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
    QueueElement_t xReceiveData = { 0 };

    /* Silence warnings about unused parameters. */
    ( void ) msg_prio;

    /* Lock the mutex that guards access to the queue list. This call will
     * never fail because it blocks forever. */
    ( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );

    /* Find the mq referenced by mqdes. */
    if( prvFindQueueInList( NULL, NULL, mqdes ) == pdFALSE )
    {
        /* Queue not found; bad descriptor. */
        errno = EBADF;
        xStatus = -1;
    }

    /* Verify that msg_len is large enough. */
    if( xStatus == 0 )
    {
        if( msg_len < ( size_t ) pxMessageQueue->xAttr.mq_msgsize )
        {
            /* msg_len too small. */
            errno = EMSGSIZE;
            xStatus = -1;
        }
    }

    if( xStatus == 0 )
    {
        /* Convert abstime to a tick timeout. */
        iCalculateTimeoutReturn = prvCalculateTickTimeout( pxMessageQueue->xAttr.mq_flags,
                                                           abstime,
                                                           &xTimeoutTicks );

        if( iCalculateTimeoutReturn != 0 )
        {
            errno = iCalculateTimeoutReturn;
            xStatus = -1;
        }
    }

    /* Release the mutex protecting the queue list. */
    ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );

    if( xStatus == 0 )
    {
        /* Receive data from the FreeRTOS queue. */
        if( xQueueReceive( pxMessageQueue->xQueue,
                           &xReceiveData,
                           xTimeoutTicks ) == pdFALSE )
        {
            /* If queue receive fails, set the appropriate errno. */
            if( pxMessageQueue->xAttr.mq_flags & O_NONBLOCK )
            {
                /* Set errno to EAGAIN for nonblocking mq. */
                errno = EAGAIN;
            }
            else
            {
                /* Otherwise, set errno to ETIMEDOUT. */
                errno = ETIMEDOUT;
            }

            xStatus = -1;
        }
    }

    if( xStatus == 0 )
    {
        /* Get the length of data for return value. */
        xStatus = ( ssize_t ) xReceiveData.xDataSize;

        /* Copy received data into given buffer, then free it. */
        ( void ) memcpy( msg_ptr, xReceiveData.pcData, xReceiveData.xDataSize );
        vPortFree( xReceiveData.pcData );
    }

    return xStatus;
}