int mq_timedsend()

in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_mqueue.c [724:825]


int mq_timedsend( mqd_t mqdes,
                  const char * msg_ptr,
                  size_t msg_len,
                  unsigned int msg_prio,
                  const struct timespec * abstime )
{
    int iStatus = 0, iCalculateTimeoutReturn = 0;
    TickType_t xTimeoutTicks = 0;
    QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
    QueueElement_t xSendData = { 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;
        iStatus = -1;
    }

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

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

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

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

    /* Allocate memory for the message. */
    if( iStatus == 0 )
    {
        xSendData.xDataSize = msg_len;
        xSendData.pcData = pvPortMalloc( msg_len );

        /* Check that memory allocation succeeded. */
        if( xSendData.pcData == NULL )
        {
            /* msg_len too large. */
            errno = EMSGSIZE;
            iStatus = -1;
        }
        else
        {
            /* Copy the data to send. */
            ( void ) memcpy( xSendData.pcData, msg_ptr, msg_len );
        }
    }

    if( iStatus == 0 )
    {
        /* Send data to the FreeRTOS queue. */
        if( xQueueSend( pxMessageQueue->xQueue,
                        &xSendData,
                        xTimeoutTicks ) == pdFALSE )
        {
            /* If queue send 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;
            }

            /* Free the allocated queue data. */
            vPortFree( xSendData.pcData );

            iStatus = -1;
        }
    }

    return iStatus;
}