Squashed commit of the following:

Change all calls to mq_send() and mq_timedsend() in the OS to calls to nxmq_send() and nxmq_timedsend(), making appropriate changes for differences in return values.

    sched/mqueue:  Add internal function nxmq_send() and nxmq_timedsend() that are equivalent to mq_send() and mq_timedsend() except that they do not create cancellation points and do to not modify the errno variable.
This commit is contained in:
Gregory Nutt
2017-10-10 08:43:10 -06:00
parent c5a5a5a1b6
commit fca07be1df
22 changed files with 497 additions and 306 deletions
+4 -3
View File
@@ -53,8 +53,9 @@
#include <debug.h> #include <debug.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h> #include <nuttx/mqueue.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/fs/fs.h>
#include <nuttx/audio/audio.h> #include <nuttx/audio/audio.h>
#include <mqueue.h> #include <mqueue.h>
@@ -716,7 +717,7 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
msg.session = session; msg.session = session;
#endif #endif
apb->flags |= AUDIO_APB_DEQUEUED; apb->flags |= AUDIO_APB_DEQUEUED;
mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), (void)nxmq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg),
CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO);
} }
} }
@@ -754,7 +755,7 @@ static inline void audio_complete(FAR struct audio_upperhalf_s *upper,
#ifdef CONFIG_AUDIO_MULTI_SESSION #ifdef CONFIG_AUDIO_MULTI_SESSION
msg.session = session; msg.session = session;
#endif #endif
mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), (void)nxmq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg),
CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO);
} }
} }
+3 -2
View File
@@ -3,7 +3,7 @@
* *
* A do-nothinig audio device driver to simplify testing of audio decoders. * A do-nothinig audio device driver to simplify testing of audio decoders.
* *
* Copyright (C) 2014 Gregory Nutt. All rights reserved. * Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -53,6 +53,7 @@
#include <debug.h> #include <debug.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/mqueue.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h> #include <nuttx/fs/ioctl.h>
#include <nuttx/audio/audio.h> #include <nuttx/audio/audio.h>
@@ -589,7 +590,7 @@ static int null_stop(FAR struct audio_lowerhalf_s *dev)
term_msg.msgId = AUDIO_MSG_STOP; term_msg.msgId = AUDIO_MSG_STOP;
term_msg.u.data = 0; term_msg.u.data = 0;
mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg),
CONFIG_AUDIO_NULL_MSG_PRIO); CONFIG_AUDIO_NULL_MSG_PRIO);
/* Join the worker thread */ /* Join the worker thread */
+7 -10
View File
@@ -53,6 +53,7 @@
#include <debug.h> #include <debug.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/mqueue.h>
#include <nuttx/clock.h> #include <nuttx/clock.h>
#include <nuttx/wqueue.h> #include <nuttx/wqueue.h>
#include <nuttx/i2c/i2c_master.h> #include <nuttx/i2c/i2c_master.h>
@@ -963,11 +964,11 @@ cs43l22_senddone(FAR struct i2s_dev_s *i2s,
*/ */
msg.msgId = AUDIO_MSG_COMPLETE; msg.msgId = AUDIO_MSG_COMPLETE;
ret = mq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), ret = nxmq_send(priv->mq, (FAR const char *)&msg, sizeof(msg),
CONFIG_CS43L22_MSG_PRIO); CONFIG_CS43L22_MSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
auderr("ERROR: mq_send failed: %d\n", errno); auderr("ERROR: nxmq_send failed: %d\n", ret);
} }
} }
@@ -1225,7 +1226,7 @@ static int cs43l22_stop(FAR struct audio_lowerhalf_s *dev)
term_msg.msgId = AUDIO_MSG_STOP; term_msg.msgId = AUDIO_MSG_STOP;
term_msg.u.data = 0; term_msg.u.data = 0;
mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg),
CONFIG_CS43L22_MSG_PRIO); CONFIG_CS43L22_MSG_PRIO);
/* Join the worker thread */ /* Join the worker thread */
@@ -1341,15 +1342,11 @@ static int cs43l22_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
term_msg.msgId = AUDIO_MSG_ENQUEUE; term_msg.msgId = AUDIO_MSG_ENQUEUE;
term_msg.u.data = 0; term_msg.u.data = 0;
ret = mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), ret = nxmq_send(priv->mq, (FAR const char *)&term_msg,
CONFIG_CS43L22_MSG_PRIO); sizeof(term_msg), CONFIG_CS43L22_MSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
int errcode = errno; auderr("ERROR: nxmq_send failed: %d\n", ret);
DEBUGASSERT(errcode > 0);
auderr("ERROR: mq_send failed: %d\n", errcode);
UNUSED(errcode);
} }
} }
+5 -4
View File
@@ -55,6 +55,7 @@
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/signal.h> #include <nuttx/signal.h>
#include <nuttx/mqueue.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h> #include <nuttx/fs/ioctl.h>
#include <nuttx/audio/audio.h> #include <nuttx/audio/audio.h>
@@ -1222,7 +1223,7 @@ static int vs1053_dreq_isr(int irq, FAR void *context, FAR void *arg)
if (dev->running) if (dev->running)
{ {
msg.msgId = AUDIO_MSG_DATA_REQUEST; msg.msgId = AUDIO_MSG_DATA_REQUEST;
mq_send(dev->mq, (FAR const char *)&msg, sizeof(msg), (void)nxmq_send(dev->mq, (FAR const char *)&msg, sizeof(msg),
CONFIG_VS1053_MSG_PRIO); CONFIG_VS1053_MSG_PRIO);
} }
else else
@@ -1513,7 +1514,7 @@ static int vs1053_stop(FAR struct audio_lowerhalf_s *lower)
term_msg.msgId = AUDIO_MSG_STOP; term_msg.msgId = AUDIO_MSG_STOP;
term_msg.u.data = 0; term_msg.u.data = 0;
mq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg), (void)nxmq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg),
CONFIG_VS1053_MSG_PRIO); CONFIG_VS1053_MSG_PRIO);
/* Join the worker thread */ /* Join the worker thread */
@@ -1627,8 +1628,8 @@ static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower,
{ {
term_msg.msgId = AUDIO_MSG_ENQUEUE; term_msg.msgId = AUDIO_MSG_ENQUEUE;
term_msg.u.data = 0; term_msg.u.data = 0;
mq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg), (void)nxmq_send(dev->mq, (FAR const char *)&term_msg,
CONFIG_VS1053_MSG_PRIO); sizeof(term_msg), CONFIG_VS1053_MSG_PRIO);
} }
} }
+6 -10
View File
@@ -1360,11 +1360,11 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s,
*/ */
msg.msgId = AUDIO_MSG_COMPLETE; msg.msgId = AUDIO_MSG_COMPLETE;
ret = mq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), ret = nxmq_send(priv->mq, (FAR const char *)&msg, sizeof(msg),
CONFIG_WM8904_MSG_PRIO); CONFIG_WM8904_MSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
auderr("ERROR: mq_send failed: %d\n", errno); auderr("ERROR: nxmq_send failed: %d\n", ret);
} }
} }
@@ -1622,7 +1622,7 @@ static int wm8904_stop(FAR struct audio_lowerhalf_s *dev)
term_msg.msgId = AUDIO_MSG_STOP; term_msg.msgId = AUDIO_MSG_STOP;
term_msg.u.data = 0; term_msg.u.data = 0;
mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg),
CONFIG_WM8904_MSG_PRIO); CONFIG_WM8904_MSG_PRIO);
/* Join the worker thread */ /* Join the worker thread */
@@ -1738,15 +1738,11 @@ static int wm8904_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
term_msg.msgId = AUDIO_MSG_ENQUEUE; term_msg.msgId = AUDIO_MSG_ENQUEUE;
term_msg.u.data = 0; term_msg.u.data = 0;
ret = mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), ret = nxmq_send(priv->mq, (FAR const char *)&term_msg,
CONFIG_WM8904_MSG_PRIO); sizeof(term_msg), CONFIG_WM8904_MSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
int errcode = errno; auderr("ERROR: nxmq_send failed: %d\n", ret);
DEBUGASSERT(errcode > 0);
auderr("ERROR: mq_send failed: %d\n", errcode);
UNUSED(errcode);
} }
} }
+3 -1
View File
@@ -71,6 +71,7 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/signal.h> #include <nuttx/signal.h>
#include <nuttx/semaphore.h> #include <nuttx/semaphore.h>
#include <nuttx/mqueue.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h> #include <nuttx/spi/spi.h>
@@ -702,7 +703,8 @@ static void *cc3000_worker(FAR void *arg)
priv->state = eSPI_STATE_READ_READY; priv->state = eSPI_STATE_READ_READY;
priv->rx_buffer.len = data_to_recv; priv->rx_buffer.len = data_to_recv;
ret = mq_send(priv->queue, (FAR const char *)&priv->rx_buffer, ret = nxmq_send(priv->queue,
(FAR const char *)&priv->rx_buffer,
sizeof(priv->rx_buffer), 1); sizeof(priv->rx_buffer), 1);
DEBUGASSERT(ret >= 0); DEBUGASSERT(ret >= 0);
UNUSED(ret); UNUSED(ret);
+20 -10
View File
@@ -55,11 +55,11 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_close_group * Name: nxmq_close_group
* *
* Description: * Description:
* This function is used to indicate that all threads in the group are * This function is used to indicate that all threads in the group are
* finished with the specified message queue mqdes. The mq_close_group() * finished with the specified message queue mqdes. The nxmq_close_group()
* deallocates any system resources allocated by the system for use by * deallocates any system resources allocated by the system for use by
* this task for its message queue. * this task for its message queue.
* *
@@ -68,12 +68,12 @@
* group - Group that has the open descriptor. * group - Group that has the open descriptor.
* *
* Return Value: * Return Value:
* 0 (OK) if the message queue is closed successfully, * Zero (OK) if the message queue is closed successfully. Otherwise, a
* otherwise, -1 (ERROR). * negated errno value is returned.
* *
****************************************************************************/ ****************************************************************************/
int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group) int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
{ {
FAR struct mqueue_inode_s *msgq; FAR struct mqueue_inode_s *msgq;
FAR struct inode *inode; FAR struct inode *inode;
@@ -93,7 +93,7 @@ int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
/* Close/free the message descriptor */ /* Close/free the message descriptor */
mq_desclose_group(mqdes, group); nxmq_desclose_group(mqdes, group);
/* Get the inode from the message queue structure */ /* Get the inode from the message queue structure */
@@ -130,8 +130,8 @@ int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group)
* otherwise, -1 (ERROR). * otherwise, -1 (ERROR).
* *
* Assumptions: * Assumptions:
* - The behavior of a task that is blocked on either a mq_send() or * - The behavior of a task that is blocked on either a [nx]mq_send() or
* mq_receive() is undefined when mq_close() is called. * [nx]mq_receive() is undefined when mq_close() is called.
* - The results of using this message queue descriptor after a successful * - The results of using this message queue descriptor after a successful
* return from mq_close() is undefined. * return from mq_close() is undefined.
* *
@@ -151,7 +151,17 @@ int mq_close(mqd_t mqdes)
rtcb = (FAR struct tcb_s *)sched_self(); rtcb = (FAR struct tcb_s *)sched_self();
DEBUGASSERT(mqdes != NULL && rtcb != NULL && rtcb->group != NULL); DEBUGASSERT(mqdes != NULL && rtcb != NULL && rtcb->group != NULL);
ret = mq_close_group(mqdes, rtcb->group); /* Then perform the close operation */
ret = nxmq_close_group(mqdes, rtcb->group);
#if 0
if (ret < 0) /* Currently, nxmq_close_group() only returns OK */
{
set_errno(-ret);
ret = ERROR;
}
#endif
sched_unlock(); sched_unlock();
return ret; return ret;
} }
@@ -193,7 +203,7 @@ void mq_inode_release(FAR struct inode *inode)
/* Free the message queue (and any messages left in it) */ /* Free the message queue (and any messages left in it) */
mq_msgqfree(msgq); nxmq_free_msgq(msgq);
inode->u.i_mqueue = NULL; inode->u.i_mqueue = NULL;
/* Release and free the inode container. If it has been properly /* Release and free the inode container. If it has been properly
+4 -4
View File
@@ -164,7 +164,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
/* Create a message queue descriptor for the current thread */ /* Create a message queue descriptor for the current thread */
msgq = inode->u.i_mqueue; msgq = inode->u.i_mqueue;
mqdes = mq_descreate(NULL, msgq, oflags); mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!mqdes) if (!mqdes)
{ {
errcode = ENOMEM; errcode = ENOMEM;
@@ -208,7 +208,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
* be created with a reference count of zero. * be created with a reference count of zero.
*/ */
msgq = (FAR struct mqueue_inode_s *)mq_msgqalloc(mode, attr); msgq = (FAR struct mqueue_inode_s *)nxmq_alloc_msgq(mode, attr);
if (!msgq) if (!msgq)
{ {
errcode = ENOSPC; errcode = ENOSPC;
@@ -217,7 +217,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
/* Create a message queue descriptor for the TCB */ /* Create a message queue descriptor for the TCB */
mqdes = mq_descreate(NULL, msgq, oflags); mqdes = nxmq_create_des(NULL, msgq, oflags);
if (!mqdes) if (!mqdes)
{ {
errcode = ENOMEM; errcode = ENOMEM;
@@ -240,7 +240,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
return mqdes; return mqdes;
errout_with_msgq: errout_with_msgq:
mq_msgqfree(msgq); nxmq_free_msgq(msgq);
inode->u.i_mqueue = NULL; inode->u.i_mqueue = NULL;
errout_with_inode: errout_with_inode:
+5 -23
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* graphics/nxmu/nxmu_sendclient.c * graphics/nxmu/nxmu_sendclient.c
* *
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -43,28 +43,10 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/mqueue.h>
#include "nxfe.h" #include "nxfe.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -102,10 +84,10 @@ int nxmu_sendclient(FAR struct nxfe_conn_s *conn, FAR const void *msg,
/* Send the message to the client */ /* Send the message to the client */
ret = mq_send(conn->swrmq, msg, msglen, NX_CLIMSG_PRIO); ret = nxmq_send(conn->swrmq, msg, msglen, NX_CLIMSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
gerr("ERROR: mq_send failed: %d\n", errno); gerr("ERROR: nxmq_send failed: %d\n", ret);
} }
return ret; return ret;
+124 -16
View File
@@ -1,7 +1,8 @@
/**************************************************************************** /****************************************************************************
* include/nuttx/mqueue.h * include/nuttx/mqueue.h
* *
* Copyright (C) 2007, 2009, 2011, 2014-2016 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2011, 2014-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -56,6 +57,37 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Most internal nxsig_* interfaces are not available in the user space in
* PROTECTED and KERNEL builds. In that context, the application signal
* interfaces must be used. The differences between the two sets of
* interfaces are: (1) the nxsig_* interfaces do not cause cancellation
* points and (2) they do not modify the errno variable.
*
* This is only important when compiling libraries (libc or libnx) that are
* used both by the OS (libkc.a and libknx.a) or by the applications
* (libuc.a and libunx.a). The that case, the correct interface must be
* used for the build context.
*
* The interfaces sigtimedwait(), sigwait(), sigwaitinfo(), sleep(),
* nanosleep(), and usleep() are cancellation points.
*
* REVISIT: The fact that these interfaces are cancellation points is an
* issue and may cause violations: It use of these internally will cause
* the calling function to become a cancellation points!
*/
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
# define _MQ_SEND(d,m,l,p) nxmq_send(d,m,l,p)
# define _MQ_TIMEDSEND(d,m,l,p,t) nxmq_send(d,m,l,p,t)
# define _MQ_ERRNO(r) (-(r))
# define _MQ_ERRVAL(r) (r)
#else
# define _MQ_SEND(d,m,l,p) mq_send(d,m,l,p)
# define _MQ_TIMEDSEND(d,m,l,p,t) mq_send(d,m,l,p,t)
# define _MQ_ERRNO(r) errno
# define _MQ_ERRVAL(r) (-errno)
#endif
/**************************************************************************** /****************************************************************************
* Public Type Declarations * Public Type Declarations
****************************************************************************/ ****************************************************************************/
@@ -111,12 +143,88 @@ extern "C"
#define EXTERN extern #define EXTERN extern
#endif #endif
struct mq_attr; /* Forward reference */
struct tcb_s; /* Forward reference */ struct tcb_s; /* Forward reference */
struct mq_attr; /* Forward reference */
struct timespec; /* Forward reference */
struct task_group_s; /* Forward reference */ struct task_group_s; /* Forward reference */
/**************************************************************************** /****************************************************************************
* Name: mq_msgqfree * Name: nxmq_send
*
* Description:
* This function adds the specified message (msg) to the message queue
* (mqdes). This is an internal OS interface. It is functionally
* equivalent to mq_send() except that:
*
* - It is not a cancellaction point, and
* - It does not modify the errno value.
*
* See comments with mq_send() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mqdes - Message queue descriptor
* msg - Message to send
* msglen - The length of the message in bytes
* prio - The priority of the message
*
* 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.
* (see mq_send() for the list list valid return values).
*
****************************************************************************/
int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio);
/****************************************************************************
* Name: nxmq_timedsend
*
* Description:
* This function adds the specified message (msg) to the message queue
* (mqdes). nxmq_timedsend() behaves just like mq_send(), except that if
* the queue is full and the O_NONBLOCK flag is not enabled for the
* message queue description, then abstime points to a structure which
* specifies a ceiling on the time for which the call will block.
*
* nxmq_timedsend() is functionally equivalent to mq_timedsend() except
* that:
*
* - It is not a cancellaction point, and
* - It does not modify the errno value.
*
* See comments with mq_timedsend() for a more complete description of the
* behavior of this function
*
* Input Parameters:
* mqdes - Message queue descriptor
* msg - Message to send
* msglen - The length of the message in bytes
* prio - The priority of the message
* abstime - the absolute time to wait until a timeout is decleared
*
* 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.
* (see mq_timedsend() for the list list valid return values).
*
* EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the
* message queue description referred to by mqdes.
* EINVAL Either msg or mqdes 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.
* EINTR The call was interrupted by a signal handler.
*
****************************************************************************/
int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
FAR const struct timespec *abstime);
/****************************************************************************
* Name: nxmq_free_msgq
* *
* Description: * Description:
* This function deallocates an initialized message queue structure. * This function deallocates an initialized message queue structure.
@@ -133,10 +241,10 @@ struct task_group_s; /* Forward reference */
* *
****************************************************************************/ ****************************************************************************/
void mq_msgqfree(FAR struct mqueue_inode_s *msgq); void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq);
/**************************************************************************** /****************************************************************************
* Name: mq_msgqalloc * Name: nxmq_alloc_msgq
* *
* Description: * Description:
* This function implements a part of the POSIX message queue open logic. * This function implements a part of the POSIX message queue open logic.
@@ -154,11 +262,11 @@ void mq_msgqfree(FAR struct mqueue_inode_s *msgq);
* *
****************************************************************************/ ****************************************************************************/
FAR struct mqueue_inode_s *mq_msgqalloc(mode_t mode, FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode,
FAR struct mq_attr *attr); FAR struct mq_attr *attr);
/**************************************************************************** /****************************************************************************
* Name: mq_descreate * Name: nxmq_create_des
* *
* Description: * Description:
* Create a message queue descriptor for the specified TCB * Create a message queue descriptor for the specified TCB
@@ -174,15 +282,15 @@ FAR struct mqueue_inode_s *mq_msgqalloc(mode_t mode,
* *
****************************************************************************/ ****************************************************************************/
mqd_t mq_descreate(FAR struct tcb_s *mtcb, FAR struct mqueue_inode_s *msgq, mqd_t nxmq_create_des(FAR struct tcb_s *mtcb,
int oflags); FAR struct mqueue_inode_s *msgq, int oflags);
/**************************************************************************** /****************************************************************************
* Name: mq_close_group * Name: nxmq_close_group
* *
* Description: * Description:
* This function is used to indicate that all threads in the group are * This function is used to indicate that all threads in the group are
* finished with the specified message queue mqdes. The mq_close_group() * finished with the specified message queue mqdes. nxmq_close_group()
* deallocates any system resources allocated by the system for use by * deallocates any system resources allocated by the system for use by
* this task for its message queue. * this task for its message queue.
* *
@@ -191,15 +299,15 @@ mqd_t mq_descreate(FAR struct tcb_s *mtcb, FAR struct mqueue_inode_s *msgq,
* group - Group that has the open descriptor. * group - Group that has the open descriptor.
* *
* Return Value: * Return Value:
* 0 (OK) if the message queue is closed successfully, * Zero (OK) if the message queue is closed successfully. Otherwise, a
* otherwise, -1 (ERROR). * negated errno value is returned.
* *
****************************************************************************/ ****************************************************************************/
int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group); int nxmq_close_group(mqd_t mqdes, FAR struct task_group_s *group);
/**************************************************************************** /****************************************************************************
* Name: mq_desclose_group * Name: nxmq_desclose_group
* *
* Description: * Description:
* This function performs the portion of the mq_close operation related * This function performs the portion of the mq_close operation related
@@ -217,7 +325,7 @@ int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group);
* *
****************************************************************************/ ****************************************************************************/
void mq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group); void nxmq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group);
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
+4 -3
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* libnx/nxmu/nxmu_sendserver.c * libnx/nxmu/nxmu_sendserver.c
* *
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Copyright (C) 2012-2013, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,7 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/mqueue.h>
#include <nuttx/nx/nxmu.h> #include <nuttx/nx/nxmu.h>
/**************************************************************************** /****************************************************************************
@@ -82,10 +83,10 @@ int nxmu_sendserver(FAR struct nxfe_conn_s *conn, FAR const void *msg,
/* Send the message to the server */ /* Send the message to the server */
ret = mq_send(conn->cwrmq, msg, msglen, NX_SVRMSG_PRIO); ret = _MQ_SEND(conn->cwrmq, msg, msglen, NX_SVRMSG_PRIO);
if (ret < 0) if (ret < 0)
{ {
gerr("ERROR: mq_send failed: %d\n", errno); gerr("ERROR: _MQ_SEND failed: %d\n", _MQ_ERRNO(rer));
} }
return ret; return ret;
+3 -3
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/mqueue/mq_desclose.c * sched/mqueue/mq_desclose.c
* *
* Copyright (C) 2007, 2009, 2013-2016 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2013-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,7 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_desclose_group * Name: nxmq_desclose_group
* *
* Description: * Description:
* This function performs the portion of the mq_close operation related * This function performs the portion of the mq_close operation related
@@ -90,7 +90,7 @@
* *
****************************************************************************/ ****************************************************************************/
void mq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group) void nxmq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group)
{ {
FAR struct mqueue_inode_s *msgq; FAR struct mqueue_inode_s *msgq;
+3 -3
View File
@@ -104,7 +104,7 @@ static mqd_t nxmq_alloc_des(void)
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_descreate * Name: nxmq_create_des
* *
* Description: * Description:
* Create a message queue descriptor for the specified TCB * Create a message queue descriptor for the specified TCB
@@ -120,8 +120,8 @@ static mqd_t nxmq_alloc_des(void)
* *
****************************************************************************/ ****************************************************************************/
mqd_t mq_descreate(FAR struct tcb_s *mtcb, FAR struct mqueue_inode_s *msgq, mqd_t nxmq_create_des(FAR struct tcb_s *mtcb,
int oflags) FAR struct mqueue_inode_s *msgq, int oflags)
{ {
FAR struct task_group_s *group; FAR struct task_group_s *group;
mqd_t mqdes; mqd_t mqdes;
+3 -3
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/mqueue/mq_msgqalloc.c * sched/mqueue/mq_msgqalloc.c
* *
* Copyright (C) 2014 Gregory Nutt. All rights reserved. * Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,7 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_msgqalloc * Name: nxmq_alloc_msgq
* *
* Description: * Description:
* This function implements a part of the POSIX message queue open logic. * This function implements a part of the POSIX message queue open logic.
@@ -72,7 +72,7 @@
* *
****************************************************************************/ ****************************************************************************/
FAR struct mqueue_inode_s *mq_msgqalloc(mode_t mode, FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode,
FAR struct mq_attr *attr) FAR struct mq_attr *attr)
{ {
FAR struct mqueue_inode_s *msgq; FAR struct mqueue_inode_s *msgq;
+2 -2
View File
@@ -48,7 +48,7 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_msgqfree * Name: nxmq_free_msgq
* *
* Description: * Description:
* This function deallocates an initialized message queue structure. * This function deallocates an initialized message queue structure.
@@ -65,7 +65,7 @@
* *
****************************************************************************/ ****************************************************************************/
void mq_msgqfree(FAR struct mqueue_inode_s *msgq) void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq)
{ {
FAR struct mqueue_msg_s *curr; FAR struct mqueue_msg_s *curr;
FAR struct mqueue_msg_s *next; FAR struct mqueue_msg_s *next;
+1 -1
View File
@@ -67,6 +67,6 @@ void nxmq_release(FAR struct task_group_s *group)
{ {
while (group->tg_msgdesq.head) while (group->tg_msgdesq.head)
{ {
mq_close_group((mqd_t)group->tg_msgdesq.head, group); (void)nxmq_close_group((mqd_t)group->tg_msgdesq.head, group);
} }
} }
+102 -61
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/mqueue/mq_send.c * sched/mqueue/mq_send.c
* *
* Copyright (C) 2007, 2009, 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -55,67 +55,48 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_send * Name: nxmq_send
* *
* Description: * Description:
* This function adds the specified message (msg) to the message queue * This function adds the specified message (msg) to the message queue
* (mqdes). The "msglen" parameter specifies the length of the message * (mqdes). This is an internal OS interface. It is functionally
* in bytes pointed to by "msg." This length must not exceed the maximum * equivalent to mq_send() except that:
* message length from the mq_getattr().
* *
* If the message queue is not full, mq_send() place the message in the * - It is not a cancellaction point, and
* message queue at the position indicated by the "prio" argument. * - It does not modify the errno value.
* Messages with higher priority will be inserted before lower priority
* messages. The value of "prio" must not exceed MQ_PRIO_MAX.
* *
* If the specified message queue is full and O_NONBLOCK is not set in the * See comments with mq_send() for a more complete description of the
* message queue, then mq_send() will block until space becomes available * behavior of this function
* to the queue the message.
* *
* If the message queue is full and O_NONBLOCK is set, the message is not * Input Parameters:
* queued and ERROR is returned.
*
* Parameters:
* mqdes - Message queue descriptor * mqdes - Message queue descriptor
* msg - Message to send * msg - Message to send
* msglen - The length of the message in bytes * msglen - The length of the message in bytes
* prio - The priority of the message * prio - The priority of the message
* *
* Return Value: * Returned Value:
* On success, mq_send() returns 0 (OK); on error, -1 (ERROR) * This is an internal OS interface and should not be used by applications.
* is returned, with errno set to indicate the error: * It follows the NuttX internal error return policy: Zero (OK) is
* * returned on success. A negated errno value is returned on failure.
* EAGAIN The queue was full and the O_NONBLOCK flag was set for the * (see mq_send() for the list list valid return values).
* message queue description referred to by mqdes.
* EINVAL Either msg or mqdes 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.
* EINTR The call was interrupted by a signal handler.
*
* Assumptions/restrictions:
* *
****************************************************************************/ ****************************************************************************/
int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio) int nxmq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
{ {
FAR struct mqueue_inode_s *msgq; FAR struct mqueue_inode_s *msgq;
FAR struct mqueue_msg_s *mqmsg = NULL; FAR struct mqueue_msg_s *mqmsg = NULL;
irqstate_t flags; irqstate_t flags;
int ret = ERROR; int ret;
/* mq_send() is a cancellation point */
(void)enter_cancellation_point();
/* Verify the input parameters -- setting errno appropriately /* Verify the input parameters -- setting errno appropriately
* on any failures to verify. * on any failures to verify.
*/ */
if (nxmq_verify_send(mqdes, msg, msglen, prio) != OK) ret = nxmq_verify_send(mqdes, msg, msglen, prio);
if (ret < 0);
{ {
leave_cancellation_point(); return ret;
return ERROR;
} }
/* Get a pointer to the message queue */ /* Get a pointer to the message queue */
@@ -130,37 +111,36 @@ int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
* non-FULL. This would fail with EAGAIN, EINTR, or ETIMEOUT. * non-FULL. This would fail with EAGAIN, EINTR, or ETIMEOUT.
*/ */
mqmsg = NULL;
flags = enter_critical_section(); flags = enter_critical_section();
if (up_interrupt_context() || /* In an interrupt handler */ ret = OK;
msgq->nmsgs < msgq->maxmsgs || /* OR Message queue not full */
nxmq_wait_send(mqdes) == OK) /* OR Successfully waited for mq not full */ if (!up_interrupt_context()) /* In an interrupt handler? */
{ {
/* Allocate the message */ /* No.. Not in an interrupt handler. Is the message queue FULL? */
if (msgq->nmsgs >= msgq->maxmsgs) /* Message queue not-FULL? */
{
/* Yes.. the message queue is full. Wait for space to become
* available in the message queue.
*/
ret = nxmq_wait_send(mqdes);
}
}
/* ret can only be negative if nxmq_wait_send failed */
leave_critical_section(flags); leave_critical_section(flags);
if (ret >= 0)
{
/* Now allocate the message. */
mqmsg = nxmq_alloc_msg(); mqmsg = nxmq_alloc_msg();
/* Check if the message was sucessfully allocated */ /* Check if the message was sucessfully allocated */
if (mqmsg == NULL) ret = (mqmsg == NULL) ? -ENOMEM : OK;
{
/* No... nxmq_alloc_msg() does not set the errno value */
set_errno(ENOMEM);
}
}
else
{
/* We cannot send the message (and didn't even try to allocate it)
* because:
* - We are not in an interrupt handler AND
* - The message queue is full AND
* - When we tried waiting, the wait was unsuccessful.
*
* In this case nxmq_wait_send() has already set the errno value.
*/
leave_critical_section(flags);
} }
/* Check if we were able to get a message structure -- this can fail /* Check if we were able to get a message structure -- this can fail
@@ -183,6 +163,67 @@ int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
} }
sched_unlock(); sched_unlock();
return ret;
}
/****************************************************************************
* Name: mq_send
*
* Description:
* This function adds the specified message (msg) to the message queue
* (mqdes). The "msglen" parameter specifies the length of the message
* in bytes pointed to by "msg." This length must not exceed the maximum
* message length from the mq_getattr().
*
* If the message queue is not full, mq_send() place the message in the
* message queue at the position indicated by the "prio" argument.
* Messages with higher priority will be inserted before lower priority
* messages. The value of "prio" must not exceed MQ_PRIO_MAX.
*
* If the specified message queue is full and O_NONBLOCK is not set in the
* message queue, then mq_send() will block until space becomes available
* to the queue the message.
*
* If the message queue is full and O_NONBLOCK is set, the message is not
* queued and ERROR is returned.
*
* Input Parameters:
* mqdes - Message queue descriptor
* msg - Message to send
* msglen - The length of the message in bytes
* prio - The priority of the message
*
* Returned Value:
* On success, mq_send() returns 0 (OK); on error, -1 (ERROR)
* is returned, with errno set to indicate the error:
*
* EAGAIN The queue was full and the O_NONBLOCK flag was set for the
* message queue description referred to by mqdes.
* EINVAL Either msg or mqdes 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.
* EINTR The call was interrupted by a signal handler.
*
****************************************************************************/
int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
{
int ret;
/* mq_send() is a cancellation point */
(void)enter_cancellation_point();
/* Let nxmq_send() do all of the work */
ret = nxmq_send(mqdes, msg, msglen, prio);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
leave_cancellation_point(); leave_cancellation_point();
return ret; return ret;
} }
+48 -48
View File
@@ -69,27 +69,25 @@
* Name: nxmq_verify_send * Name: nxmq_verify_send
* *
* Description: * Description:
* This is internal, common logic shared by both mq_send and mq_timesend. * This is internal, common logic shared by both [nx]mq_send and
* This function verifies the input parameters that are common to both * [nx]mq_timesend. This function verifies the input parameters that are
* functions. * common to both functions.
* *
* Parameters: * Input Parameters:
* mqdes - Message queue descriptor * mqdes - Message queue descriptor
* msg - Message to send * msg - Message to send
* msglen - The length of the message in bytes * msglen - The length of the message in bytes
* prio - The priority of the message * prio - The priority of the message
* *
* Return Value: * Returned Value:
* One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and * One success, 0 (OK) is returned. On failure, a negated errno value is
* the errno is set appropriately: * returned.
* *
* EINVAL Either msg or mqdes is NULL or the value of prio is invalid. * EINVAL Either msg or mqdes is NULL or the value of prio is invalid.
* EPERM Message queue opened not opened for writing. * EPERM Message queue opened not opened for writing.
* EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the
* message queue. * message queue.
* *
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
@@ -99,20 +97,17 @@ int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
if (!msg || !mqdes || prio < 0 || prio > MQ_PRIO_MAX) if (!msg || !mqdes || prio < 0 || prio > MQ_PRIO_MAX)
{ {
set_errno(EINVAL); return -EINVAL;
return ERROR;
} }
if ((mqdes->oflags & O_WROK) == 0) if ((mqdes->oflags & O_WROK) == 0)
{ {
set_errno(EPERM); return -EPERM;
return ERROR;
} }
if (msglen > (size_t)mqdes->msgq->maxmsgsize) if (msglen > (size_t)mqdes->msgq->maxmsgsize)
{ {
set_errno(EMSGSIZE); return -EMSGSIZE;
return ERROR;
} }
return OK; return OK;
@@ -139,7 +134,7 @@ int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen,
* Inputs: * Inputs:
* None * None
* *
* Return Value: * Returned Value:
* A reference to the allocated msg structure. On a failure to allocate, * A reference to the allocated msg structure. On a failure to allocate,
* this function PANICs. * this function PANICs.
* *
@@ -207,15 +202,16 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void)
* Name: nxmq_wait_send * Name: nxmq_wait_send
* *
* Description: * Description:
* This is internal, common logic shared by both mq_send and mq_timesend. * This is internal, common logic shared by both [nx]mq_send and
* This function waits until the message queue is not full. * [nx]mq_timesend. This function waits until the message queue is not
* full.
* *
* Parameters: * Input Parameters:
* mqdes - Message queue descriptor * mqdes - Message queue descriptor
* *
* Return Value: * Returned Value:
* On success, mq_send() returns 0 (OK); on error, -1 (ERROR) is * On success, nxmq_wait_send() returns 0 (OK); a negated errno value is
* returned, with errno set to indicate the error: * returned on any failure:
* *
* EAGAIN The queue was full and the O_NONBLOCK flag was set for the * 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 mqdes.
@@ -233,23 +229,22 @@ int nxmq_wait_send(mqd_t mqdes)
{ {
FAR struct tcb_s *rtcb; FAR struct tcb_s *rtcb;
FAR struct mqueue_inode_s *msgq; FAR struct mqueue_inode_s *msgq;
int ret;
/* nxmq_wait_send() is not a cancellation point, but it is always called from #ifdef CONFIG_CANCELLATION_POINTS
* a cancellation point. /* nxmq_wait_send() is not a cancellation point, but may be called via
* mq_send() or mq_timedsend() which are cancellation points.
*/ */
if (enter_cancellation_point()) if (check_cancellation_point())
{ {
#ifdef CONFIG_CANCELLATION_POINTS
/* If there is a pending cancellation, then do not perform /* If there is a pending cancellation, then do not perform
* the wait. Exit now with ECANCELED. * the wait. Exit now with ECANCELED.
*/ */
set_errno(ECANCELED); return -ECANCELED;
leave_cancellation_point();
return ERROR;
#endif
} }
#endif
/* Get a pointer to the message queue */ /* Get a pointer to the message queue */
@@ -267,9 +262,7 @@ int nxmq_wait_send(mqd_t mqdes)
{ {
/* No... We will return an error to the caller. */ /* No... We will return an error to the caller. */
set_errno(EAGAIN); return -EAGAIN;
leave_cancellation_point();
return ERROR;
} }
/* Yes... We will not return control until the message queue is /* Yes... We will not return control until the message queue is
@@ -284,6 +277,8 @@ int nxmq_wait_send(mqd_t mqdes)
while (msgq->nmsgs >= msgq->maxmsgs) while (msgq->nmsgs >= msgq->maxmsgs)
{ {
int saved_errno;
/* Block until the message queue is no longer full. /* Block until the message queue is no longer full.
* When we are unblocked, we will try again * When we are unblocked, we will try again
*/ */
@@ -292,25 +287,32 @@ int nxmq_wait_send(mqd_t mqdes)
rtcb->msgwaitq = msgq; rtcb->msgwaitq = msgq;
msgq->nwaitnotfull++; msgq->nwaitnotfull++;
set_errno(OK); /* "Borrow" the per-task errno to communication wake-up error
* conditions.
*/
saved_errno = rtcb->pterrno;
rtcb->pterrno = OK;
up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL); up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL);
/* When we resume at this point, either (1) the message queue /* When we resume at this point, either (1) the message queue
* is no longer empty, or (2) the wait has been interrupted by * is no longer empty, or (2) the wait has been interrupted by
* a signal. We can detect the latter case be examining the * a signal. We can detect the latter case be examining the
* errno value (should be EINTR or ETIMEOUT). * per-task errno value (should be EINTR or ETIMEOUT).
*/ */
if (get_errno() != OK) ret = rtcb->pterrno;
rtcb->pterrno = saved_errno;
if (ret != OK)
{ {
leave_cancellation_point(); return -ret;
return ERROR;
} }
} }
} }
} }
leave_cancellation_point();
return OK; return OK;
} }
@@ -318,23 +320,21 @@ int nxmq_wait_send(mqd_t mqdes)
* Name: nxmq_do_send * Name: nxmq_do_send
* *
* Description: * Description:
* This is internal, common logic shared by both mq_send and mq_timesend. * This is internal, common logic shared by both [nx]mq_send and
* This function adds the specified message (msg) to the message queue * [nx]mq_timesend. This function adds the specified message (msg) to the
* (mqdes). Then it notifies any tasks that were waiting for message * message queue (mqdes). Then it notifies any tasks that were waiting
* queue notifications setup by mq_notify. And, finally, it awakens any * for message queue notifications setup by mq_notify. And, finally, it
* tasks that were waiting for the message not empty event. * awakens any tasks that were waiting for the message not empty event.
* *
* Parameters: * Input Parameters:
* mqdes - Message queue descriptor * mqdes - Message queue descriptor
* msg - Message to send * msg - Message to send
* msglen - The length of the message in bytes * msglen - The length of the message in bytes
* prio - The priority of the message * prio - The priority of the message
* *
* Return Value: * Returned Value:
* This function always returns OK. * This function always returns OK.
* *
* Assumptions/restrictions:
*
****************************************************************************/ ****************************************************************************/
int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg, int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
+108 -59
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/mqueue/mq_timedsend.c * sched/mqueue/mq_timedsend.c
* *
* Copyright (C) 2007-2009, 2011, 2013-2016 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011, 2013-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -67,11 +67,11 @@
* This function is called if the timeout elapses before the message queue * This function is called if the timeout elapses before the message queue
* becomes non-full. * becomes non-full.
* *
* Parameters: * Input Parameters:
* argc - the number of arguments (should be 1) * argc - the number of arguments (should be 1)
* pid - the task ID of the task to wakeup * pid - the task ID of the task to wakeup
* *
* Return Value: * Returned Value:
* None * None
* *
* Assumptions: * Assumptions:
@@ -99,7 +99,7 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid)
* punch and already changed the task's state. * punch and already changed the task's state.
*/ */
if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTFULL) if (wtcb != NULL && wtcb->task_state == TSTATE_WAIT_MQNOTFULL)
{ {
/* Restart with task with a timeout error */ /* Restart with task with a timeout error */
@@ -116,43 +116,36 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid)
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mq_send * Name: nxmq_timedsend
* *
* Description: * Description:
* This function adds the specificied message (msg) to the message queue * This function adds the specified message (msg) to the message queue
* (mqdes). The "msglen" parameter specifies the length of the message * (mqdes). nxmq_timedsend() behaves just like mq_send(), except
* in bytes pointed to by "msg." This length must not exceed the maximum * that if the queue is full and the O_NONBLOCK flag is not enabled for
* message length from the mq_getattr(). * the message queue description, then abstime points to a structure which
* specifies a ceiling on the time for which the call will block.
* *
* If the message queue is not full, mq_timedsend() place the message in the * nxmq_timedsend() is functionally equivalent to mq_timedsend() except
* message queue at the position indicated by the "prio" argrument. * that:
* Messages with higher priority will be inserted before lower priority
* messages. The value of "prio" must not exceed MQ_PRIO_MAX.
* *
* If the specified message queue is full and O_NONBLOCK is not set in the * - It is not a cancellaction point, and
* message queue, then mq_timedsend() will block until space becomes available * - It does not modify the errno value.
* to the queue the message or a timeout occurs.
* *
* mq_timedsend() behaves just like mq_send(), except that if the queue * See comments with mq_timedsend() for a more complete description of the
* is full and the O_NONBLOCK flag is not enabled for the message queue * behavior of this function
* description, then abstime points to a structure which specifies a
* ceiling on the time for which the call will block. This ceiling is an
* absolute timeout in seconds and nanoseconds since the Epoch (midnight
* on the morning of 1 January 1970).
* *
* If the message queue is full, and the timeout has already expired by * Input Parameters:
* the time of the call, mq_timedsend() returns immediately.
*
* Parameters:
* mqdes - Message queue descriptor * mqdes - Message queue descriptor
* msg - Message to send * msg - Message to send
* msglen - The length of the message in bytes * msglen - The length of the message in bytes
* prio - The priority of the message * prio - The priority of the message
* abstime - the absolute time to wait until a timeout is decleared * abstime - the absolute time to wait until a timeout is decleared
* *
* Return Value: * Returned Value:
* On success, mq_send() returns 0 (OK); on error, -1 (ERROR) * This is an internal OS interface and should not be used by applications.
* is returned, with errno set to indicate the error: * It follows the NuttX internal error return policy: Zero (OK) is
* returned on success. A negated errno value is returned on failure.
* (see mq_timedsend() for the list list valid return values).
* *
* EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the
* message queue description referred to by mqdes. * message queue description referred to by mqdes.
@@ -162,11 +155,9 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid)
* message queue. * message queue.
* EINTR The call was interrupted by a signal handler. * EINTR The call was interrupted by a signal handler.
* *
* Assumptions/restrictions:
*
****************************************************************************/ ****************************************************************************/
int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, int nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
FAR const struct timespec *abstime) FAR const struct timespec *abstime)
{ {
FAR struct tcb_s *rtcb = this_task(); FAR struct tcb_s *rtcb = this_task();
@@ -175,24 +166,16 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
irqstate_t flags; irqstate_t flags;
ssystime_t ticks; ssystime_t ticks;
int result; int result;
int ret = ERROR; int ret;
DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
/* mq_timedsend() is a cancellation point */ /* Verify the input parameters on any failures to verify. */
(void)enter_cancellation_point(); ret = nxmq_verify_send(mqdes, msg, msglen, prio);
if (ret < 0)
/* Verify the input parameters -- setting errno appropriately
* on any failures to verify.
*/
if (nxmq_verify_send(mqdes, msg, msglen, prio) != OK)
{ {
/* nxmq_verify_send() will set the errno appropriately */ return ret;
leave_cancellation_point();
return ERROR;
} }
/* Pre-allocate a message structure */ /* Pre-allocate a message structure */
@@ -204,9 +187,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
* errno value. * errno value.
*/ */
set_errno(ENOMEM); return -ENOMEM;
leave_cancellation_point();
return ERROR;
} }
/* Get a pointer to the message queue */ /* Get a pointer to the message queue */
@@ -236,7 +217,6 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
ret = nxmq_do_send(mqdes, mqmsg, msg, msglen, prio); ret = nxmq_do_send(mqdes, mqmsg, msg, msglen, prio);
sched_unlock(); sched_unlock();
leave_cancellation_point();
return ret; return ret;
} }
@@ -246,7 +226,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
{ {
result = EINVAL; ret = -EINVAL;
goto errout_with_mqmsg; goto errout_with_mqmsg;
} }
@@ -258,7 +238,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
rtcb->waitdog = wd_create(); rtcb->waitdog = wd_create();
if (!rtcb->waitdog) if (!rtcb->waitdog)
{ {
result = EINVAL; ret = -EINVAL;
goto errout_with_mqmsg; goto errout_with_mqmsg;
} }
@@ -285,6 +265,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
if (result != OK) if (result != OK)
{ {
ret = -result;
goto errout_in_critical_section; goto errout_in_critical_section;
} }
@@ -306,9 +287,8 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
if (ret < 0) if (ret < 0)
{ {
/* nxmq_wait_send() will set the errno, but the error exit will reset it */ /* nxmq_wait_send() failed. */
result = get_errno();
goto errout_in_critical_section; goto errout_in_critical_section;
} }
@@ -332,8 +312,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
return ret; return ret;
/* Exit here with (1) the scheduler locked, (2) a message allocated, (3) a /* Exit here with (1) the scheduler locked, (2) a message allocated, (3) a
* wdog allocated, and (4) interrupts disabled. The error code is in * wdog allocated, and (4) interrupts disabled.
* 'result'
*/ */
errout_in_critical_section: errout_in_critical_section:
@@ -348,8 +327,78 @@ errout_in_critical_section:
errout_with_mqmsg: errout_with_mqmsg:
nxmq_free_msg(mqmsg); nxmq_free_msg(mqmsg);
sched_unlock(); sched_unlock();
return ret;
set_errno(result); }
leave_cancellation_point();
return ERROR; /****************************************************************************
* Name: mq_timedsend
*
* Description:
* This function adds the specified message (msg) to the message queue
* (mqdes). The "msglen" parameter specifies the length of the message
* in bytes pointed to by "msg." This length must not exceed the maximum
* message length from the mq_getattr().
*
* If the message queue is not full, mq_timedsend() place the message in the
* message queue at the position indicated by the "prio" argrument.
* Messages with higher priority will be inserted before lower priority
* messages. The value of "prio" must not exceed MQ_PRIO_MAX.
*
* If the specified message queue is full and O_NONBLOCK is not set in the
* message queue, then mq_timedsend() will block until space becomes available
* to the queue the message or a timeout occurs.
*
* mq_timedsend() behaves just like mq_send(), except that if the queue
* is full and the O_NONBLOCK flag is not enabled for the message queue
* description, then abstime points to a structure which specifies a
* ceiling on the time for which the call will block. This ceiling is an
* absolute timeout in seconds and nanoseconds since the Epoch (midnight
* on the morning of 1 January 1970).
*
* If the message queue is full, and the timeout has already expired by
* the time of the call, mq_timedsend() returns immediately.
*
* Input Parameters:
* mqdes - Message queue descriptor
* msg - Message to send
* msglen - The length of the message in bytes
* prio - The priority of the message
* abstime - the absolute time to wait until a timeout is decleared
*
* Returned Value:
* On success, mq_send() returns 0 (OK); on error, -1 (ERROR)
* is returned, with errno set to indicate the error:
*
* EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the
* message queue description referred to by mqdes.
* EINVAL Either msg or mqdes 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.
* EINTR The call was interrupted by a signal handler.
*
* Assumptions/restrictions:
*
****************************************************************************/
int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
FAR const struct timespec *abstime)
{
int ret;
/* mq_timedsend() is a cancellation point */
(void)enter_cancellation_point();
/* Let nxmq_send() do all of the work */
ret = nxmq_timedsend(mqdes, msg, msglen, prio, abstime);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
} }
+1 -1
View File
@@ -296,7 +296,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
if (status == -EINTR) if (status == -EINTR)
{ {
serr("ERROR: Timedout!\n"); swarn("WARNING: Timedout!\n");
ret = ETIMEDOUT; ret = ETIMEDOUT;
} }
else else
+7 -5
View File
@@ -112,14 +112,16 @@ int pthread_sem_take(sem_t *sem, bool intr)
ret = nxsem_wait(sem); ret = nxsem_wait(sem);
if (ret < 0) if (ret < 0)
{ {
/* The only case that an error should occur here is if the wait /* The only cases that an error should occur here is if the wait
* was awakened by a signal. * was awakened by a signal or if the thread was canceled during
* the wait.
*/ */
DEBUGASSERT(ret == -EINTR); DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
/* When the signal is received, should we errout? Or should we /* When the error occurs in this case, should we errout? Or
* just continue waiting until we have the semaphore? * should we just continue waiting until we have the
* semaphore?
*/ */
if (intr) if (intr)
+3 -3
View File
@@ -124,17 +124,17 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
*/ */
pjoin = pthread_findjoininfo(group, (pid_t)thread); pjoin = pthread_findjoininfo(group, (pid_t)thread);
if (!pjoin) if (pjoin == NULL)
{ {
/* Determine what kind of error to return */ /* Determine what kind of error to return */
FAR struct tcb_s *tcb = sched_gettcb((pthread_t)thread); FAR struct tcb_s *tcb = sched_gettcb((pthread_t)thread);
serr("ERROR: Could not find thread data\n"); swarn("WARNING: Could not find thread data\n");
/* Case (1) or (3) -- we can't tell which. Assume (3) */ /* Case (1) or (3) -- we can't tell which. Assume (3) */
if (!tcb) if (tcb == NULL)
{ {
ret = ESRCH; ret = ESRCH;
} }