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:
parent
bc50d2975f
commit
c374ab8b2c
@ -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.
|
||||
|
||||
|
@ -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 ********************************************************/
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user