mqd_t mq_open(FAR const char *mq_name, int oflags, ...) { FAR struct inode *inode; FAR const char *relpath = NULL; FAR struct mqueue_inode_s *msgq; char fullpath[MAX_MQUEUE_PATH]; va_list ap; struct mq_attr *attr; mqd_t mqdes; mode_t mode; int errcode; int ret; /* Make sure that a non-NULL name is supplied */ if (!mq_name) { errcode = EINVAL; goto errout; } /* Get the full path to the message queue */ snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name); /* Make sure that the check for the existence of the message queue * and the creation of the message queue are atomic with respect to * other processes executing mq_open(). A simple sched_lock() should * be sufficient. */ sched_lock(); /* Get the inode for this mqueue. This should succeed if the message * queue has already been created. */ inode = inode_find(fullpath, &relpath); if (inode) { /* It exists. Verify that the inode is a message queue */ if (!INODE_IS_MQUEUE(inode)) { errcode = ENXIO; goto errout_with_inode; } /* It exists and is a message queue. Check if the caller wanted to * create a new mqueue with this name. */ if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) { errcode = EEXIST; goto errout_with_inode; } /* Create a message queue descriptor for the current thread */ msgq = inode->u.i_mqueue; mqdes = mq_descreate(NULL, msgq, oflags); if (!mqdes) { errcode = ENOMEM; goto errout_with_inode; } } else { /* The mqueue does not exists. Were we asked to create it? */ if ((oflags & O_CREAT) == 0) { /* The mqueue does not exist and O_CREAT is not set */ errcode = ENOENT; goto errout_with_lock; } /* Create the mqueue. First we have to extract the additional * parameters from the variable argument list. */ va_start(ap, oflags); mode = va_arg(ap, mode_t); attr = va_arg(ap, FAR struct mq_attr*); va_end(ap); /* Create an inode in the pseudo-filesystem at this path */ inode_semtake(); ret = inode_reserve(fullpath, &inode); inode_semgive(); if (ret < 0) { errcode = -ret; goto errout_with_lock; } /* Allocate memory for the new message queue. */ msgq = (FAR struct mqueue_inode_s*)mq_msgqalloc(mode, attr); if (!msgq) { errcode = ENOSPC; goto errout_with_inode; } /* Create a message queue descriptor for the TCB */ mqdes = mq_descreate(NULL, msgq, oflags); if (!mqdes) { errcode = ENOMEM; goto errout_with_msgq; } /* Bind the message queue and the inode structure */ INODE_SET_MQUEUE(inode); inode->u.i_mqueue = msgq; msgq->inode = inode; } sched_unlock(); return mqdes; errout_with_msgq: mq_msgqfree(msgq); inode->u.i_mqueue = NULL; errout_with_inode: inode_release(inode); errout_with_lock: sched_unlock(); errout: set_errno(errcode); return (mqd_t)ERROR; }
mqd_t mq_open(const char *mq_name, int oflags, ...) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; FAR msgq_t *msgq; mqd_t mqdes = NULL; va_list arg; /* Points to each un-named argument */ struct mq_attr *attr; /* MQ creation attributes */ int namelen; /* Length of MQ name */ /* Make sure that a non-NULL name is supplied */ if (mq_name) { sched_lock(); namelen = strlen(mq_name); if (namelen > 0) { /* See if the message queue already exists */ msgq = mq_findnamed(mq_name); if (msgq) { /* It does. Check if the caller wanted to create a new * message queue with this name (i.e., O_CREAT|O_EXCL) */ if ((oflags & O_CREAT) == 0 || (oflags & O_EXCL) == 0) { /* Create a message queue descriptor for the TCB */ mqdes = mq_descreate(rtcb, msgq, oflags); if (mqdes) { /* Allow a new connection to the message queue */ msgq->nconnect++; } } } /* It doesn't exist. Should we create one? */ else if ((oflags & O_CREAT) != 0) { /* Allocate memory for the new message queue. The size to * allocate is the size of the msgq_t header plus the size * of the message queue name+1. */ msgq = (FAR msgq_t*)kmm_zalloc(SIZEOF_MQ_HEADER + namelen + 1); if (msgq) { /* Create a message queue descriptor for the TCB */ mqdes = mq_descreate(rtcb, msgq, oflags); if (mqdes) { /* Set up to get the optional arguments needed to create * a message queue. */ va_start(arg, oflags); (void)va_arg(arg, mode_t); /* MQ creation mode parameter (ignored) */ attr = va_arg(arg, struct mq_attr*); /* Initialize the new named message queue */ sq_init(&msgq->msglist); if (attr) { msgq->maxmsgs = (int16_t)attr->mq_maxmsg; if (attr->mq_msgsize <= MQ_MAX_BYTES) { msgq->maxmsgsize = (int16_t)attr->mq_msgsize; } else { msgq->maxmsgsize = MQ_MAX_BYTES; } } else { msgq->maxmsgs = MQ_MAX_MSGS; msgq->maxmsgsize = MQ_MAX_BYTES; } msgq->nconnect = 1; #ifndef CONFIG_DISABLE_SIGNALS msgq->ntpid = INVALID_PROCESS_ID; #endif strcpy(msgq->name, mq_name); /* Add the new message queue to the list of * message queues */ sq_addlast((FAR sq_entry_t*)msgq, &g_msgqueues); /* Clean-up variable argument stuff */ va_end(arg); } else { /* Deallocate the msgq structure. Since it is * uninitialized, mq_deallocate() is not used. */ sched_kfree(msgq); } } }