From 342a2fb06c717ae0fa55e3f1fba2dc28230a073f Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 21 Sep 2011 13:28:16 +0000 Subject: 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 --- nuttx/ChangeLog | 8 ++++++++ nuttx/sched/mq_internal.h | 4 ++-- nuttx/sched/mq_sndinternal.c | 14 +++++++------- nuttx/sched/mq_timedreceive.c | 18 +++++++----------- nuttx/sched/mq_timedsend.c | 18 +++++++----------- nuttx/sched/mq_waitirq.c | 10 +++++----- nuttx/sched/sig_received.c | 2 +- 7 files changed, 37 insertions(+), 37 deletions(-) (limited to 'nuttx') 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 * * 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 * * 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 * * 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 } -- cgit v1.2.3