Пример #1
0
void mq_inode_release(FAR struct inode *inode)
{
  /* Decrement the reference count on the inode */

  inode_semtake();
  if (inode->i_crefs > 0)
    {
      inode->i_crefs--;
    }

  /* If the message queue was previously unlinked and the reference count
   * has decremented to zero, then release the message queue and delete
   * the inode now.
   */

   if (inode->i_crefs <= 0 && (inode->i_flags & FSNODEFLAG_DELETED) != 0)
     {
       FAR struct mqueue_inode_s *msgq = inode->u.i_mqueue;
       DEBUGASSERT(msgq);

       /* Free the message queue (and any messages left in it) */

       mq_msgqfree(msgq);
       inode->u.i_mqueue = NULL;

       /* Release and free the inode container */

       inode_semgive();
       inode_free(inode->i_child);
       kmm_free(inode);
       return;
    }

  inode_semgive();
}
Пример #2
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;
}
Пример #3
0
int mq_close(mqd_t mqdes)
{
  FAR _TCB    *rtcb = (FAR _TCB*)g_readytorun.head;
  FAR msgq_t *msgq;
  irqstate_t  saved_state;
  int         ret = ERROR;

  /* Verify the inputs */

   if (mqdes)
     {
       sched_lock();

       /* Remove the message descriptor from the current task's
        * list of message descriptors.
        */

       sq_rem((FAR sq_entry_t*)mqdes, &rtcb->msgdesq);

       /* Find the message queue associated with the message descriptor */

       msgq = mqdes->msgq;

       /* Check if the calling task has a notification attached to
        * the message queue via this mqdes.
        */

#ifndef CONFIG_DISABLE_SIGNALS
       if (msgq->ntmqdes == mqdes)
         {
           msgq->ntpid   = INVALID_PROCESS_ID;
           msgq->ntsigno = 0;
           msgq->ntvalue.sival_int = 0;
           msgq->ntmqdes = NULL;
         }
#endif

       /* Decrement the connection count on the message queue. */

       if (msgq->nconnect)
         {
           msgq->nconnect--;
         }

       /* If it is no longer connected to any message descriptor and if the
        * message queue has already been unlinked, then we can discard the
        * message queue.
        */

       if (!msgq->nconnect && msgq->unlinked)
         {
           /* Remove the message queue from the list of all
            * message queues
            */

           saved_state = irqsave();
           (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues);
           irqrestore(saved_state);

           /* Then deallocate it (and any messages left in it) */

           mq_msgqfree(msgq);
         }

       /* Deallocate the message descriptor */

       mq_desfree(mqdes);

       sched_unlock();
       ret = OK;
     }

   return ret;
}