mqueue: Add nxmq_open/nxmq_close/nxmq_unlink function

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2020-05-04 04:31:05 +08:00 committed by patacongo
parent de2a9d8a77
commit 929292f57b
4 changed files with 273 additions and 74 deletions

View file

@ -88,7 +88,7 @@ int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
inode = msgq->inode;
DEBUGASSERT(inode->u.i_mqueue == msgq);
/* Decrement the reference count on the inode, possibly freeing it */
/* Decrement the reference count on the inode, possibly free it */
mq_inode_release(inode);
}
@ -99,6 +99,51 @@ int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
return ret;
}
/****************************************************************************
* Name: nxmq_close
*
* Description:
* This is an internal OS interface. It is functionally equivalent to
* mq_close() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_close() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mqdes - Message queue descriptor.
*
* Returned Value:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success. A negated errno value is returned on failure.
*
****************************************************************************/
int nxmq_close(mqd_t mqdes)
{
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)sched_self();
int ret;
/* Lock the scheduler to prevent any asynchronous task delete operation
* (unlikely).
*/
sched_lock();
rtcb = (FAR struct tcb_s *)sched_self();
DEBUGASSERT(mqdes != NULL && rtcb != NULL && rtcb->group != NULL);
/* Then perform the close operation */
ret = nxmq_close_group(mqdes, rtcb->group);
sched_unlock();
return ret;
}
/****************************************************************************
* Name: mq_close
*
@ -129,30 +174,15 @@ int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
int mq_close(mqd_t mqdes)
{
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)sched_self();
int ret;
/* Lock the scheduler to prevent any asynchronous task delete operation
* (unlikely).
*/
sched_lock();
rtcb = (FAR struct tcb_s *)sched_self();
DEBUGASSERT(mqdes != NULL && rtcb != NULL && rtcb->group != NULL);
/* Then perform the close operation */
ret = nxmq_close_group(mqdes, rtcb->group);
#if 0
if (ret < 0) /* Currently, nxmq_close_group() only returns OK */
ret = nxmq_close(mqdes);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
#endif
sched_unlock();
return ret;
}

View file

@ -43,14 +43,18 @@
****************************************************************************/
/****************************************************************************
* Name: mq_open
* Name: nxmq_open
*
* Description:
* This function establish a connection between a named message queue and
* the calling task. After a successful call of mq_open(), the task can
* reference the message queue using the address returned by the call. The
* message queue remains usable until it is closed by a successful call to
* mq_close().
* the calling task. This is an internal OS interface. It is functionally
* equivalent to mq_open() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_open() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mq_name - Name of the queue to open
@ -65,30 +69,27 @@
* messages that may be placed in the message queue.
*
* Returned Value:
* A message queue descriptor or (mqd_t)-1 (ERROR)
*
* Assumptions:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success, mqdes point to the new message queue descriptor.
* A negated errno value is returned on failure.
*
****************************************************************************/
mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
int nxmq_open(FAR const char *mq_name, int oflags, mode_t mode,
FAR struct mq_attr *attr, FAR mqd_t *mqdes)
{
FAR struct inode *inode;
FAR struct mqueue_inode_s *msgq;
struct inode_search_s desc;
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 == NULL || *mq_name == '\0')
{
errcode = EINVAL;
ret = -EINVAL;
goto errout;
}
@ -132,7 +133,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
if (!INODE_IS_MQUEUE(inode))
{
errcode = ENXIO;
ret = -ENXIO;
goto errout_with_inode;
}
@ -142,17 +143,17 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
{
errcode = EEXIST;
ret = -EEXIST;
goto errout_with_inode;
}
/* Create a message queue descriptor for the current thread */
msgq = inode->u.i_mqueue;
mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!mqdes)
*mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!*mqdes)
{
errcode = ENOMEM;
ret = -ENOMEM;
goto errout_with_inode;
}
}
@ -164,25 +165,15 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
{
/* The mqueue does not exist and O_CREAT is not set */
errcode = ENOENT;
ret = -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 */
ret = inode_semtake();
if (ret < 0)
{
errcode = -ret;
goto errout_with_lock;
}
@ -191,7 +182,6 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
if (ret < 0)
{
errcode = -ret;
goto errout_with_lock;
}
@ -202,16 +192,16 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
msgq = (FAR struct mqueue_inode_s *)nxmq_alloc_msgq(mode, attr);
if (!msgq)
{
errcode = ENOSPC;
ret = -ENOSPC;
goto errout_with_inode;
}
/* Create a message queue descriptor for the TCB */
mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!mqdes)
*mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!*mqdes)
{
errcode = ENOMEM;
ret = -ENOMEM;
goto errout_with_msgq;
}
@ -228,7 +218,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
RELEASE_SEARCH(&desc);
sched_unlock();
return mqdes;
return OK;
errout_with_msgq:
nxmq_free_msgq(msgq);
@ -242,6 +232,66 @@ errout_with_lock:
sched_unlock();
errout:
set_errno(errcode);
return (mqd_t)ERROR;
return ret;
}
/****************************************************************************
* Name: mq_open
*
* Description:
* This function establish a connection between a named message queue and
* the calling task. After a successful call of mq_open(), the task can
* reference the message queue using the address returned by the call. The
* message queue remains usable until it is closed by a successful call to
* mq_close().
*
* Input Parameters:
* mq_name - Name of the queue to open
* oflags - open flags
* Optional parameters. When the O_CREAT flag is specified, two optional
* parameters are expected:
*
* 1. mode_t mode (ignored), and
* 2. struct mq_attr *attr. The mq_maxmsg attribute
* is used at the time that the message queue is
* created to determine the maximum number of
* messages that may be placed in the message queue.
*
* Returned Value:
* A message queue descriptor or (mqd_t)-1 (ERROR)
*
* Assumptions:
*
****************************************************************************/
mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
{
FAR struct mq_attr *attr = NULL;
mode_t mode = 0;
mqd_t mqdes;
va_list ap;
int ret;
/* Were we asked to create it? */
if ((oflags & O_CREAT) != 0)
{
/* 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);
}
ret = nxmq_open(mq_name, oflags, mode, attr, &mqdes);
if (ret < 0)
{
set_errno(ret);
mqdes = (mqd_t)ERROR;
}
return mqdes;
}

View file

@ -40,30 +40,33 @@
****************************************************************************/
/****************************************************************************
* Name: mq_unlink
* Name: nxmq_unlink
*
* Description:
* This function removes the message queue named by "mq_name." If one
* or more tasks have the message queue open when mq_unlink() is called,
* removal of the message queue is postponed until all references to the
* message queue have been closed.
* This is an internal OS interface. It is functionally equivalent to
* mq_unlink() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_unlink() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mq_name - Name of the message queue
*
* Returned Value:
* None
*
* Assumptions:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success. A negated errno value is returned on failure.
*
****************************************************************************/
int mq_unlink(FAR const char *mq_name)
int nxmq_unlink(FAR const char *mq_name)
{
FAR struct inode *inode;
struct inode_search_s desc;
char fullpath[MAX_MQUEUE_PATH];
int errcode;
int ret;
/* Get the full path to the message queue */
@ -80,7 +83,6 @@ int mq_unlink(FAR const char *mq_name)
{
/* There is no inode that includes in this path */
errcode = -ret;
goto errout_with_search;
}
@ -93,7 +95,7 @@ int mq_unlink(FAR const char *mq_name)
if (!INODE_IS_MQUEUE(inode))
{
errcode = ENXIO;
ret = -ENXIO;
goto errout_with_inode;
}
@ -104,13 +106,12 @@ int mq_unlink(FAR const char *mq_name)
ret = inode_semtake();
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
if (inode->i_child != NULL)
{
errcode = ENOTEMPTY;
ret = -ENOTEMPTY;
goto errout_with_semaphore;
}
@ -127,7 +128,6 @@ int mq_unlink(FAR const char *mq_name)
*/
DEBUGASSERT(ret >= 0 || ret == -EBUSY);
UNUSED(ret);
/* Now we do not release the reference count in the normal way (by calling
* inode release. Rather, we call mq_inode_release(). mq_inode_release
@ -151,7 +151,39 @@ errout_with_inode:
errout_with_search:
RELEASE_SEARCH(&desc);
set_errno(errcode);
sched_unlock();
return ERROR;
return ret;
}
/****************************************************************************
* Name: mq_unlink
*
* Description:
* This function removes the message queue named by "mq_name." If one
* or more tasks have the message queue open when mq_unlink() is called,
* removal of the message queue is postponed until all references to the
* message queue have been closed.
*
* Input Parameters:
* mq_name - Name of the message queue
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
int mq_unlink(FAR const char *mq_name)
{
int ret;
ret = nxmq_unlink(mq_name);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
return ret;
}

View file

@ -151,6 +151,93 @@ struct mq_attr; /* Forward reference */
struct timespec; /* Forward reference */
struct task_group_s; /* Forward reference */
/****************************************************************************
* Name: nxmq_open
*
* Description:
* This function establish a connection between a named message queue and
* the calling task. This is an internal OS interface. It is functionally
* equivalent to mq_open() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_open() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mq_name - Name of the queue to open
* oflags - open flags
* Optional parameters. When the O_CREAT flag is specified, two optional
* parameters are expected:
*
* 1. mode_t mode (ignored), and
* 2. struct mq_attr *attr. The mq_maxmsg attribute
* is used at the time that the message queue is
* created to determine the maximum number of
* messages that may be placed in the message queue.
*
* Returned Value:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success, mqdes point to the new message queue descriptor.
* A negated errno value is returned on failure.
*
****************************************************************************/
int nxmq_open(FAR const char *mq_name, int oflags, mode_t mode,
FAR struct mq_attr *attr, FAR mqd_t *mqdes);
/****************************************************************************
* Name: nxmq_close
*
* Description:
* This is an internal OS interface. It is functionally equivalent to
* mq_close() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_close() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mqdes - Message queue descriptor.
*
* Returned Value:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success. A negated errno value is returned on failure.
*
****************************************************************************/
int nxmq_close(mqd_t mqdes);
/****************************************************************************
* Name: nxmq_unlink
*
* Description:
* This is an internal OS interface. It is functionally equivalent to
* mq_unlink() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno value.
*
* See comments with mq_unlink() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mq_name - Name of the message queue
*
* Returned Value:
* This is an internal OS interface and should not be used by applications.
* It follows the NuttX internal error return policy: Zero (OK) is
* returned on success. A negated errno value is returned on failure.
*
****************************************************************************/
int nxmq_unlink(FAR const char *mq_name);
/****************************************************************************
* Name: nxmq_send
*