summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-21 13:28:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-21 13:28:16 +0000
commit342a2fb06c717ae0fa55e3f1fba2dc28230a073f (patch)
tree34c2c48653cf89919673748b86a4578ed1a3c86e /nuttx
parentdfa9ad91efa32959ed7b5c971aa6181a1704455d (diff)
downloadpx4-nuttx-342a2fb06c717ae0fa55e3f1fba2dc28230a073f.tar.gz
px4-nuttx-342a2fb06c717ae0fa55e3f1fba2dc28230a073f.tar.bz2
px4-nuttx-342a2fb06c717ae0fa55e3f1fba2dc28230a073f.zip
Fix important bugs in mq_timedreceived() and mq_timedsend()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3966 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog8
-rw-r--r--nuttx/sched/mq_internal.h4
-rw-r--r--nuttx/sched/mq_sndinternal.c14
-rw-r--r--nuttx/sched/mq_timedreceive.c18
-rw-r--r--nuttx/sched/mq_timedsend.c18
-rw-r--r--nuttx/sched/mq_waitirq.c10
-rw-r--r--nuttx/sched/sig_received.c2
7 files changed, 37 insertions, 37 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index dea82eb65..25b43abe3 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -2100,3 +2100,11 @@
* arch/arm/src/stm32/stm32_i2c.c: Fix another bug where I2C conflicts with FSMC
being enabled. That time at the tail end of the transaction where there is
an unfinished stop condition.
+ * sched/mq_timedreceive.c and sched/mq_timedsend.c: The count of threads
+ waiting on the message queues was not being decremented after a timeout.
+ This would cause the accounting logic to become out of sync and the, perhaps,
+ an assertion to be triggered. This is an important bug and fixes a
+ potential crash when using mq_timedreceived() and mq_timedsend().
+ * sched/mq_sndinternal.c: Related to the above, the send logic was incrementing
+ the wrong counter when it waited as part of the mq_timedsend.c logic.
+
diff --git a/nuttx/sched/mq_internal.h b/nuttx/sched/mq_internal.h
index 28dd011d9..c9666f683 100644
--- a/nuttx/sched/mq_internal.h
+++ b/nuttx/sched/mq_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/mq_internal.h
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -154,7 +154,7 @@ EXTERN void mq_msgqfree(FAR msgq_t *msgq);
/* mq_waitirq.c ************************************************************/
-EXTERN void mq_waitirq(FAR _TCB *wtcb);
+EXTERN void mq_waitirq(FAR _TCB *wtcb, int errcode);
/* mq_rcvinternal.c ********************************************************/
diff --git a/nuttx/sched/mq_sndinternal.c b/nuttx/sched/mq_sndinternal.c
index 64eee136d..b359f6f17 100644
--- a/nuttx/sched/mq_sndinternal.c
+++ b/nuttx/sched/mq_sndinternal.c
@@ -114,19 +114,19 @@ int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, int prio)
if (!msg || !mqdes || prio < 0 || prio > MQ_PRIO_MAX)
{
- *get_errno_ptr() = EINVAL;
+ set_errno(EINVAL);
return ERROR;
}
if ((mqdes->oflags & O_WROK) == 0)
{
- *get_errno_ptr() = EPERM;
+ set_errno(EPERM);
return ERROR;
}
if (msglen < 0 || msglen > (size_t)mqdes->msgq->maxmsgsize)
{
- *get_errno_ptr() = EMSGSIZE;
+ set_errno(EMSGSIZE);
return ERROR;
}
@@ -267,7 +267,7 @@ int mq_waitsend(mqd_t mqdes)
{
/* No... We will return an error to the caller. */
- *get_errno_ptr() = EAGAIN;
+ set_errno(EAGAIN);
return ERROR;
}
@@ -289,9 +289,9 @@ int mq_waitsend(mqd_t mqdes)
rtcb = (FAR _TCB*)g_readytorun.head;
rtcb->msgwaitq = msgq;
- (msgq->nwaitnotempty)++;
+ msgq->nwaitnotfull++;
- *get_errno_ptr() = OK;
+ set_errno(OK);
up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL);
/* When we resume at this point, either (1) the message queue
@@ -300,7 +300,7 @@ int mq_waitsend(mqd_t mqdes)
* errno value (should be EINTR or ETIMEOUT).
*/
- if (*get_errno_ptr() != OK)
+ if (get_errno() != OK)
{
return ERROR;
}
diff --git a/nuttx/sched/mq_timedreceive.c b/nuttx/sched/mq_timedreceive.c
index 1100331eb..856c08be5 100644
--- a/nuttx/sched/mq_timedreceive.c
+++ b/nuttx/sched/mq_timedreceive.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/mq_timedreceive.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -115,16 +115,12 @@ static void mq_rcvtimeout(int argc, uint32_t pid)
if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY)
{
- /* Mark the errno value for the thread. */
+ /* Restart with task with a timeout error */
- wtcb->pterrno = ETIMEDOUT;
-
- /* Restart the task. */
-
- up_unblock_task(wtcb);
+ mq_waitirq(wtcb, ETIMEDOUT);
}
- /* Interrupts may now be enabled. */
+ /* Interrupts may now be re-enabled. */
irqrestore(saved_state);
}
@@ -210,7 +206,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen,
if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000)
{
- *get_errno_ptr() = EINVAL;
+ set_errno(EINVAL);
return ERROR;
}
@@ -222,7 +218,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen,
wdog = wd_create();
if (!wdog)
{
- *get_errno_ptr() = EINVAL;
+ set_errno(EINVAL);
return ERROR;
}
@@ -268,7 +264,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen,
if (result != OK)
{
- *get_errno_ptr() = result;
+ set_errno(result);
irqrestore(saved_state);
sched_unlock();
wd_delete(wdog);
diff --git a/nuttx/sched/mq_timedsend.c b/nuttx/sched/mq_timedsend.c
index 412d2b8b4..4f329d311 100644
--- a/nuttx/sched/mq_timedsend.c
+++ b/nuttx/sched/mq_timedsend.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/mq_timedsend.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -115,16 +115,12 @@ static void mq_sndtimeout(int argc, uint32_t pid)
if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTFULL)
{
- /* Mark the errno value for the thread. */
+ /* Restart with task with a timeout error */
- wtcb->pterrno = ETIMEDOUT;
-
- /* Restart the task. */
-
- up_unblock_task(wtcb);
+ mq_waitirq(wtcb, ETIMEDOUT);
}
- /* Interrupts may now be enabled. */
+ /* Interrupts may now be re-enabled. */
irqrestore(saved_state);
}
@@ -206,7 +202,7 @@ int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio,
if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000)
{
- *get_errno_ptr() = EINVAL;
+ set_errno(EINVAL);
return ERROR;
}
@@ -222,7 +218,7 @@ int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio,
wdog = wd_create();
if (!wdog)
{
- *get_errno_ptr() = EINVAL;
+ set_errno(EINVAL);
return ERROR;
}
@@ -267,7 +263,7 @@ int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio,
if (result != OK)
{
- *get_errno_ptr() = result;
+ set_errno(result);
ret = ERROR;
}
diff --git a/nuttx/sched/mq_waitirq.c b/nuttx/sched/mq_waitirq.c
index 9d436c280..69f09a4f1 100644
--- a/nuttx/sched/mq_waitirq.c
+++ b/nuttx/sched/mq_waitirq.c
@@ -75,9 +75,9 @@
* Function: sem_waitirq
*
* Description:
- * This function is called when a signal is received by a task that is
- * waiting on a message queue -- either for a queue to becoming not full
- * (on mq_send) or not empty (on mq_receive).
+ * This function is called when a signal or a timeout is received by a
+ * task that is waiting on a message queue -- either for a queue to
+ * becoming not full (on mq_send) or not empty (on mq_receive).
*
* Parameters:
* wtcb - A pointer to the TCB of the task that is waiting on a message
@@ -90,7 +90,7 @@
*
****************************************************************************/
-void mq_waitirq(FAR _TCB *wtcb)
+void mq_waitirq(FAR _TCB *wtcb, int errcode)
{
FAR msgq_t *msgq;
irqstate_t saved_state;
@@ -158,7 +158,7 @@ void mq_waitirq(FAR _TCB *wtcb)
/* Mark the errno value for the thread. */
- wtcb->pterrno = EINTR;
+ wtcb->pterrno = errcode;
/* Restart the task. */
diff --git a/nuttx/sched/sig_received.c b/nuttx/sched/sig_received.c
index 1aa76c900..26727dfbc 100644
--- a/nuttx/sched/sig_received.c
+++ b/nuttx/sched/sig_received.c
@@ -393,7 +393,7 @@ int sig_received(FAR _TCB *stcb, siginfo_t *info)
if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY ||
stcb->task_state == TSTATE_WAIT_MQNOTFULL)
{
- mq_waitirq(stcb);
+ mq_waitirq(stcb, EINTR);
}
#endif
}