Completes the re-implementation of mq_unlink()
This commit is contained in:
parent
1f2cc9f4fe
commit
419b074b15
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/mqueue/mq_close.c
|
||||
* fs/mqueue/mq_close.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2013-2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -107,7 +107,7 @@ int mq_close(mqd_t mqdes)
|
||||
FAR struct tcb_s *rtcb = sched_self();
|
||||
FAR struct task_group_s *group = rtcb->group;
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
struct inode *inode ;
|
||||
FAR struct inode *inode;
|
||||
|
||||
DEBUGASSERT(group);
|
||||
|
||||
@ -128,11 +128,6 @@ int mq_close(mqd_t mqdes)
|
||||
msgq = mqdes->msgq;
|
||||
DEBUGASSERT(msgq && msgq->inode);
|
||||
|
||||
/* Get the inode from the message queue structure */
|
||||
|
||||
inode = msgq->inode;
|
||||
DEBUGASSERT(inode->u.i_mqueue == msgq);
|
||||
|
||||
/* Check if the calling task has a notification attached to
|
||||
* the message queue via this mqdes.
|
||||
*/
|
||||
@ -147,6 +142,35 @@ int mq_close(mqd_t mqdes)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the inode from the message queue structure */
|
||||
|
||||
inode = msgq->inode;
|
||||
DEBUGASSERT(inode->u.i_mqueue == msgq);
|
||||
|
||||
/* Decrement the reference count on the inode */
|
||||
|
||||
mq_release(inode);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_close
|
||||
*
|
||||
* Description:
|
||||
* Release a reference count on a message queue inode.
|
||||
*
|
||||
* Parameters:
|
||||
* inode - The message queue inode
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void mq_release(FAR struct inode *inode)
|
||||
{
|
||||
/* Decrement the reference count on the inode */
|
||||
|
||||
inode_semtake();
|
||||
@ -155,32 +179,28 @@ int mq_close(mqd_t mqdes)
|
||||
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 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 OK;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Deallocate the message descriptor */
|
||||
|
||||
mq_desfree(mqdes);
|
||||
|
||||
sched_unlock();
|
||||
inode_semgive();
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* sched/mqueue/mq_open.c
|
||||
* fs/mqueue/mq_open.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
@ -64,11 +64,6 @@
|
||||
/****************************************************************************
|
||||
* Pre-procesor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_FS_MQUEUE_MPATH
|
||||
# define CONFIG_FS_MQUEUE_MPATH "/var/mqueue"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************
|
||||
* sched/mqueue/mq_unlink.c
|
||||
* fs/mqueue/mq_unlink.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -39,10 +39,14 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <mqueue.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/mqueue.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "mqueue/mqueue.h"
|
||||
|
||||
/************************************************************************
|
||||
@ -88,58 +92,80 @@
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
int mq_unlink(const char *mq_name)
|
||||
int mq_unlink(FAR const char *mq_name)
|
||||
{
|
||||
FAR struct mqueue_inode_s *msgq;
|
||||
irqstate_t saved_state;
|
||||
int ret = ERROR;
|
||||
FAR struct inode *inode;
|
||||
FAR const char *relpath = NULL;
|
||||
char fullpath[MAX_MQUEUE_PATH];
|
||||
int errcode;
|
||||
int ret;
|
||||
|
||||
/* Verify the input values */
|
||||
/* Get the full path to the message queue */
|
||||
|
||||
snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name);
|
||||
|
||||
/* Get the inode for this message queue. */
|
||||
|
||||
if (mq_name)
|
||||
{
|
||||
sched_lock();
|
||||
|
||||
/* Find the named message queue */
|
||||
|
||||
msgq = mq_findnamed(mq_name);
|
||||
if (msgq)
|
||||
inode = inode_find(fullpath, &relpath);
|
||||
if (!inode)
|
||||
{
|
||||
/* If it is no longer connected, then we can just
|
||||
* discard the message queue now.
|
||||
/* There is no inode that includes in this path */
|
||||
|
||||
errcode = ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Verify that what we found is, indeed, a message queue */
|
||||
|
||||
if (!INODE_IS_MQUEUE(inode))
|
||||
{
|
||||
errcode = ENXIO;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Refuse to unlink the inode if it has children. I.e., if it is
|
||||
* functioning as a directory and the directory is not empty.
|
||||
*/
|
||||
|
||||
if (!msgq->nconnect)
|
||||
inode_semtake();
|
||||
if (inode->i_child != NULL)
|
||||
{
|
||||
/* Remove the message queue from the list of all
|
||||
* message queues
|
||||
errcode = ENOTEMPTY;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Remove the old inode from the tree. Because we hold a reference count
|
||||
* on the inode, it will not be deleted now. This will set the
|
||||
* FSNODEFLAG_DELETED bit in the inode flags.
|
||||
*/
|
||||
|
||||
saved_state = irqsave();
|
||||
(void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues);
|
||||
irqrestore(saved_state);
|
||||
ret = inode_remove(fullpath);
|
||||
|
||||
/* Then deallocate it (and any messages left in it) */
|
||||
|
||||
mq_msgqfree(msgq);
|
||||
}
|
||||
|
||||
/* If the message queue is still connected to a message descriptor,
|
||||
* then mark it for deletion when the last message descriptor is
|
||||
* closed
|
||||
/* inode_remove() should always fail with -EBUSY because we hae a reference
|
||||
* on the inode. -EBUSY means taht the inode was, indeed, unlinked but
|
||||
* thatis could not be freed because there are refrences.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
msgq->unlinked = true;
|
||||
}
|
||||
DEBUGASSERT(ret >= 0 || ret == -EBUSY);
|
||||
UNUSED(ret);
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
/* Now we do not release the reference count in the normal way (by calling
|
||||
* inode release. Rather, we call sem_close(). sem_close will decrement
|
||||
* the reference count on the inode. But it will also free the message queue
|
||||
* if that reference count decrements to zero. Since we hold one reference,
|
||||
* that can only occur if the message queue is not in-use.
|
||||
*/
|
||||
|
||||
sched_unlock();
|
||||
}
|
||||
inode_semgive();
|
||||
mq_release(inode);
|
||||
return OK;
|
||||
|
||||
return ret;
|
||||
errout_with_semaphore:
|
||||
inode_semgive();
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,13 @@
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_FS_MQUEUE_MPATH
|
||||
# define CONFIG_FS_MQUEUE_MPATH "/var/mqueue"
|
||||
#endif
|
||||
|
||||
/* Sizes of things */
|
||||
|
||||
#define MAX_MQUEUE_PATH 64
|
||||
|
||||
@ -68,6 +75,22 @@ extern "C"
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mq_close
|
||||
*
|
||||
* Description:
|
||||
* Release a reference count on a message queue inode.
|
||||
*
|
||||
* Parameters:
|
||||
* inode - The message queue inode
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void mq_release(FAR struct inode *inode);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user