mqd_t mq_open()

in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_mqueue.c [494:607]


mqd_t mq_open( const char * name,
               int oflag,
               mode_t mode,
               struct mq_attr * attr )
{
    mqd_t xMessageQueue = NULL;
    size_t xNameLength = 0;

    /* Default mq_attr. */
    struct mq_attr xQueueCreationAttr =
    {
        .mq_flags   = 0,
        .mq_maxmsg  = posixconfigMQ_MAX_MESSAGES,
        .mq_msgsize = posixconfigMQ_MAX_SIZE,
        .mq_curmsgs = 0
    };

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

    /* Initialize the queue list, if needed. */
    prvInitializeQueueList();

    /* Check queue name. */
    if( prvValidateQueueName( name, &xNameLength ) == pdFALSE )
    {
        /* Invalid name. */
        errno = EINVAL;
        xMessageQueue = ( mqd_t ) -1;
    }

    /* Check attributes, if given. */
    if( xMessageQueue == NULL )
    {
        if( ( oflag & O_CREAT ) && ( attr != NULL ) && ( ( attr->mq_maxmsg <= 0 ) || ( attr->mq_msgsize <= 0 ) ) )
        {
            /* Invalid mq_attr.mq_maxmsg or mq_attr.mq_msgsize. */
            errno = EINVAL;
            xMessageQueue = ( mqd_t ) -1;
        }
    }

    if( xMessageQueue == NULL )
    {
        /* 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 );

        /* Search the queue list to check if the queue exists. */
        if( prvFindQueueInList( ( QueueListElement_t ** ) &xMessageQueue,
                                name,
                                ( mqd_t ) NULL ) == pdTRUE )
        {
            /* If the mq exists, check that this function wasn't called with
             * O_CREAT and O_EXCL. */
            if( ( oflag & O_EXCL ) && ( oflag & O_CREAT ) )
            {
                errno = EEXIST;
                xMessageQueue = ( mqd_t ) -1;
            }
            else
            {
                /* Check if the mq has been unlinked and is pending removal. */
                if( ( ( QueueListElement_t * ) xMessageQueue )->xPendingUnlink == pdTRUE )
                {
                    /* Queue pending deletion. Don't allow it to be re-opened. */
                    errno = EINVAL;
                    xMessageQueue = ( mqd_t ) -1;
                }
                else
                {
                    /* Increase count of open file descriptors for queue. */
                    ( ( QueueListElement_t * ) xMessageQueue )->xOpenDescriptors++;
                }
            }
        }
        /* Queue does not exist. */
        else
        {
            /* Only create the new queue if O_CREAT was specified. */
            if( oflag & O_CREAT )
            {
                /* Copy attributes if provided. */
                if( attr != NULL )
                {
                    xQueueCreationAttr = *attr;
                }

                /* Copy oflags. */
                xQueueCreationAttr.mq_flags = ( long ) oflag;

                /* Create the new message queue. */
                if( prvCreateNewMessageQueue( ( QueueListElement_t ** ) &xMessageQueue,
                                              &xQueueCreationAttr,
                                              name,
                                              xNameLength ) == pdFALSE )
                {
                    errno = ENOSPC;
                    xMessageQueue = ( mqd_t ) -1;
                }
            }
            else
            {
                errno = ENOENT;
                xMessageQueue = ( mqd_t ) -1;
            }
        }

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

    return xMessageQueue;
}