forked from nuttx/nuttx-update
mqueue: simplify the mqueue reailize
1. remove descript management in mqueue, save code size 2. use i_ops instead of i_mqueue to remove the dup logic Change-Id: Ie88960e50ddcae9c87977c9ad65a45297c663291 Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
c8784faf3c
commit
3bc33572e3
25 changed files with 291 additions and 842 deletions
|
@ -40,65 +40,6 @@
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_close_group
|
||||
*
|
||||
* Description:
|
||||
* This function is used to indicate that all threads in the group are
|
||||
* finished with the specified message queue mqdes. The nxmq_close_group()
|
||||
* deallocates any system resources allocated by the system for use by
|
||||
* this task for its message queue.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor.
|
||||
* group - Group that has the open descriptor.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) if the message queue is closed successfully. Otherwise, a
|
||||
* negated errno value is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct inode *inode;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(mqdes != NULL && group != NULL);
|
||||
|
||||
/* Verify the inputs */
|
||||
|
||||
if (mqdes)
|
||||
{
|
||||
sched_lock();
|
||||
|
||||
/* Find the message queue associated with the message descriptor */
|
||||
|
||||
msgq = mqdes->msgq;
|
||||
DEBUGASSERT(msgq && msgq->inode);
|
||||
|
||||
/* Close/free the message descriptor */
|
||||
|
||||
ret = nxmq_desclose_group(mqdes, group);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Get the inode from the message queue structure */
|
||||
|
||||
inode = msgq->inode;
|
||||
DEBUGASSERT(inode->u.i_mqueue == msgq);
|
||||
|
||||
/* Decrement the reference count on the inode, possibly free it */
|
||||
|
||||
mq_inode_release(inode);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_close
|
||||
*
|
||||
|
@ -124,23 +65,7 @@ int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
|
|||
|
||||
int nxmq_close(mqd_t mqdes)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)nxsched_self();
|
||||
int ret;
|
||||
|
||||
/* Lock the scheduler to prevent any asynchronous task delete operation
|
||||
* (unlikely).
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
||||
DEBUGASSERT(mqdes != NULL && rtcb != NULL && rtcb->group != NULL);
|
||||
|
||||
/* Then perform the close operation */
|
||||
|
||||
ret = nxmq_close_group(mqdes, rtcb->group);
|
||||
|
||||
sched_unlock();
|
||||
return ret;
|
||||
return nx_close(mqdes);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -173,80 +98,5 @@ int nxmq_close(mqd_t mqdes)
|
|||
|
||||
int mq_close(mqd_t mqdes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nxmq_close(mqdes);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_inode_release
|
||||
*
|
||||
* Description:
|
||||
* Release a reference count on a message queue inode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - The message queue inode
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void mq_inode_release(FAR struct inode *inode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Decrement the reference count on the inode */
|
||||
|
||||
do
|
||||
{
|
||||
ret = inode_semtake();
|
||||
|
||||
/* The only error that is expected is due to thread cancellation.
|
||||
* At this point, we must continue to free the mqueue anyway.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(ret == OK || ret == -ECANCELED);
|
||||
}
|
||||
while (ret < 0);
|
||||
|
||||
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) */
|
||||
|
||||
nxmq_free_msgq(msgq);
|
||||
inode->u.i_mqueue = NULL;
|
||||
|
||||
/* Release and free the inode container. If it has been properly
|
||||
* unlinked, then the peer pointer should be NULL.
|
||||
*/
|
||||
|
||||
inode_semgive();
|
||||
|
||||
DEBUGASSERT(inode->i_peer == NULL);
|
||||
inode_free(inode);
|
||||
return;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
return close(mqdes);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,52 @@
|
|||
#include "inode/inode.h"
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int nxmq_file_close(FAR struct file *filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_nxmq_fileops =
|
||||
{
|
||||
NULL, /* open */
|
||||
nxmq_file_close, /* close */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* seek */
|
||||
NULL, /* ioctl */
|
||||
NULL, /* poll */
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
NULL, /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int nxmq_file_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
|
||||
if (inode->i_crefs <= 1 && (inode->i_flags & FSNODEFLAG_DELETED))
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq = inode->i_private;
|
||||
|
||||
if (msgq)
|
||||
{
|
||||
nxmq_free_msgq(msgq);
|
||||
inode->i_private = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -147,14 +193,13 @@ int nxmq_open(FAR const char *mq_name, int oflags, mode_t mode,
|
|||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Create a message queue descriptor for the current thread */
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
msgq = inode->u.i_mqueue;
|
||||
*mqdes = nxmq_create_des(NULL, msgq, oflags);
|
||||
if (!*mqdes)
|
||||
*mqdes = files_allocate(inode, oflags, 0, 0);
|
||||
if (*mqdes < 0)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_inode;
|
||||
ret = *mqdes;
|
||||
goto errout_with_msgq;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -196,19 +241,18 @@ int nxmq_open(FAR const char *mq_name, int oflags, mode_t mode,
|
|||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Create a message queue descriptor for the TCB */
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
*mqdes = nxmq_create_des(NULL, msgq, oflags);
|
||||
if (!*mqdes)
|
||||
*mqdes = files_allocate(inode, oflags, 0, 0);
|
||||
if (*mqdes < 0)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
ret = *mqdes;
|
||||
goto errout_with_msgq;
|
||||
}
|
||||
|
||||
/* Bind the message queue and the inode structure */
|
||||
|
||||
INODE_SET_MQUEUE(inode);
|
||||
inode->u.i_mqueue = msgq;
|
||||
inode->u.i_ops = &g_nxmq_fileops;
|
||||
inode->i_private = msgq;
|
||||
msgq->inode = inode;
|
||||
|
||||
/* Set the initial reference count on this inode to one */
|
||||
|
@ -222,7 +266,6 @@ int nxmq_open(FAR const char *mq_name, int oflags, mode_t mode,
|
|||
|
||||
errout_with_msgq:
|
||||
nxmq_free_msgq(msgq);
|
||||
inode->u.i_mqueue = NULL;
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
|
|
|
@ -35,6 +35,38 @@
|
|||
#include "inode/inode.h"
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_inode_release
|
||||
*
|
||||
* Description:
|
||||
* Release a reference count on a message queue inode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - The message queue inode
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mq_inode_release(FAR struct inode *inode)
|
||||
{
|
||||
if (inode->i_crefs <= 1)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq = inode->i_private;
|
||||
|
||||
if (msgq)
|
||||
{
|
||||
nxmq_free_msgq(msgq);
|
||||
inode->i_private = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -182,8 +214,8 @@ int mq_unlink(FAR const char *mq_name)
|
|||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_FS_MQUEUE_MPATH
|
||||
|
@ -55,41 +56,4 @@
|
|||
|
||||
#define MAX_MQUEUE_PATH 64
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_inode_release
|
||||
*
|
||||
* Description:
|
||||
* Release a reference count on a message queue inode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - The message queue inode
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void mq_inode_release(FAR struct inode *inode);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FS_MQUEUE_MQUEUE_H */
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include "queue.h"
|
||||
|
||||
/********************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -66,7 +65,7 @@ struct mq_attr
|
|||
|
||||
/* Message queue descriptor */
|
||||
|
||||
typedef FAR struct mq_des *mqd_t;
|
||||
typedef int mqd_t;
|
||||
|
||||
/********************************************************************************
|
||||
* Public Data
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
# include <nuttx/semaphore.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
# include <nuttx/mqueue.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -372,9 +368,6 @@ union inode_ops_u
|
|||
#ifdef CONFIG_FS_NAMED_SEMAPHORES
|
||||
FAR struct nsem_inode_s *i_nsem; /* Named semaphore */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
FAR struct mqueue_inode_s *i_mqueue; /* POSIX message queue */
|
||||
#endif
|
||||
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
|
||||
FAR char *i_link; /* Full path to link target */
|
||||
#endif
|
||||
|
|
|
@ -98,8 +98,6 @@
|
|||
|
||||
/* This structure defines a message queue */
|
||||
|
||||
struct mq_des; /* forward reference */
|
||||
|
||||
struct mqueue_inode_s
|
||||
{
|
||||
FAR struct inode *inode; /* Containing inode */
|
||||
|
@ -113,23 +111,11 @@ struct mqueue_inode_s
|
|||
#else
|
||||
uint16_t maxmsgsize; /* Max size of message in message queue */
|
||||
#endif
|
||||
FAR struct mq_des *ntmqdes; /* Notification: Owning mqdes (NULL if none) */
|
||||
pid_t ntpid; /* Notification: Receiving Task's PID */
|
||||
struct sigevent ntevent; /* Notification description */
|
||||
struct sigwork_s ntwork; /* Notification work */
|
||||
};
|
||||
|
||||
/* This describes the message queue descriptor that is held in the
|
||||
* task's TCB
|
||||
*/
|
||||
|
||||
struct mq_des
|
||||
{
|
||||
FAR struct mq_des *flink; /* Forward link to next message descriptor */
|
||||
FAR struct mqueue_inode_s *msgq; /* Pointer to associated message queue */
|
||||
int oflags; /* Flags set when message queue was opened */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
@ -424,69 +410,6 @@ void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq);
|
|||
FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode,
|
||||
FAR struct mq_attr *attr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_create_des
|
||||
*
|
||||
* Description:
|
||||
* Create a message queue descriptor for the specified TCB
|
||||
*
|
||||
* Input Parameters:
|
||||
* TCB - task that needs the descriptor.
|
||||
* msgq - Named message queue containing the message
|
||||
* oflags - access rights for the descriptor
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, the message queue descriptor is returned. NULL is returned
|
||||
* on a failure to allocate.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
mqd_t nxmq_create_des(FAR struct tcb_s *mtcb,
|
||||
FAR struct mqueue_inode_s *msgq, int oflags);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_close_group
|
||||
*
|
||||
* Description:
|
||||
* This function is used to indicate that all threads in the group are
|
||||
* finished with the specified message queue mqdes. nxmq_close_group()
|
||||
* deallocates any system resources allocated by the system for use by
|
||||
* this task for its message queue.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor.
|
||||
* group - Group that has the open descriptor.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) if the message queue is closed successfully. Otherwise, a
|
||||
* negated errno value is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_desclose_group
|
||||
*
|
||||
* Description:
|
||||
* This function performs the portion of the mq_close operation related
|
||||
* to freeing resource used by the message queue descriptor itself.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor.
|
||||
* group - Group that has the open descriptor.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* and failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* - Called only from mq_close() with the scheduler locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <signal.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
#include <mqueue.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
|
@ -601,12 +600,6 @@ struct task_group_s
|
|||
struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
/* POSIX Named Message Queue Fields *******************************************/
|
||||
|
||||
sq_queue_t tg_msgdesq; /* List of opened message queues */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Address Environment ********************************************************/
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <strings.h>
|
||||
#include "queue.h"
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
|
||||
|
|
|
@ -169,12 +169,6 @@ static inline void group_release(FAR struct task_group_s *group)
|
|||
env_release(group);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
/* Close message queues opened by members of the group */
|
||||
|
||||
nxmq_release(group);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM)
|
||||
/* Release any resource held by shared memory virtual page allocator */
|
||||
|
||||
|
|
|
@ -22,9 +22,8 @@ ifneq ($(CONFIG_DISABLE_MQUEUE),y)
|
|||
|
||||
CSRCS += mq_send.c mq_timedsend.c mq_sndinternal.c mq_receive.c
|
||||
CSRCS += mq_timedreceive.c mq_rcvinternal.c mq_initialize.c
|
||||
CSRCS += mq_descreate.c mq_desclose.c mq_msgfree.c mq_msgqalloc.c
|
||||
CSRCS += mq_msgqfree.c mq_release.c mq_recover.c mq_setattr.c
|
||||
CSRCS += mq_waitirq.c mq_notify.c mq_getattr.c
|
||||
CSRCS += mq_msgfree.c mq_msgqalloc.c mq_msgqfree.c mq_recover.c
|
||||
CSRCS += mq_setattr.c mq_waitirq.c mq_notify.c mq_getattr.c
|
||||
|
||||
# Include mqueue build support
|
||||
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
/****************************************************************************
|
||||
* sched/mqueue/mq_desclose.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <mqueue.h>
|
||||
#include <sched.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/mqueue.h>
|
||||
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_desfree
|
||||
*
|
||||
* Description:
|
||||
* Deallocate a message queue descriptor but returning it to the free list
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - message queue descriptor to free
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define mq_desfree(mqdes) sq_addlast((FAR sq_entry_t*)mqdes, &g_desfree)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_desclose_group
|
||||
*
|
||||
* Description:
|
||||
* This function performs the portion of the mq_close operation related
|
||||
* to freeing resource used by the message queue descriptor itself.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor.
|
||||
* group - Group that has the open descriptor.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* and failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* - Called only from mq_close() with the scheduler locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
mqd_t mq_ptr;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(mqdes != NULL && group != NULL);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
/* Check that msgq is valid for closing. It must be owned by the current
|
||||
* group. NOTE the call to sq_rem() below would corrupt the descriptor
|
||||
* list if mqdes did not lie in the list.
|
||||
*/
|
||||
|
||||
mq_ptr = (mqd_t)sq_peek(&group->tg_msgdesq);
|
||||
while (mq_ptr)
|
||||
{
|
||||
if (mq_ptr == mqdes)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
mq_ptr = (mqd_t)sq_next(mq_ptr);
|
||||
}
|
||||
|
||||
DEBUGASSERT(mq_ptr != NULL);
|
||||
if (mq_ptr == NULL)
|
||||
{
|
||||
/* 'mqdes' does not lie in the group's list of message descriptors. */
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Remove the message descriptor from the current group's list of message
|
||||
* descriptors.
|
||||
*/
|
||||
|
||||
sq_rem((FAR sq_entry_t *)mqdes, &group->tg_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.
|
||||
*/
|
||||
|
||||
if (msgq->ntmqdes == mqdes)
|
||||
{
|
||||
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
|
||||
msgq->ntpid = INVALID_PROCESS_ID;
|
||||
msgq->ntmqdes = NULL;
|
||||
nxsig_cancel_notification(&msgq->ntwork);
|
||||
}
|
||||
|
||||
/* Deallocate the message descriptor */
|
||||
|
||||
mq_desfree(mqdes);
|
||||
return OK;
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/****************************************************************************
|
||||
* sched/mqueue/mq_descreate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <mqueue.h>
|
||||
#include <sched.h>
|
||||
#include <queue.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/mqueue.h>
|
||||
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_alloc_des
|
||||
*
|
||||
* Description:
|
||||
* Allocate a message queue descriptor.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Reference to the allocated mq descriptor.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static mqd_t nxmq_alloc_des(void)
|
||||
{
|
||||
mqd_t mqdes;
|
||||
|
||||
/* Try to get the message descriptorfrom the free list */
|
||||
|
||||
mqdes = (mqd_t)sq_remfirst(&g_desfree);
|
||||
|
||||
/* Check if we got one. */
|
||||
|
||||
if (!mqdes)
|
||||
{
|
||||
/* Add another block of message descriptors to the list */
|
||||
|
||||
nxmq_alloc_desblock();
|
||||
|
||||
/* And try again */
|
||||
|
||||
mqdes = (mqd_t)sq_remfirst(&g_desfree);
|
||||
}
|
||||
|
||||
return mqdes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_create_des
|
||||
*
|
||||
* Description:
|
||||
* Create a message queue descriptor for the specified TCB
|
||||
*
|
||||
* Input Parameters:
|
||||
* mtcb - task that needs the descriptor.
|
||||
* msgq - Named message queue containing the message
|
||||
* oflags - access rights for the descriptor
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, the message queue descriptor is returned. NULL is returned
|
||||
* on a failure to allocate.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
mqd_t nxmq_create_des(FAR struct tcb_s *mtcb,
|
||||
FAR struct mqueue_inode_s *msgq, int oflags)
|
||||
{
|
||||
FAR struct task_group_s *group;
|
||||
mqd_t mqdes;
|
||||
|
||||
/* A NULL TCB pointer means to use the TCB of the currently executing
|
||||
* task/thread.
|
||||
*/
|
||||
|
||||
if (!mtcb)
|
||||
{
|
||||
mtcb = nxsched_self();
|
||||
}
|
||||
|
||||
group = mtcb->group;
|
||||
DEBUGASSERT(group);
|
||||
|
||||
/* Create a message queue descriptor for the TCB */
|
||||
|
||||
mqdes = nxmq_alloc_des();
|
||||
if (mqdes)
|
||||
{
|
||||
/* Initialize the message queue descriptor */
|
||||
|
||||
memset(mqdes, 0, sizeof(struct mq_des));
|
||||
mqdes->msgq = msgq;
|
||||
mqdes->oflags = oflags;
|
||||
|
||||
/* And add it to the specified task's TCB */
|
||||
|
||||
sq_addlast((FAR sq_entry_t *)mqdes, &group->tg_msgdesq);
|
||||
}
|
||||
|
||||
return mqdes;
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
#include <nuttx/config.h>
|
||||
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mqueue.h>
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -51,19 +53,31 @@
|
|||
|
||||
int mq_getattr(mqd_t mqdes, struct mq_attr *mq_stat)
|
||||
{
|
||||
int ret = ERROR;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
if (mqdes && mq_stat)
|
||||
if (!mq_stat)
|
||||
{
|
||||
/* Return the attributes */
|
||||
|
||||
mq_stat->mq_maxmsg = mqdes->msgq->maxmsgs;
|
||||
mq_stat->mq_msgsize = mqdes->msgq->maxmsgsize;
|
||||
mq_stat->mq_flags = mqdes->oflags;
|
||||
mq_stat->mq_curmsgs = mqdes->msgq->nmsgs;
|
||||
|
||||
ret = OK;
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
mq_stat->mq_maxmsg = msgq->maxmsgs;
|
||||
mq_stat->mq_msgsize = msgq->maxmsgsize;
|
||||
mq_stat->mq_flags = filep->f_oflags;
|
||||
mq_stat->mq_curmsgs = msgq->nmsgs;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -30,18 +30,6 @@
|
|||
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/* This is a container for a list of message queue descriptors. */
|
||||
|
||||
struct mq_des_block_s
|
||||
{
|
||||
sq_entry_t queue;
|
||||
struct mq_des mqdes[NUM_MSG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
@ -59,13 +47,6 @@ sq_queue_t g_msgfree;
|
|||
|
||||
sq_queue_t g_msgfreeirq;
|
||||
|
||||
/* The g_desfree data structure is a list of message descriptors available
|
||||
* to the operating system for general use. The number of messages in the
|
||||
* pool is a constant.
|
||||
*/
|
||||
|
||||
sq_queue_t g_desfree;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -82,10 +63,6 @@ static struct mqueue_msg_s *g_msgalloc;
|
|||
|
||||
static struct mqueue_msg_s *g_msgfreeirqalloc;
|
||||
|
||||
/* g_desalloc is a list of allocated block of message queue descriptors. */
|
||||
|
||||
static sq_queue_t g_desalloc;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -155,7 +132,6 @@ void nxmq_initialize(void)
|
|||
|
||||
sq_init(&g_msgfree);
|
||||
sq_init(&g_msgfreeirq);
|
||||
sq_init(&g_desalloc);
|
||||
|
||||
/* Allocate a block of messages for general use */
|
||||
|
||||
|
@ -170,50 +146,4 @@ void nxmq_initialize(void)
|
|||
g_msgfreeirqalloc =
|
||||
mq_msgblockalloc(&g_msgfreeirq, CONFIG_PREALLOC_MQ_IRQ_MSGS,
|
||||
MQ_ALLOC_IRQ);
|
||||
|
||||
/* Allocate a block of message queue descriptors */
|
||||
|
||||
nxmq_alloc_desblock();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_alloc_desblock
|
||||
*
|
||||
* Description:
|
||||
* Allocate a block of message descriptors and place them on the free
|
||||
* list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxmq_alloc_desblock(void)
|
||||
{
|
||||
FAR struct mq_des_block_s *mqdesblock;
|
||||
|
||||
/* Allocate a block of message descriptors */
|
||||
|
||||
mqdesblock = (FAR struct mq_des_block_s *)
|
||||
kmm_malloc(sizeof(struct mq_des_block_s));
|
||||
if (mqdesblock)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Add the block to the list of allocated blocks (in case
|
||||
* we ever need to reclaim the memory).
|
||||
*/
|
||||
|
||||
sq_addlast((FAR sq_entry_t *)&mqdesblock->queue, &g_desalloc);
|
||||
|
||||
/* Then add each message queue descriptor to the free list */
|
||||
|
||||
for (i = 0; i < NUM_MSG_DESCRIPTORS; i++)
|
||||
{
|
||||
sq_addlast((FAR sq_entry_t *)&mqdesblock->mqdes[i], &g_desfree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,24 +93,34 @@
|
|||
|
||||
int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
||||
{
|
||||
FAR struct tcb_s *rtcb;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct inode *inode;
|
||||
FAR struct file *filep;
|
||||
FAR struct tcb_s *rtcb;
|
||||
int errval;
|
||||
|
||||
errval = fs_getfilep(mqdes, &filep);
|
||||
if (errval < 0)
|
||||
{
|
||||
goto errout_without_lock;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
/* Was a valid message queue descriptor provided? */
|
||||
|
||||
if (!mqdes)
|
||||
if (!msgq)
|
||||
{
|
||||
/* No.. return EBADF */
|
||||
|
||||
errval = EBADF;
|
||||
goto errout;
|
||||
goto errout_without_lock;
|
||||
}
|
||||
|
||||
/* Get a pointer to the message queue */
|
||||
|
||||
sched_lock();
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* Get the current process ID */
|
||||
|
||||
|
@ -118,7 +128,7 @@ int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
|||
|
||||
/* Is there already a notification attached */
|
||||
|
||||
if (!msgq->ntmqdes)
|
||||
if (msgq->ntpid == INVALID_PROCESS_ID)
|
||||
{
|
||||
/* No... Have we been asked to establish one? */
|
||||
|
||||
|
@ -139,8 +149,7 @@ int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
|||
memcpy(&msgq->ntevent, notification,
|
||||
sizeof(struct sigevent));
|
||||
|
||||
msgq->ntpid = rtcb->pid;
|
||||
msgq->ntmqdes = mqdes;
|
||||
msgq->ntpid = rtcb->pid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,8 +173,7 @@ int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
|||
*/
|
||||
|
||||
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
|
||||
msgq->ntpid = INVALID_PROCESS_ID;
|
||||
msgq->ntmqdes = NULL;
|
||||
msgq->ntpid = INVALID_PROCESS_ID;
|
||||
nxsig_cancel_notification(&msgq->ntwork);
|
||||
}
|
||||
|
||||
|
@ -173,7 +181,9 @@ int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
|||
return OK;
|
||||
|
||||
errout:
|
||||
set_errno(errval);
|
||||
sched_unlock();
|
||||
|
||||
errout_without_lock:
|
||||
set_errno(errval);
|
||||
return ERROR;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,9 @@
|
|||
* are common to both functions.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message Queue Descriptor
|
||||
* msg - Buffer to receive the message
|
||||
* msgq - Message queue descriptor
|
||||
* oflags - flags from user set
|
||||
* msg - Buffer to receive the message
|
||||
* msglen - Size of the buffer in bytes
|
||||
*
|
||||
* Returned Value:
|
||||
|
@ -64,25 +65,26 @@
|
|||
* EPERM Message queue opened not opened for reading.
|
||||
* EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the message
|
||||
* queue.
|
||||
* EINVAL Invalid 'msg' or 'mqdes'
|
||||
* EINVAL Invalid 'msg' or 'msgq'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_verify_receive(mqd_t mqdes, FAR char *msg, size_t msglen)
|
||||
int nxmq_verify_receive(FAR struct mqueue_inode_s *msgq,
|
||||
int oflags, FAR char *msg, size_t msglen)
|
||||
{
|
||||
/* Verify the input parameters */
|
||||
|
||||
if (!msg || !mqdes)
|
||||
if (!msg || !msgq)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((mqdes->oflags & O_RDOK) == 0)
|
||||
if ((oflags & O_RDOK) == 0)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (msglen < (size_t)mqdes->msgq->maxmsgsize)
|
||||
if (msglen < (size_t)msgq->maxmsgsize)
|
||||
{
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
@ -100,7 +102,8 @@ int nxmq_verify_receive(mqd_t mqdes, FAR char *msg, size_t msglen)
|
|||
* returns it.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor
|
||||
* msgq - Message queue descriptor
|
||||
* oflags - flags from user set
|
||||
* rcvmsg - The caller-provided location in which to return the newly
|
||||
* received message.
|
||||
*
|
||||
|
@ -117,10 +120,10 @@ int nxmq_verify_receive(mqd_t mqdes, FAR char *msg, size_t msglen)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
||||
int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq,
|
||||
int oflags, FAR struct mqueue_msg_s **rcvmsg)
|
||||
{
|
||||
FAR struct tcb_s *rtcb;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *newmsg;
|
||||
int ret;
|
||||
|
||||
|
@ -142,10 +145,6 @@ int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Get a pointer to the message queue */
|
||||
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* Get the message from the head of the queue */
|
||||
|
||||
while ((newmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&msgq->msglist))
|
||||
|
@ -155,7 +154,7 @@ int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
|||
* has been satisfied?
|
||||
*/
|
||||
|
||||
if ((mqdes->oflags & O_NONBLOCK) == 0)
|
||||
if ((oflags & O_NONBLOCK) == 0)
|
||||
{
|
||||
/* Yes.. Block and try again */
|
||||
|
||||
|
@ -191,7 +190,7 @@ int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
|||
else
|
||||
{
|
||||
/* The queue was empty, and the O_NONBLOCK flag was set for the
|
||||
* message queue description referred to by 'mqdes'.
|
||||
* message queue description.
|
||||
*/
|
||||
|
||||
return -EAGAIN;
|
||||
|
@ -222,7 +221,7 @@ int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
|||
* and disposes of the message structure
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor
|
||||
* msgq - Message queue descriptor
|
||||
* mqmsg - The message obtained by mq_waitmsg()
|
||||
* ubuffer - The address of the user provided buffer to receive the message
|
||||
* prio - The user-provided location to return the message priority.
|
||||
|
@ -240,12 +239,12 @@ int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t nxmq_do_receive(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
||||
ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
|
||||
FAR struct mqueue_msg_s *mqmsg,
|
||||
FAR char *ubuffer, unsigned int *prio)
|
||||
{
|
||||
FAR struct tcb_s *btcb;
|
||||
irqstate_t flags;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
ssize_t rcvmsglen;
|
||||
|
||||
/* Get the length of the message (also the return value) */
|
||||
|
@ -269,7 +268,6 @@ ssize_t nxmq_do_receive(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
|||
|
||||
/* Check if any tasks are waiting for the MQ not full event. */
|
||||
|
||||
msgq = mqdes->msgq;
|
||||
if (msgq->nwaitnotfull > 0)
|
||||
{
|
||||
/* Find the highest priority task that is waiting for
|
||||
|
|
|
@ -72,17 +72,31 @@
|
|||
ssize_t nxmq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
||||
FAR unsigned int *prio)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *mqmsg;
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
irqstate_t flags;
|
||||
ssize_t ret;
|
||||
|
||||
/* Convert fd to msgq */
|
||||
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
DEBUGASSERT(up_interrupt_context() == false);
|
||||
|
||||
/* Verify the input parameters and, in case of an error, set
|
||||
* errno appropriately.
|
||||
*/
|
||||
|
||||
ret = nxmq_verify_receive(mqdes, msg, msglen);
|
||||
ret = nxmq_verify_receive(msgq, filep->f_oflags, msg, msglen);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -105,20 +119,20 @@ ssize_t nxmq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||
|
||||
/* Get the message from the message queue */
|
||||
|
||||
ret = nxmq_wait_receive(mqdes, &mqmsg);
|
||||
ret = nxmq_wait_receive(msgq, filep->f_oflags, &mqmsg);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Check if we got a message from the message queue. We might
|
||||
* not have a message if:
|
||||
*
|
||||
* - The message queue is empty and O_NONBLOCK is set in the mqdes
|
||||
* - The message queue is empty and O_NONBLOCK is set in the filep
|
||||
* - The wait was interrupted by a signal
|
||||
*/
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
DEBUGASSERT(mqmsg != NULL);
|
||||
ret = nxmq_do_receive(mqdes, mqmsg, msg, prio);
|
||||
ret = nxmq_do_receive(msgq, mqmsg, msg, prio);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/****************************************************************************
|
||||
* sched/mqueue/mq_release.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxmq_release
|
||||
*
|
||||
* Description:
|
||||
* This function is called when the final member of a task group exits.
|
||||
* This function closes all of the message queues opened by members of
|
||||
* the task group.
|
||||
*
|
||||
* Input Parameters:
|
||||
* group - The task group that is terminating.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxmq_release(FAR struct task_group_s *group)
|
||||
{
|
||||
while (group->tg_msgdesq.head)
|
||||
{
|
||||
nxmq_close_group((mqd_t)group->tg_msgdesq.head, group);
|
||||
}
|
||||
}
|
|
@ -70,16 +70,29 @@
|
|||
int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
||||
unsigned int prio)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *mqmsg = NULL;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Convert fd to msgq */
|
||||
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
/* Verify the input parameters -- setting errno appropriately
|
||||
* on any failures to verify.
|
||||
*/
|
||||
|
||||
ret = nxmq_verify_send(mqdes, msg, msglen, prio);
|
||||
ret = nxmq_verify_send(msgq, filep->f_oflags, msg, msglen, prio);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -88,7 +101,6 @@ int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
/* Get a pointer to the message queue */
|
||||
|
||||
sched_lock();
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* Allocate a message structure:
|
||||
* - Immediately if we are called from an interrupt handler.
|
||||
|
@ -111,7 +123,7 @@ int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
* available in the message queue.
|
||||
*/
|
||||
|
||||
ret = nxmq_wait_send(mqdes);
|
||||
ret = nxmq_wait_send(msgq, filep->f_oflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +157,7 @@ int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
* to be exceeded in that case.
|
||||
*/
|
||||
|
||||
ret = nxmq_do_send(mqdes, mqmsg, msg, msglen, prio);
|
||||
ret = nxmq_do_send(msgq, mqmsg, msg, msglen, prio);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <fcntl.h> /* O_NONBLOCK */
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mqueue.h>
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -61,23 +62,33 @@
|
|||
int mq_setattr(mqd_t mqdes, const struct mq_attr *mq_stat,
|
||||
struct mq_attr *oldstat)
|
||||
{
|
||||
int ret = ERROR;
|
||||
FAR struct file *filep;
|
||||
int ret;
|
||||
|
||||
if (mqdes && mq_stat)
|
||||
if (!mq_stat)
|
||||
{
|
||||
/* Return the attributes if so requested */
|
||||
|
||||
if (oldstat)
|
||||
{
|
||||
mq_getattr(mqdes, oldstat);
|
||||
}
|
||||
|
||||
/* Set the new value of the O_NONBLOCK flag. */
|
||||
|
||||
mqdes->oflags = ((mq_stat->mq_flags & O_NONBLOCK) |
|
||||
(mqdes->oflags & (~O_NONBLOCK)));
|
||||
ret = OK;
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Return the attributes if so requested */
|
||||
|
||||
if (oldstat)
|
||||
{
|
||||
mq_getattr(mqdes, oldstat);
|
||||
}
|
||||
|
||||
/* Set the new value of the O_NONBLOCK flag. */
|
||||
|
||||
filep->f_oflags = ((mq_stat->mq_flags & O_NONBLOCK) |
|
||||
(filep->f_oflags & (~O_NONBLOCK)));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -55,38 +55,39 @@
|
|||
* common to both functions.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor
|
||||
* msg - Message to send
|
||||
* msgq - Message queue descriptor
|
||||
* oflags - flags from user set
|
||||
* msg - Message to send
|
||||
* msglen - The length of the message in bytes
|
||||
* prio - The priority of the message
|
||||
* prio - The priority of the message
|
||||
*
|
||||
* Returned Value:
|
||||
* One success, 0 (OK) is returned. On failure, a negated errno value is
|
||||
* returned.
|
||||
*
|
||||
* EINVAL Either msg or mqdes is NULL or the value of prio is invalid.
|
||||
* EINVAL Either msg or msgq is NULL or the value of prio is invalid.
|
||||
* EPERM Message queue opened not opened for writing.
|
||||
* EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the
|
||||
* message queue.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
||||
unsigned int prio)
|
||||
int nxmq_verify_send(FAR struct mqueue_inode_s *msgq, int oflags,
|
||||
FAR const char *msg, size_t msglen, unsigned int prio)
|
||||
{
|
||||
/* Verify the input parameters */
|
||||
|
||||
if (msg == NULL || mqdes == NULL || prio > MQ_PRIO_MAX)
|
||||
if (msg == NULL || msgq == NULL || prio > MQ_PRIO_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((mqdes->oflags & O_WROK) == 0)
|
||||
if ((oflags & O_WROK) == 0)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (msglen > (size_t)mqdes->msgq->maxmsgsize)
|
||||
if (msglen > (size_t)msgq->maxmsgsize)
|
||||
{
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
@ -190,14 +191,15 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void)
|
|||
* full.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor
|
||||
* msgq - Message queue descriptor
|
||||
* oflags - flags from user set
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, nxmq_wait_send() returns 0 (OK); a negated errno value is
|
||||
* returned on any failure:
|
||||
*
|
||||
* EAGAIN The queue was full and the O_NONBLOCK flag was set for the
|
||||
* message queue description referred to by mqdes.
|
||||
* message queue description referred to by msgq.
|
||||
* EINTR The call was interrupted by a signal handler.
|
||||
* ETIMEOUT A timeout expired before the message queue became non-full
|
||||
* (mq_timedsend only).
|
||||
|
@ -208,10 +210,9 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_wait_send(mqd_t mqdes)
|
||||
int nxmq_wait_send(FAR struct mqueue_inode_s *msgq, int oflags)
|
||||
{
|
||||
FAR struct tcb_s *rtcb;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_CANCELLATION_POINTS
|
||||
|
@ -229,10 +230,6 @@ int nxmq_wait_send(mqd_t mqdes)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Get a pointer to the message queue */
|
||||
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* Verify that the queue is indeed full as the caller thinks */
|
||||
|
||||
if (msgq->nmsgs >= msgq->maxmsgs)
|
||||
|
@ -241,7 +238,7 @@ int nxmq_wait_send(mqd_t mqdes)
|
|||
* message queue?
|
||||
*/
|
||||
|
||||
if ((mqdes->oflags & O_NONBLOCK) != 0)
|
||||
if ((oflags & O_NONBLOCK) != 0)
|
||||
{
|
||||
/* No... We will return an error to the caller. */
|
||||
|
||||
|
@ -305,12 +302,12 @@ int nxmq_wait_send(mqd_t mqdes)
|
|||
* Description:
|
||||
* This is internal, common logic shared by both [nx]mq_send and
|
||||
* [nx]mq_timesend. This function adds the specified message (msg) to the
|
||||
* message queue (mqdes). Then it notifies any tasks that were waiting
|
||||
* message queue (msgq). Then it notifies any tasks that were waiting
|
||||
* for message queue notifications setup by mq_notify. And, finally, it
|
||||
* awakens any tasks that were waiting for the message not empty event.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mqdes - Message queue descriptor
|
||||
* msgq - Message queue descriptor
|
||||
* msg - Message to send
|
||||
* msglen - The length of the message in bytes
|
||||
* prio - The priority of the message
|
||||
|
@ -320,11 +317,11 @@ int nxmq_wait_send(mqd_t mqdes)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
||||
int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
|
||||
FAR struct mqueue_msg_s *mqmsg,
|
||||
FAR const char *msg, size_t msglen, unsigned int prio)
|
||||
{
|
||||
FAR struct tcb_s *btcb;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *next;
|
||||
FAR struct mqueue_msg_s *prev;
|
||||
irqstate_t flags;
|
||||
|
@ -332,7 +329,6 @@ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
|||
/* Get a pointer to the message queue */
|
||||
|
||||
sched_lock();
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* Construct the message header info */
|
||||
|
||||
|
@ -376,7 +372,7 @@ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
|||
* message queue
|
||||
*/
|
||||
|
||||
if (msgq->ntmqdes)
|
||||
if (msgq->ntpid != INVALID_PROCESS_ID)
|
||||
{
|
||||
struct sigevent event;
|
||||
pid_t pid;
|
||||
|
@ -389,8 +385,7 @@ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
|||
/* Detach the notification */
|
||||
|
||||
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
|
||||
msgq->ntpid = INVALID_PROCESS_ID;
|
||||
msgq->ntmqdes = NULL;
|
||||
msgq->ntpid = INVALID_PROCESS_ID;
|
||||
|
||||
/* Notification the client */
|
||||
|
||||
|
|
|
@ -138,17 +138,31 @@ ssize_t nxmq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||
FAR const struct timespec *abstime)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *mqmsg;
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Convert fd to msgq */
|
||||
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
DEBUGASSERT(up_interrupt_context() == false);
|
||||
|
||||
/* Verify the input parameters and, in case of an error, set
|
||||
* errno appropriately.
|
||||
*/
|
||||
|
||||
ret = nxmq_verify_receive(mqdes, msg, msglen);
|
||||
ret = nxmq_verify_receive(msgq, filep->f_oflags, msg, msglen);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -178,7 +192,7 @@ ssize_t nxmq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||
* will not need to start timer.
|
||||
*/
|
||||
|
||||
if (mqdes->msgq->msglist.head == NULL)
|
||||
if (msgq->msglist.head == NULL)
|
||||
{
|
||||
sclock_t ticks;
|
||||
|
||||
|
@ -213,7 +227,7 @@ ssize_t nxmq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||
|
||||
/* Get the message from the message queue */
|
||||
|
||||
ret = nxmq_wait_receive(mqdes, &mqmsg);
|
||||
ret = nxmq_wait_receive(msgq, filep->f_oflags, &mqmsg);
|
||||
|
||||
/* Stop the watchdog timer (this is not harmful in the case where
|
||||
* it was never started)
|
||||
|
@ -236,7 +250,7 @@ ssize_t nxmq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||
if (ret >= 0)
|
||||
{
|
||||
DEBUGASSERT(mqmsg != NULL);
|
||||
ret = nxmq_do_receive(mqdes, mqmsg, msg, prio);
|
||||
ret = nxmq_do_receive(msgq, mqmsg, msg, prio);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
|
|
|
@ -145,18 +145,31 @@ int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
unsigned int prio, FAR const struct timespec *abstime)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct mqueue_msg_s *mqmsg = NULL;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
irqstate_t flags;
|
||||
sclock_t ticks;
|
||||
int result;
|
||||
int ret;
|
||||
|
||||
/* Convert fd to msgq */
|
||||
|
||||
ret = fs_getfilep(mqdes, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
msgq = inode->i_private;
|
||||
|
||||
DEBUGASSERT(up_interrupt_context() == false);
|
||||
|
||||
/* Verify the input parameters on any failures to verify. */
|
||||
|
||||
ret = nxmq_verify_send(mqdes, msg, msglen, prio);
|
||||
ret = nxmq_verify_send(msgq, filep->f_oflags, msg, msglen, prio);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -177,7 +190,6 @@ int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
/* Get a pointer to the message queue */
|
||||
|
||||
sched_lock();
|
||||
msgq = mqdes->msgq;
|
||||
|
||||
/* OpenGroup.org: "Under no circumstance shall the operation fail with a
|
||||
* timeout if there is sufficient room in the queue to add the message
|
||||
|
@ -199,7 +211,7 @@ int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
* Currently nxmq_do_send() always returns OK.
|
||||
*/
|
||||
|
||||
ret = nxmq_do_send(mqdes, mqmsg, msg, msglen, prio);
|
||||
ret = nxmq_do_send(msgq, mqmsg, msg, msglen, prio);
|
||||
sched_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
@ -247,7 +259,7 @@ int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
|
||||
/* And wait for the message queue to be non-empty */
|
||||
|
||||
ret = nxmq_wait_send(mqdes);
|
||||
ret = nxmq_wait_send(msgq, filep->f_oflags);
|
||||
|
||||
/* This may return with an error and errno set to either EINTR
|
||||
* or ETIMEOUT. Cancel the watchdog timer in any event.
|
||||
|
@ -275,7 +287,7 @@ int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
|||
* Currently nxmq_do_send() always returns OK.
|
||||
*/
|
||||
|
||||
ret = nxmq_do_send(mqdes, mqmsg, msg, msglen, prio);
|
||||
ret = nxmq_do_send(msgq, mqmsg, msg, msglen, prio);
|
||||
|
||||
sched_unlock();
|
||||
leave_cancellation_point();
|
||||
|
|
|
@ -47,12 +47,6 @@
|
|||
#define MQ_MAX_MSGS 16
|
||||
#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX
|
||||
|
||||
/* This defines the number of messages descriptors to allocate at each
|
||||
* "gulp."
|
||||
*/
|
||||
|
||||
#define NUM_MSG_DESCRIPTORS 4
|
||||
|
||||
/********************************************************************************
|
||||
* Public Type Definitions
|
||||
********************************************************************************/
|
||||
|
@ -103,13 +97,6 @@ EXTERN sq_queue_t g_msgfree;
|
|||
|
||||
EXTERN sq_queue_t g_msgfreeirq;
|
||||
|
||||
/* The g_desfree data structure is a list of message descriptors available
|
||||
* to the operating system for general use. The number of messages in the
|
||||
* pool is a constant.
|
||||
*/
|
||||
|
||||
EXTERN sq_queue_t g_desfree;
|
||||
|
||||
/********************************************************************************
|
||||
* Public Function Prototypes
|
||||
********************************************************************************/
|
||||
|
@ -120,7 +107,6 @@ struct task_group_s; /* Forward reference */
|
|||
/* Functions defined in mq_initialize.c *****************************************/
|
||||
|
||||
void weak_function nxmq_initialize(void);
|
||||
void nxmq_alloc_desblock(void);
|
||||
void nxmq_free_msg(FAR struct mqueue_msg_s *mqmsg);
|
||||
|
||||
/* mq_waitirq.c *****************************************************************/
|
||||
|
@ -129,24 +115,24 @@ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode);
|
|||
|
||||
/* mq_rcvinternal.c *************************************************************/
|
||||
|
||||
int nxmq_verify_receive(mqd_t mqdes, FAR char *msg, size_t msglen);
|
||||
int nxmq_wait_receive(mqd_t mqdes, FAR struct mqueue_msg_s **rcvmsg);
|
||||
ssize_t nxmq_do_receive(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
||||
FAR char *ubuffer, FAR unsigned int *prio);
|
||||
int nxmq_verify_receive(FAR struct mqueue_inode_s *msgq,
|
||||
int oflags, FAR char *msg, size_t msglen);
|
||||
int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq,
|
||||
int oflags, FAR struct mqueue_msg_s **rcvmsg);
|
||||
ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
|
||||
FAR struct mqueue_msg_s *mqmsg,
|
||||
FAR char *ubuffer, unsigned int *prio);
|
||||
|
||||
/* mq_sndinternal.c *************************************************************/
|
||||
|
||||
int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
|
||||
unsigned int prio);
|
||||
int nxmq_verify_send(FAR struct mqueue_inode_s *msgq, int oflags,
|
||||
FAR const char *msg, size_t msglen, unsigned int prio);
|
||||
FAR struct mqueue_msg_s *nxmq_alloc_msg(void);
|
||||
int nxmq_wait_send(mqd_t mqdes);
|
||||
int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
||||
int nxmq_wait_send(FAR struct mqueue_inode_s *msgq, int oflags);
|
||||
int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
|
||||
FAR struct mqueue_msg_s *mqmsg,
|
||||
FAR const char *msg, size_t msglen, unsigned int prio);
|
||||
|
||||
/* mq_release.c *****************************************************************/
|
||||
|
||||
void nxmq_release(FAR struct task_group_s *group);
|
||||
|
||||
/* mq_recover.c *****************************************************************/
|
||||
|
||||
void nxmq_recover(FAR struct tcb_s *tcb);
|
||||
|
|
Loading…
Reference in a new issue