Example #1
0
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;
}
Example #2
0
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);
                    }
                }
            }