From e7e79a6ccb4f3e320b2b8b7bad1b14d65218641d Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 18 Mar 2011 18:38:08 +0000 Subject: License updated. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2827 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/src/chqueues.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'os/kernel/src/chqueues.c') diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index 8d459a7e8..05fbddfb9 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -1,5 +1,6 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. This file is part of ChibiOS/RT. -- cgit v1.2.3 From 807c5f1882224c2afd471a44889b83c2adf80589 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 18 May 2011 17:54:55 +0000 Subject: Fixed bug 3303908. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2972 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/src/chqueues.c | 124 +++++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 59 deletions(-) (limited to 'os/kernel/src/chqueues.c') diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index 05fbddfb9..f6ae10257 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -47,6 +47,30 @@ #if CH_USE_QUEUES || defined(__DOXYGEN__) +/** + * @brief Puts the invoking thread into the queue's threads queue. + * + * @param[out] qp pointer to an @p GenericQueue structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A message specifying how the invoking thread has been + * released from threads queue. + * @retval RDY_OK is the normal exit, thread signaled. + * @retval RDY_RESET if the queue has been reset. + * @retval RDY_TIMEOUT if the queue operation timed out. + */ +static msg_t qwait(GenericQueue *qp, systime_t time) { + + if (TIME_IMMEDIATE == time) + return RDY_TIMEOUT; + currp->p_u.wtobjp = qp; + queue_insert(currp, &qp->q_waiting); + return chSchGoSleepTimeoutS(THD_STATE_WTQUEUE, time); +} + /** * @brief Initializes an input queue. * @details A Semaphore is internally initialized and works as a counter of @@ -64,28 +88,11 @@ */ void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy) { + queue_init(&iqp->q_waiting); + iqp->q_counter = 0; iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp; iqp->q_top = bp + size; iqp->q_notify = infy; - chSemInit(&iqp->q_sem, 0); -} - -/** - * @brief Returns the filled space into an input queue. - * - * @param[in] iqp pointer to an @p InputQueue structure - * @return The number of bytes in the queue. - * @retval 0 if the queue is empty. - * - * @iclass - */ -size_t chIQGetFullI(InputQueue *iqp) { - cnt_t cnt; - - cnt = chQSpaceI(iqp); - if (cnt < 0) - return 0; - return (size_t)cnt; } /** @@ -102,7 +109,9 @@ size_t chIQGetFullI(InputQueue *iqp) { void chIQResetI(InputQueue *iqp) { iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; - chSemResetI(&iqp->q_sem, 0); + iqp->q_counter = 0; + while (notempty(&iqp->q_waiting)) + chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = RDY_RESET; } /** @@ -123,10 +132,12 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { if (chIQIsFullI(iqp)) return Q_FULL; + iqp->q_counter++; *iqp->q_wrptr++ = b; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; - chSemSignalI(&iqp->q_sem); + if (notempty(&iqp->q_waiting)) + chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = RDY_OK; return Q_OK; } @@ -150,17 +161,21 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { */ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { uint8_t b; - msg_t msg; chSysLock(); - if (iqp->q_notify) iqp->q_notify(iqp); - if ((msg = chSemWaitTimeoutS(&iqp->q_sem, time)) < RDY_OK) { - chSysUnlock(); - return msg; + while (chIQIsEmptyI(iqp)) { + msg_t msg; + + if ((msg = qwait((GenericQueue *)iqp, time)) < RDY_OK) { + chSysUnlock(); + return msg; + } } + + iqp->q_counter--; b = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) iqp->q_rdptr = iqp->q_buffer; @@ -202,16 +217,16 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, chSysLock(); while (TRUE) { - if (chIQIsEmptyI(iqp)) { + while (chIQIsEmptyI(iqp)) { if (nfy) nfy(iqp); - if ((chSemWaitTimeoutS(&iqp->q_sem, time) != RDY_OK)) { + if (qwait((GenericQueue *)iqp, time) != RDY_OK) { chSysUnlock(); return r; } } - else - chSemFastWaitI(&iqp->q_sem); + + iqp->q_counter--; *bp++ = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) iqp->q_rdptr = iqp->q_buffer; @@ -245,28 +260,11 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, */ void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy) { + queue_init(&oqp->q_waiting); + oqp->q_counter = size; oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp; oqp->q_top = bp + size; oqp->q_notify = onfy; - chSemInit(&oqp->q_sem, (cnt_t)size); -} - -/** - * @brief Returns the filled space into an output queue. - * - * @param[in] oqp pointer to an @p OutputQueue structure - * @return The number of bytes in the queue. - * @retval 0 if the queue is empty. - * - * @iclass - */ -size_t chOQGetFullI(OutputQueue *oqp) { - cnt_t cnt; - - cnt = chQSpaceI(oqp); - if (cnt < 0) - return chQSizeI(oqp); - return chQSizeI(oqp) - (size_t)cnt; } /** @@ -283,7 +281,9 @@ size_t chOQGetFullI(OutputQueue *oqp) { void chOQResetI(OutputQueue *oqp) { oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; - chSemResetI(&oqp->q_sem, (cnt_t)(oqp->q_top - oqp->q_buffer)); + oqp->q_counter = chQSizeI(oqp); + while (notempty(&oqp->q_waiting)) + chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = RDY_RESET; } /** @@ -307,13 +307,18 @@ void chOQResetI(OutputQueue *oqp) { * @api */ msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) { - msg_t msg; chSysLock(); - if ((msg = chSemWaitTimeoutS(&oqp->q_sem, time)) < RDY_OK) { - chSysUnlock(); - return msg; + while (chOQIsFullI(oqp)) { + msg_t msg; + + if ((msg = qwait((GenericQueue *)oqp, time)) < RDY_OK) { + chSysUnlock(); + return msg; + } } + + oqp->q_counter--; *oqp->q_wrptr++ = b; if (oqp->q_wrptr >= oqp->q_top) oqp->q_wrptr = oqp->q_buffer; @@ -341,10 +346,12 @@ msg_t chOQGetI(OutputQueue *oqp) { if (chOQIsEmptyI(oqp)) return Q_EMPTY; + oqp->q_counter++; b = *oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; - chSemSignalI(&oqp->q_sem); + if (notempty(&oqp->q_waiting)) + chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = RDY_OK; return b; } @@ -381,16 +388,15 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, chSysLock(); while (TRUE) { - if (chOQIsFullI(oqp)) { + while (chOQIsFullI(oqp)) { if (nfy) nfy(oqp); - if ((chSemWaitTimeoutS(&oqp->q_sem, time) != RDY_OK)) { + if (qwait((GenericQueue *)oqp, time) != RDY_OK) { chSysUnlock(); return w; } } - else - chSemFastWaitI(&oqp->q_sem); + oqp->q_counter--; *oqp->q_wrptr++ = *bp++; if (oqp->q_wrptr >= oqp->q_top) oqp->q_wrptr = oqp->q_buffer; -- cgit v1.2.3 From 3495905f51318549a2bd6764360a4812aac869fa Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 19 May 2011 17:46:52 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2974 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/src/chqueues.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'os/kernel/src/chqueues.c') diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index f6ae10257..767a36e63 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -58,14 +58,14 @@ * . * @return A message specifying how the invoking thread has been * released from threads queue. - * @retval RDY_OK is the normal exit, thread signaled. - * @retval RDY_RESET if the queue has been reset. - * @retval RDY_TIMEOUT if the queue operation timed out. + * @retval Q_OK is the normal exit, thread signaled. + * @retval Q_RESET if the queue has been reset. + * @retval Q_TIMEOUT if the queue operation timed out. */ static msg_t qwait(GenericQueue *qp, systime_t time) { if (TIME_IMMEDIATE == time) - return RDY_TIMEOUT; + return Q_TIMEOUT; currp->p_u.wtobjp = qp; queue_insert(currp, &qp->q_waiting); return chSchGoSleepTimeoutS(THD_STATE_WTQUEUE, time); @@ -111,7 +111,7 @@ void chIQResetI(InputQueue *iqp) { iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; iqp->q_counter = 0; while (notempty(&iqp->q_waiting)) - chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = RDY_RESET; + chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_RESET; } /** @@ -137,7 +137,7 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; if (notempty(&iqp->q_waiting)) - chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = RDY_OK; + chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; return Q_OK; } @@ -155,7 +155,7 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * . * @return A byte value from the queue. * @retval Q_TIMEOUT if the specified time expired. - * @retval Q_RESET if the queue was reset. + * @retval Q_RESET if the queue has been reset. * * @api */ @@ -163,13 +163,13 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { uint8_t b; chSysLock(); - if (iqp->q_notify) - iqp->q_notify(iqp); - while (chIQIsEmptyI(iqp)) { msg_t msg; - if ((msg = qwait((GenericQueue *)iqp, time)) < RDY_OK) { + if (iqp->q_notify) + iqp->q_notify(iqp); + + if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -220,7 +220,7 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, while (chIQIsEmptyI(iqp)) { if (nfy) nfy(iqp); - if (qwait((GenericQueue *)iqp, time) != RDY_OK) { + if (qwait((GenericQueue *)iqp, time) != Q_OK) { chSysUnlock(); return r; } @@ -283,7 +283,7 @@ void chOQResetI(OutputQueue *oqp) { oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; oqp->q_counter = chQSizeI(oqp); while (notempty(&oqp->q_waiting)) - chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = RDY_RESET; + chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_RESET; } /** @@ -302,7 +302,7 @@ void chOQResetI(OutputQueue *oqp) { * @return The operation status. * @retval Q_OK if the operation succeeded. * @retval Q_TIMEOUT if the specified time expired. - * @retval Q_RESET if the queue was reset. + * @retval Q_RESET if the queue has been reset. * * @api */ @@ -312,7 +312,7 @@ msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) { while (chOQIsFullI(oqp)) { msg_t msg; - if ((msg = qwait((GenericQueue *)oqp, time)) < RDY_OK) { + if ((msg = qwait((GenericQueue *)oqp, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -351,7 +351,7 @@ msg_t chOQGetI(OutputQueue *oqp) { if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; if (notempty(&oqp->q_waiting)) - chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = RDY_OK; + chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; return b; } @@ -391,7 +391,7 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, while (chOQIsFullI(oqp)) { if (nfy) nfy(oqp); - if (qwait((GenericQueue *)oqp, time) != RDY_OK) { + if (qwait((GenericQueue *)oqp, time) != Q_OK) { chSysUnlock(); return w; } -- cgit v1.2.3 From f4ec81ae144ef2ae7ddd9a0e56082970420c0464 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 May 2011 12:46:24 +0000 Subject: USB CDC functionality restored, more improvements to the I/O queues. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2983 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/src/chqueues.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'os/kernel/src/chqueues.c') diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index 767a36e63..8532f8307 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -136,8 +136,10 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { *iqp->q_wrptr++ = b; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; + if (notempty(&iqp->q_waiting)) chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; + return Q_OK; } @@ -146,6 +148,9 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * @details This function reads a byte value from an input queue. If the queue * is empty then the calling thread is suspended until a byte arrives * in the queue or a timeout occurs. + * @note The callback is invoked if the queue is empty before entering the + * @p THD_STATE_WTQUEUE state in order to solicit the low level to + * start queue filling. * * @param[in] iqp pointer to an @p InputQueue structure * @param[in] time the number of ticks before the operation timeouts, @@ -192,8 +197,9 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { * been reset. * @note The function is not atomic, if you need atomicity it is suggested * to use a semaphore or a mutex for mutual exclusion. - * @note The queue callback is invoked before entering a sleep state and at - * the end of the transfer. + * @note The callback is invoked if the queue is empty before entering the + * @p THD_STATE_WTQUEUE state in order to solicit the low level to + * start queue filling. * * @param[in] iqp pointer to an @p InputQueue structure * @param[out] bp pointer to the data buffer @@ -220,6 +226,7 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, while (chIQIsEmptyI(iqp)) { if (nfy) nfy(iqp); + if (qwait((GenericQueue *)iqp, time) != Q_OK) { chSysUnlock(); return r; @@ -230,15 +237,12 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, *bp++ = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) iqp->q_rdptr = iqp->q_buffer; + chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ r++; - if (--n == 0) { - chSysLock(); - if (nfy) - nfy(iqp); - chSysUnlock(); + if (--n == 0) return r; - } + chSysLock(); } } @@ -291,6 +295,8 @@ void chOQResetI(OutputQueue *oqp) { * @details This function writes a byte value to an output queue. If the queue * is full then the calling thread is suspended until there is space * in the queue or a timeout occurs. + * @note The callback is invoked after writing the character into the + * buffer. * * @param[in] oqp pointer to an @p OutputQueue structure * @param[in] b the byte value to be written in the queue @@ -350,8 +356,10 @@ msg_t chOQGetI(OutputQueue *oqp) { b = *oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; + if (notempty(&oqp->q_waiting)) chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; + return b; } @@ -363,8 +371,8 @@ msg_t chOQGetI(OutputQueue *oqp) { * been reset. * @note The function is not atomic, if you need atomicity it is suggested * to use a semaphore or a mutex for mutual exclusion. - * @note The queue callback is invoked before entering a sleep state and at - * the end of the transfer. + * @note The callback is invoked after writing each character into the + * buffer. * * @param[in] oqp pointer to an @p OutputQueue structure * @param[out] bp pointer to the data buffer @@ -389,8 +397,6 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, chSysLock(); while (TRUE) { while (chOQIsFullI(oqp)) { - if (nfy) - nfy(oqp); if (qwait((GenericQueue *)oqp, time) != Q_OK) { chSysUnlock(); return w; @@ -400,15 +406,14 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, *oqp->q_wrptr++ = *bp++; if (oqp->q_wrptr >= oqp->q_top) oqp->q_wrptr = oqp->q_buffer; + + if (nfy) + nfy(oqp); + chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ w++; - if (--n == 0) { - chSysLock(); - if (nfy) - nfy(oqp); - chSysUnlock(); + if (--n == 0) return w; - } chSysLock(); } } -- cgit v1.2.3