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
This commit is contained in:
patacongo 2011-09-21 13:28:16 +00:00
parent bc50d2975f
commit c374ab8b2c
7 changed files with 37 additions and 37 deletions

View File

@ -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.

View File

@ -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 ********************************************************/

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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. */

View File

@ -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
}