From fca07be1df52595d494c7524d17fb9294c385d5c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 10 Oct 2017 08:43:10 -0600 Subject: [PATCH] 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. --- audio/audio.c | 11 +- drivers/audio/audio_null.c | 7 +- drivers/audio/cs43l22.c | 21 ++- drivers/audio/vs1053.c | 13 +- drivers/audio/wm8904.c | 20 ++- drivers/wireless/cc3000/cc3000.c | 6 +- fs/mqueue/mq_close.c | 30 +++-- fs/mqueue/mq_open.c | 8 +- graphics/nxmu/nxmu_sendclient.c | 28 +--- include/nuttx/mqueue.h | 142 +++++++++++++++++--- libnx/nxmu/nxmu_sendserver.c | 7 +- sched/mqueue/mq_desclose.c | 6 +- sched/mqueue/mq_descreate.c | 6 +- sched/mqueue/mq_msgqalloc.c | 8 +- sched/mqueue/mq_msgqfree.c | 4 +- sched/mqueue/mq_release.c | 2 +- sched/mqueue/mq_send.c | 173 +++++++++++++++---------- sched/mqueue/mq_sndinternal.c | 112 ++++++++-------- sched/mqueue/mq_timedsend.c | 179 ++++++++++++++++---------- sched/pthread/pthread_condtimedwait.c | 2 +- sched/pthread/pthread_initialize.c | 12 +- sched/pthread/pthread_join.c | 6 +- 22 files changed, 497 insertions(+), 306 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 1acf6fb182..e4acb10b89 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -53,8 +53,9 @@ #include #include -#include +#include #include +#include #include #include @@ -716,8 +717,8 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper, msg.session = session; #endif apb->flags |= AUDIO_APB_DEQUEUED; - mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), - CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); + (void)nxmq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), + CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); } } @@ -754,8 +755,8 @@ static inline void audio_complete(FAR struct audio_upperhalf_s *upper, #ifdef CONFIG_AUDIO_MULTI_SESSION msg.session = session; #endif - mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), - CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); + (void)nxmq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), + CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); } } diff --git a/drivers/audio/audio_null.c b/drivers/audio/audio_null.c index 4ed7a010a6..bc5e8f1314 100644 --- a/drivers/audio/audio_null.c +++ b/drivers/audio/audio_null.c @@ -3,7 +3,7 @@ * * 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 * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -589,8 +590,8 @@ static int null_stop(FAR struct audio_lowerhalf_s *dev) term_msg.msgId = AUDIO_MSG_STOP; term_msg.u.data = 0; - mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_AUDIO_NULL_MSG_PRIO); + (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), + CONFIG_AUDIO_NULL_MSG_PRIO); /* Join the worker thread */ diff --git a/drivers/audio/cs43l22.c b/drivers/audio/cs43l22.c index 8dabd1cc31..f025641d52 100644 --- a/drivers/audio/cs43l22.c +++ b/drivers/audio/cs43l22.c @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -963,11 +964,11 @@ cs43l22_senddone(FAR struct i2s_dev_s *i2s, */ msg.msgId = AUDIO_MSG_COMPLETE; - ret = mq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), - CONFIG_CS43L22_MSG_PRIO); + ret = nxmq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), + CONFIG_CS43L22_MSG_PRIO); if (ret < 0) { - auderr("ERROR: mq_send failed: %d\n", errno); + auderr("ERROR: nxmq_send failed: %d\n", ret); } } @@ -1225,8 +1226,8 @@ static int cs43l22_stop(FAR struct audio_lowerhalf_s *dev) term_msg.msgId = AUDIO_MSG_STOP; term_msg.u.data = 0; - mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_CS43L22_MSG_PRIO); + (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), + CONFIG_CS43L22_MSG_PRIO); /* 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.u.data = 0; - ret = mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_CS43L22_MSG_PRIO); + ret = nxmq_send(priv->mq, (FAR const char *)&term_msg, + sizeof(term_msg), CONFIG_CS43L22_MSG_PRIO); if (ret < 0) { - int errcode = errno; - DEBUGASSERT(errcode > 0); - - auderr("ERROR: mq_send failed: %d\n", errcode); - UNUSED(errcode); + auderr("ERROR: nxmq_send failed: %d\n", ret); } } diff --git a/drivers/audio/vs1053.c b/drivers/audio/vs1053.c index 5660101db9..5d123ed6e4 100644 --- a/drivers/audio/vs1053.c +++ b/drivers/audio/vs1053.c @@ -55,6 +55,7 @@ #include #include +#include #include #include #include @@ -1222,8 +1223,8 @@ static int vs1053_dreq_isr(int irq, FAR void *context, FAR void *arg) if (dev->running) { msg.msgId = AUDIO_MSG_DATA_REQUEST; - mq_send(dev->mq, (FAR const char *)&msg, sizeof(msg), - CONFIG_VS1053_MSG_PRIO); + (void)nxmq_send(dev->mq, (FAR const char *)&msg, sizeof(msg), + CONFIG_VS1053_MSG_PRIO); } else { @@ -1513,8 +1514,8 @@ static int vs1053_stop(FAR struct audio_lowerhalf_s *lower) term_msg.msgId = AUDIO_MSG_STOP; term_msg.u.data = 0; - mq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_VS1053_MSG_PRIO); + (void)nxmq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg), + CONFIG_VS1053_MSG_PRIO); /* 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.u.data = 0; - mq_send(dev->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_VS1053_MSG_PRIO); + (void)nxmq_send(dev->mq, (FAR const char *)&term_msg, + sizeof(term_msg), CONFIG_VS1053_MSG_PRIO); } } diff --git a/drivers/audio/wm8904.c b/drivers/audio/wm8904.c index f2b35261c5..6efd183318 100644 --- a/drivers/audio/wm8904.c +++ b/drivers/audio/wm8904.c @@ -1360,11 +1360,11 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s, */ msg.msgId = AUDIO_MSG_COMPLETE; - ret = mq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), - CONFIG_WM8904_MSG_PRIO); + ret = nxmq_send(priv->mq, (FAR const char *)&msg, sizeof(msg), + CONFIG_WM8904_MSG_PRIO); if (ret < 0) { - auderr("ERROR: mq_send failed: %d\n", errno); + auderr("ERROR: nxmq_send failed: %d\n", ret); } } @@ -1622,8 +1622,8 @@ static int wm8904_stop(FAR struct audio_lowerhalf_s *dev) term_msg.msgId = AUDIO_MSG_STOP; term_msg.u.data = 0; - mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_WM8904_MSG_PRIO); + (void)nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), + CONFIG_WM8904_MSG_PRIO); /* 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.u.data = 0; - ret = mq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg), - CONFIG_WM8904_MSG_PRIO); + ret = nxmq_send(priv->mq, (FAR const char *)&term_msg, + sizeof(term_msg), CONFIG_WM8904_MSG_PRIO); if (ret < 0) { - int errcode = errno; - DEBUGASSERT(errcode > 0); - - auderr("ERROR: mq_send failed: %d\n", errcode); - UNUSED(errcode); + auderr("ERROR: nxmq_send failed: %d\n", ret); } } diff --git a/drivers/wireless/cc3000/cc3000.c b/drivers/wireless/cc3000/cc3000.c index 6fb4f52ee5..447d19f337 100644 --- a/drivers/wireless/cc3000/cc3000.c +++ b/drivers/wireless/cc3000/cc3000.c @@ -71,6 +71,7 @@ #include #include #include +#include #include #include @@ -702,8 +703,9 @@ static void *cc3000_worker(FAR void *arg) priv->state = eSPI_STATE_READ_READY; priv->rx_buffer.len = data_to_recv; - ret = mq_send(priv->queue, (FAR const char *)&priv->rx_buffer, - sizeof(priv->rx_buffer), 1); + ret = nxmq_send(priv->queue, + (FAR const char *)&priv->rx_buffer, + sizeof(priv->rx_buffer), 1); DEBUGASSERT(ret >= 0); UNUSED(ret); diff --git a/fs/mqueue/mq_close.c b/fs/mqueue/mq_close.c index 454f5cf62a..4578c1cc08 100644 --- a/fs/mqueue/mq_close.c +++ b/fs/mqueue/mq_close.c @@ -55,11 +55,11 @@ ****************************************************************************/ /**************************************************************************** - * Name: mq_close_group + * 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 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 * this task for its message queue. * @@ -68,12 +68,12 @@ * group - Group that has the open descriptor. * * Return Value: - * 0 (OK) if the message queue is closed successfully, - * otherwise, -1 (ERROR). + * Zero (OK) if the message queue is closed successfully. Otherwise, a + * 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 inode *inode; @@ -93,7 +93,7 @@ int mq_close_group(mqd_t mqdes, FAR struct task_group_s *group) /* Close/free the message descriptor */ - mq_desclose_group(mqdes, group); + nxmq_desclose_group(mqdes, group); /* 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). * * Assumptions: - * - The behavior of a task that is blocked on either a mq_send() or - * mq_receive() is undefined when mq_close() is called. + * - The behavior of a task that is blocked on either a [nx]mq_send() or + * [nx]mq_receive() is undefined when mq_close() is called. * - The results of using this message queue descriptor after a successful * return from mq_close() is undefined. * @@ -151,7 +151,17 @@ int mq_close(mqd_t mqdes) rtcb = (FAR struct tcb_s *)sched_self(); 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(); return ret; } @@ -193,7 +203,7 @@ void mq_inode_release(FAR struct inode *inode) /* Free the message queue (and any messages left in it) */ - mq_msgqfree(msgq); + nxmq_free_msgq(msgq); inode->u.i_mqueue = NULL; /* Release and free the inode container. If it has been properly diff --git a/fs/mqueue/mq_open.c b/fs/mqueue/mq_open.c index 85474e0f3f..5c372a50d5 100644 --- a/fs/mqueue/mq_open.c +++ b/fs/mqueue/mq_open.c @@ -164,7 +164,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...) /* Create a message queue descriptor for the current thread */ msgq = inode->u.i_mqueue; - mqdes = mq_descreate(NULL, msgq, oflags); + mqdes = nxmq_create_des(NULL, msgq, oflags); if (!mqdes) { 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. */ - msgq = (FAR struct mqueue_inode_s *)mq_msgqalloc(mode, attr); + msgq = (FAR struct mqueue_inode_s *)nxmq_alloc_msgq(mode, attr); if (!msgq) { 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 */ - mqdes = mq_descreate(NULL, msgq, oflags); + mqdes = nxmq_create_des(NULL, msgq, oflags); if (!mqdes) { errcode = ENOMEM; @@ -240,7 +240,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...) return mqdes; errout_with_msgq: - mq_msgqfree(msgq); + nxmq_free_msgq(msgq); inode->u.i_mqueue = NULL; errout_with_inode: diff --git a/graphics/nxmu/nxmu_sendclient.c b/graphics/nxmu/nxmu_sendclient.c index 7a0ab2be7b..a26a6d3e96 100644 --- a/graphics/nxmu/nxmu_sendclient.c +++ b/graphics/nxmu/nxmu_sendclient.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -43,28 +43,10 @@ #include #include +#include + #include "nxfe.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private 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 */ - ret = mq_send(conn->swrmq, msg, msglen, NX_CLIMSG_PRIO); + ret = nxmq_send(conn->swrmq, msg, msglen, NX_CLIMSG_PRIO); if (ret < 0) { - gerr("ERROR: mq_send failed: %d\n", errno); + gerr("ERROR: nxmq_send failed: %d\n", ret); } return ret; diff --git a/include/nuttx/mqueue.h b/include/nuttx/mqueue.h index b011435d02..0147cf85f6 100644 --- a/include/nuttx/mqueue.h +++ b/include/nuttx/mqueue.h @@ -1,7 +1,8 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -56,6 +57,37 @@ * 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 ****************************************************************************/ @@ -111,12 +143,88 @@ extern "C" #define EXTERN extern #endif -struct mq_attr; /* Forward reference */ struct tcb_s; /* Forward reference */ +struct mq_attr; /* Forward reference */ +struct timespec; /* 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: * 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: * 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 mq_attr *attr); +FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode, + FAR struct mq_attr *attr); /**************************************************************************** - * Name: mq_descreate + * Name: nxmq_create_des * * Description: * 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, - int oflags); +mqd_t nxmq_create_des(FAR struct tcb_s *mtcb, + FAR struct mqueue_inode_s *msgq, int oflags); /**************************************************************************** - * Name: mq_close_group + * 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 mq_close_group() + * 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. * @@ -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. * * Return Value: - * 0 (OK) if the message queue is closed successfully, - * otherwise, -1 (ERROR). + * Zero (OK) if the message queue is closed successfully. Otherwise, a + * 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: * 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 #ifdef __cplusplus diff --git a/libnx/nxmu/nxmu_sendserver.c b/libnx/nxmu/nxmu_sendserver.c index e239382b2f..65266a659c 100644 --- a/libnx/nxmu/nxmu_sendserver.c +++ b/libnx/nxmu/nxmu_sendserver.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,7 @@ #include #include +#include #include /**************************************************************************** @@ -82,10 +83,10 @@ int nxmu_sendserver(FAR struct nxfe_conn_s *conn, FAR const void *msg, /* 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) { - gerr("ERROR: mq_send failed: %d\n", errno); + gerr("ERROR: _MQ_SEND failed: %d\n", _MQ_ERRNO(rer)); } return ret; diff --git a/sched/mqueue/mq_desclose.c b/sched/mqueue/mq_desclose.c index 841c4ade8a..b4c72c0e96 100644 --- a/sched/mqueue/mq_desclose.c +++ b/sched/mqueue/mq_desclose.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -72,7 +72,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: mq_desclose_group + * Name: nxmq_desclose_group * * Description: * 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; diff --git a/sched/mqueue/mq_descreate.c b/sched/mqueue/mq_descreate.c index 0cb0e8a01a..d3b574f623 100644 --- a/sched/mqueue/mq_descreate.c +++ b/sched/mqueue/mq_descreate.c @@ -104,7 +104,7 @@ static mqd_t nxmq_alloc_des(void) ****************************************************************************/ /**************************************************************************** - * Name: mq_descreate + * Name: nxmq_create_des * * Description: * 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, - int oflags) +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; diff --git a/sched/mqueue/mq_msgqalloc.c b/sched/mqueue/mq_msgqalloc.c index 5bdfee47a3..473896c3f2 100644 --- a/sched/mqueue/mq_msgqalloc.c +++ b/sched/mqueue/mq_msgqalloc.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: mq_msgqalloc + * Name: nxmq_alloc_msgq * * Description: * This function implements a part of the POSIX message queue open logic. @@ -72,8 +72,8 @@ * ****************************************************************************/ -FAR struct mqueue_inode_s *mq_msgqalloc(mode_t mode, - FAR struct mq_attr *attr) +FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode, + FAR struct mq_attr *attr) { FAR struct mqueue_inode_s *msgq; diff --git a/sched/mqueue/mq_msgqfree.c b/sched/mqueue/mq_msgqfree.c index 976f4d30fb..b52494813e 100644 --- a/sched/mqueue/mq_msgqfree.c +++ b/sched/mqueue/mq_msgqfree.c @@ -48,7 +48,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: mq_msgqfree + * Name: nxmq_free_msgq * * Description: * 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 *next; diff --git a/sched/mqueue/mq_release.c b/sched/mqueue/mq_release.c index 2adfa04a95..c916c7b41d 100644 --- a/sched/mqueue/mq_release.c +++ b/sched/mqueue/mq_release.c @@ -67,6 +67,6 @@ void nxmq_release(FAR struct task_group_s *group) { 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); } } diff --git a/sched/mqueue/mq_send.c b/sched/mqueue/mq_send.c index a6edb3c64b..e842f70546 100644 --- a/sched/mqueue/mq_send.c +++ b/sched/mqueue/mq_send.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -55,67 +55,48 @@ ****************************************************************************/ /**************************************************************************** - * Name: mq_send + * Name: nxmq_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(). + * (mqdes). This is an internal OS interface. It is functionally + * equivalent to mq_send() except that: * - * 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. + * - It is not a cancellaction point, and + * - It does not modify the errno value. * - * 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. + * See comments with mq_send() for a more complete description of the + * behavior of this function * - * If the message queue is full and O_NONBLOCK is set, the message is not - * queued and ERROR is returned. - * - * Parameters: - * mqdes - Message queue descriptor - * msg - Message to send + * Input Parameters: + * mqdes - Message queue descriptor + * msg - Message to send * msglen - The length of the message in bytes - * prio - The priority of the message + * prio - The priority of the message * - * Return 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. - * - * Assumptions/restrictions: + * 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 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_msg_s *mqmsg = NULL; irqstate_t flags; - int ret = ERROR; - - /* mq_send() is a cancellation point */ - - (void)enter_cancellation_point(); + int ret; /* Verify the input parameters -- setting errno appropriately * 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 ERROR; + return ret; } /* 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. */ + mqmsg = NULL; flags = enter_critical_section(); - if (up_interrupt_context() || /* In an interrupt handler */ - msgq->nmsgs < msgq->maxmsgs || /* OR Message queue not full */ - nxmq_wait_send(mqdes) == OK) /* OR Successfully waited for mq not full */ - { - /* Allocate the message */ + ret = OK; + + if (!up_interrupt_context()) /* In an interrupt handler? */ + { + /* 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); + if (ret >= 0) + { + /* Now allocate the message. */ - leave_critical_section(flags); mqmsg = nxmq_alloc_msg(); /* Check if the message was sucessfully allocated */ - if (mqmsg == NULL) - { - /* 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); + ret = (mqmsg == NULL) ? -ENOMEM : OK; } /* 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(); + 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(); return ret; } diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index 083b497dee..933d684a13 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -69,26 +69,24 @@ * Name: nxmq_verify_send * * Description: - * This is internal, common logic shared by both mq_send and mq_timesend. - * This function verifies the input parameters that are common to both - * functions. + * This is internal, common logic shared by both [nx]mq_send and + * [nx]mq_timesend. This function verifies the input parameters that are + * common to both functions. * - * Parameters: + * Input Parameters: * mqdes - Message queue descriptor * msg - Message to send * msglen - The length of the message in bytes * prio - The priority of the message * - * Return Value: - * One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and - * the errno is set appropriately: + * 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. - * EPERM Message queue opened not opened for writing. - * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the - * message queue. - * - * Assumptions: + * 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. * ****************************************************************************/ @@ -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) { - set_errno(EINVAL); - return ERROR; + return -EINVAL; } if ((mqdes->oflags & O_WROK) == 0) { - set_errno(EPERM); - return ERROR; + return -EPERM; } if (msglen > (size_t)mqdes->msgq->maxmsgsize) { - set_errno(EMSGSIZE); - return ERROR; + return -EMSGSIZE; } return OK; @@ -139,7 +134,7 @@ int nxmq_verify_send(mqd_t mqdes, FAR const char *msg, size_t msglen, * Inputs: * None * - * Return Value: + * Returned Value: * A reference to the allocated msg structure. On a failure to allocate, * this function PANICs. * @@ -207,15 +202,16 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void) * Name: nxmq_wait_send * * Description: - * This is internal, common logic shared by both mq_send and mq_timesend. - * This function waits until the message queue is not full. + * This is internal, common logic shared by both [nx]mq_send and + * [nx]mq_timesend. This function waits until the message queue is not + * full. * - * Parameters: + * Input Parameters: * mqdes - Message queue descriptor * - * Return Value: - * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) is - * returned, with errno set to indicate the error: + * 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. @@ -233,23 +229,22 @@ int nxmq_wait_send(mqd_t mqdes) { FAR struct tcb_s *rtcb; FAR struct mqueue_inode_s *msgq; + int ret; - /* nxmq_wait_send() is not a cancellation point, but it is always called from - * a cancellation point. +#ifdef CONFIG_CANCELLATION_POINTS + /* 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 * the wait. Exit now with ECANCELED. */ - set_errno(ECANCELED); - leave_cancellation_point(); - return ERROR; -#endif + return -ECANCELED; } +#endif /* 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. */ - set_errno(EAGAIN); - leave_cancellation_point(); - return ERROR; + return -EAGAIN; } /* Yes... We will not return control until the message queue is @@ -284,33 +277,42 @@ int nxmq_wait_send(mqd_t mqdes) while (msgq->nmsgs >= msgq->maxmsgs) { + int saved_errno; + /* Block until the message queue is no longer full. * When we are unblocked, we will try again */ - rtcb = this_task(); + rtcb = this_task(); rtcb->msgwaitq = msgq; 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); /* When we resume at this point, either (1) the message queue * is no longer empty, or (2) the wait has been interrupted by * 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 ERROR; + return -ret; } } } } - leave_cancellation_point(); return OK; } @@ -318,23 +320,21 @@ int nxmq_wait_send(mqd_t mqdes) * Name: nxmq_do_send * * Description: - * This is internal, common logic shared by both mq_send and mq_timesend. - * This function adds the specified message (msg) to the message queue - * (mqdes). 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. + * 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 + * for message queue notifications setup by mq_notify. And, finally, it + * awakens any tasks that were waiting for the message not empty event. * - * Parameters: - * mqdes - Message queue descriptor - * msg - Message to send + * Input Parameters: + * mqdes - Message queue descriptor + * msg - Message to send * 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. * - * Assumptions/restrictions: - * ****************************************************************************/ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg, diff --git a/sched/mqueue/mq_timedsend.c b/sched/mqueue/mq_timedsend.c index 2a0bc59732..43924d4901 100644 --- a/sched/mqueue/mq_timedsend.c +++ b/sched/mqueue/mq_timedsend.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * 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 * becomes non-full. * - * Parameters: + * Input Parameters: * argc - the number of arguments (should be 1) * pid - the task ID of the task to wakeup * - * Return Value: + * Returned Value: * None * * Assumptions: @@ -99,7 +99,7 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid) * 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 */ @@ -116,43 +116,36 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid) ****************************************************************************/ /**************************************************************************** - * Name: mq_send + * Name: nxmq_timedsend * * Description: - * This function adds the specificied 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(). + * 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. * - * 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. + * nxmq_timedsend() is functionally equivalent to mq_timedsend() except + * that: * - * 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. + * - It is not a cancellaction point, and + * - It does not modify the errno value. * - * 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). + * See comments with mq_timedsend() for a more complete description of the + * behavior of this function * - * If the message queue is full, and the timeout has already expired by - * the time of the call, mq_timedsend() returns immediately. - * - * Parameters: - * mqdes - Message queue descriptor - * msg - Message to send - * msglen - The length of the message in bytes - * prio - The priority of the message + * 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 * - * Return Value: - * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) - * is returned, with errno set to indicate the error: + * 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. @@ -162,12 +155,10 @@ static void nxmq_sndtimeout(int argc, wdparm_t pid) * 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 nxmq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, + FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_inode_s *msgq; @@ -175,24 +166,16 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, irqstate_t flags; ssystime_t ticks; int result; - int ret = ERROR; + int ret; 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(); - - /* Verify the input parameters -- setting errno appropriately - * 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) { - /* nxmq_verify_send() will set the errno appropriately */ - - leave_cancellation_point(); - return ERROR; + return ret; } /* 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. */ - set_errno(ENOMEM); - leave_cancellation_point(); - return ERROR; + return -ENOMEM; } /* 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); sched_unlock(); - leave_cancellation_point(); 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) { - result = EINVAL; + ret = -EINVAL; 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(); if (!rtcb->waitdog) { - result = EINVAL; + ret = -EINVAL; goto errout_with_mqmsg; } @@ -269,7 +249,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, * disabled here so that this time stays valid until the wait begins. */ - flags = enter_critical_section(); + flags = enter_critical_section(); result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, @@ -285,6 +265,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, if (result != OK) { + ret = -result; 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) { - /* 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; } @@ -332,8 +312,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, return ret; /* Exit here with (1) the scheduler locked, (2) a message allocated, (3) a - * wdog allocated, and (4) interrupts disabled. The error code is in - * 'result' + * wdog allocated, and (4) interrupts disabled. */ errout_in_critical_section: @@ -348,8 +327,78 @@ errout_in_critical_section: errout_with_mqmsg: nxmq_free_msg(mqmsg); sched_unlock(); - - set_errno(result); - leave_cancellation_point(); - return ERROR; + return ret; +} + +/**************************************************************************** + * 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; } diff --git a/sched/pthread/pthread_condtimedwait.c b/sched/pthread/pthread_condtimedwait.c index 58b4f44889..b27c279397 100644 --- a/sched/pthread/pthread_condtimedwait.c +++ b/sched/pthread/pthread_condtimedwait.c @@ -296,7 +296,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, if (status == -EINTR) { - serr("ERROR: Timedout!\n"); + swarn("WARNING: Timedout!\n"); ret = ETIMEDOUT; } else diff --git a/sched/pthread/pthread_initialize.c b/sched/pthread/pthread_initialize.c index c38ee19961..3887ab7e8f 100644 --- a/sched/pthread/pthread_initialize.c +++ b/sched/pthread/pthread_initialize.c @@ -112,14 +112,16 @@ int pthread_sem_take(sem_t *sem, bool intr) ret = nxsem_wait(sem); if (ret < 0) { - /* The only case that an error should occur here is if the wait - * was awakened by a signal. + /* The only cases that an error should occur here is if the wait + * 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 - * just continue waiting until we have the semaphore? + /* When the error occurs in this case, should we errout? Or + * should we just continue waiting until we have the + * semaphore? */ if (intr) diff --git a/sched/pthread/pthread_join.c b/sched/pthread/pthread_join.c index a76c57f828..4f22777b9a 100644 --- a/sched/pthread/pthread_join.c +++ b/sched/pthread/pthread_join.c @@ -124,17 +124,17 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) */ pjoin = pthread_findjoininfo(group, (pid_t)thread); - if (!pjoin) + if (pjoin == NULL) { /* Determine what kind of error to return */ 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) */ - if (!tcb) + if (tcb == NULL) { ret = ESRCH; }