From 157b6f9695e7f72f2d54b231c19cb4045710ed01 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 21 Feb 2010 07:24:53 +0000 Subject: Updated license dates. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1646 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/include/ch.h | 12 +- os/kernel/include/channels.h | 2 +- os/kernel/include/condvars.h | 2 +- os/kernel/include/debug.h | 2 +- os/kernel/include/events.h | 2 +- os/kernel/include/heap.h | 2 +- os/kernel/include/inline.h | 2 +- os/kernel/include/lists.h | 4 +- os/kernel/include/mailboxes.h | 4 +- os/kernel/include/memcore.h | 2 +- os/kernel/include/mempools.h | 6 +- os/kernel/include/messages.h | 2 +- os/kernel/include/mutexes.h | 2 +- os/kernel/include/queues.h | 484 +++++++++++----------- os/kernel/include/registry.h | 4 +- os/kernel/include/scheduler.h | 268 ++++++------- os/kernel/include/semaphores.h | 6 +- os/kernel/include/streams.h | 2 +- os/kernel/include/sys.h | 4 +- os/kernel/include/threads.h | 660 +++++++++++++++--------------- os/kernel/include/vt.h | 6 +- os/kernel/kernel.dox | 4 +- os/kernel/src/chcond.c | 2 +- os/kernel/src/chdebug.c | 4 +- os/kernel/src/chevents.c | 2 +- os/kernel/src/chheap.c | 2 +- os/kernel/src/chlists.c | 2 +- os/kernel/src/chmboxes.c | 4 +- os/kernel/src/chmemcore.c | 6 +- os/kernel/src/chmempools.c | 2 +- os/kernel/src/chmsg.c | 2 +- os/kernel/src/chmtx.c | 552 ++++++++++++------------- os/kernel/src/chqueues.c | 2 +- os/kernel/src/chregistry.c | 6 +- os/kernel/src/chschd.c | 560 +++++++++++++------------- os/kernel/src/chsem.c | 2 +- os/kernel/src/chsys.c | 260 ++++++------ os/kernel/src/chthreads.c | 892 ++++++++++++++++++++--------------------- os/kernel/src/chvt.c | 4 +- os/kernel/templates/chconf.h | 4 +- os/kernel/templates/chcore.c | 16 +- os/kernel/templates/chcore.h | 6 +- os/kernel/templates/chtypes.h | 2 +- 43 files changed, 1907 insertions(+), 1907 deletions(-) (limited to 'os/kernel') diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h index a0b2ca6fd..8f3f07e21 100644 --- a/os/kernel/include/ch.h +++ b/os/kernel/include/ch.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -31,27 +31,27 @@ #define _CH_H_ /** - * @brief ChibiOS/RT identification macro. + * @brief ChibiOS/RT identification macro. */ #define _CHIBIOS_RT_ /** - * @brief Kernel version string. + * @brief Kernel version string. */ #define CH_KERNEL_VERSION "1.5.2unstable" /** - * @brief Kernel version major number. + * @brief Kernel version major number. */ #define CH_KERNEL_MAJOR 1 /** - * @brief Kernel version minor number. + * @brief Kernel version minor number. */ #define CH_KERNEL_MINOR 5 /** - * @brief Kernel version patch number. + * @brief Kernel version patch number. */ #define CH_KERNEL_PATCH 2 diff --git a/os/kernel/include/channels.h b/os/kernel/include/channels.h index 7e275af96..06c7cf88a 100644 --- a/os/kernel/include/channels.h +++ b/os/kernel/include/channels.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/condvars.h b/os/kernel/include/condvars.h index be40f7dd3..a84fa3bdb 100644 --- a/os/kernel/include/condvars.h +++ b/os/kernel/include/condvars.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/debug.h b/os/kernel/include/debug.h index b60171866..5cd056a81 100644 --- a/os/kernel/include/debug.h +++ b/os/kernel/include/debug.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/events.h b/os/kernel/include/events.h index 42f415b73..c434eb7ce 100644 --- a/os/kernel/include/events.h +++ b/os/kernel/include/events.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/heap.h b/os/kernel/include/heap.h index 0ebe1d7b5..8be48961a 100644 --- a/os/kernel/include/heap.h +++ b/os/kernel/include/heap.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/inline.h b/os/kernel/include/inline.h index 43f12f2e7..2b160f03f 100644 --- a/os/kernel/include/inline.h +++ b/os/kernel/include/inline.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/lists.h b/os/kernel/include/lists.h index 9240a6fcb..48841c687 100644 --- a/os/kernel/include/lists.h +++ b/os/kernel/include/lists.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -45,7 +45,7 @@ typedef struct Thread Thread; /** * @brief Evaluates to @p TRUE if the specified threads queue or list is - * empty. + * empty. */ #define isempty(p) ((p)->p_next == (Thread *)(p)) diff --git a/os/kernel/include/mailboxes.h b/os/kernel/include/mailboxes.h index 33048229f..d2c71b6d8 100644 --- a/os/kernel/include/mailboxes.h +++ b/os/kernel/include/mailboxes.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -102,7 +102,7 @@ extern "C" { * @note A message must be waiting in the queue for this function to work or * it would return garbage. The correct way to use this macro is to * use @p chMBGetFull() and then use this macro, all within a lock - * state. + * state. */ #define chMBPeek(mbp) (*(mbp)->mb_rdptr) diff --git a/os/kernel/include/memcore.h b/os/kernel/include/memcore.h index c0aa9c9a2..381339938 100644 --- a/os/kernel/include/memcore.h +++ b/os/kernel/include/memcore.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/mempools.h b/os/kernel/include/mempools.h index d6611663a..056ceaae8 100644 --- a/os/kernel/include/mempools.h +++ b/os/kernel/include/mempools.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -31,7 +31,7 @@ #if CH_USE_MEMPOOLS /** - * @brief Memory pool free object header. + * @brief Memory pool free object header. */ struct pool_header { struct pool_header *ph_next; /**< @brief Pointer to the next pool @@ -39,7 +39,7 @@ struct pool_header { }; /** - * @brief Memory pool descriptor. + * @brief Memory pool descriptor. */ typedef struct { struct pool_header *mp_next; /**< @brief Pointer to the header. */ diff --git a/os/kernel/include/messages.h b/os/kernel/include/messages.h index 669b1c8b9..d5e7cb32e 100644 --- a/os/kernel/include/messages.h +++ b/os/kernel/include/messages.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/mutexes.h b/os/kernel/include/mutexes.h index 5bdbcdbd9..a57e8386a 100644 --- a/os/kernel/include/mutexes.h +++ b/os/kernel/include/mutexes.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/queues.h b/os/kernel/include/queues.h index 124175133..fb2f13194 100644 --- a/os/kernel/include/queues.h +++ b/os/kernel/include/queues.h @@ -1,242 +1,242 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file queues.h I/O - * @brief Queues macros and structures. - * - * @addtogroup io_queues - * @{ - */ - -#ifndef _QUEUES_H_ -#define _QUEUES_H_ - -#if CH_USE_QUEUES - -/* - * Module dependencies check. - */ -#if !CH_USE_SEMAPHORES -#error "CH_USE_QUEUES requires CH_USE_SEMAPHORES" -#endif - -/** @brief Queue notification callback type.*/ -typedef void (*qnotify_t)(void); - -/** @brief Returned by the queue functions if the operation is successful.*/ -#define Q_OK RDY_OK -/** @brief Returned by the queue functions if a timeout occurs.*/ -#define Q_TIMEOUT RDY_TIMEOUT -/** @brief Returned by the queue functions if the queue is reset.*/ -#define Q_RESET RDY_RESET -/** @brief Returned by the queue functions if the queue is empty.*/ -#define Q_EMPTY -3 -/** @brief Returned by the queue functions if the queue is full.*/ -#define Q_FULL -4 - -/** - * @brief Generic I/O queue structure. - * @details This structure represents a generic Input or Output asymmetrical - * queue. The queue is asymmetrical because one end is meant to be - * accessed from a thread context, and thus can be blocking, the other - * end is accessible from interrupt handlers or from within a kernel - * lock zone (see I-Locked and S-Locked states in - * @ref system_states) and is non-blocking. - */ -typedef struct { - uint8_t *q_buffer; /**< @brief Pointer to the queue buffer.*/ - uint8_t *q_top; /**< @brief Pointer to the first location - after the buffer. */ - uint8_t *q_wrptr; /**< @brief Write pointer. */ - uint8_t *q_rdptr; /**< @brief Read pointer. */ - Semaphore q_sem; /**< @brief Counter @p Semaphore. */ - qnotify_t q_notify; /**< @brief Data notification callback. */ -} GenericQueue; - -/** - * @brief Returns the queue's buffer size. - */ -#define chQSize(q) ((q)->q_top - (q)->q_buffer) - -/** - * @brief Queue space. - * @details Returns the used space if used on an Input Queue and the empty - * space if used on an Output Queue. - * @note The returned value can be less than zero when there are waiting - * threads on the internal semaphore. - */ -#define chQSpace(q) chSemGetCounterI(&(q)->q_sem) - -/** - * @extends GenericQueue - * - * @brief Input queue structure. - * @details This structure represents a generic asymmetrical input queue. - * Writing in the queue is non-blocking and can be performed from - * interrupt handlers or from within a kernel lock zone (see - * I-Locked and S-Locked states in @ref system_states). - * Reading the queue can be a blocking operation and is supposed to - * be performed by a system thread. - */ -typedef GenericQueue InputQueue; - -/** @brief Evaluates to @p TRUE if the specified Input Queue is empty.*/ -#define chIQIsEmpty(q) (chQSpace(q) <= 0) - -/** @brief Evaluates to @p TRUE if the specified Input Queue is full.*/ -#define chIQIsFull(q) (chQSpace(q) >= chQSize(q)) - -/** - * @brief Input queue read. - * @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. - * - * @param[in] iqp pointer to an @p InputQueue structure - * @return A byte value from the queue or: - * @retval Q_RESET if the queue was reset. - */ -#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE) - -/** - * @brief Data part of a static input queue initializer. - * @details This macro should be used when statically initializing an - * input queue that is part of a bigger structure. - * - * @param[in] name the name of the input queue variable - * @param[in] buffer pointer to the queue buffer area - * @param[in] size size of the queue buffer area - * @param[in] inotify input notification callback pointer - */ -#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer) + size, \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer), \ - _SEMAPHORE_DATA(name.q_sem, 0), \ - inotify \ -} - -/** - * @brief Static input queue initializer. - * @details Statically initialized input queues require no explicit - * initialization using @p chIQInit(). - * - * @param[in] name the name of the input queue variable - * @param[in] buffer pointer to the queue buffer area - * @param[in] size size of the queue buffer area - * @param[in] inotify input notification callback pointer - */ -#define INPUTQUEUE_DECL(name, buffer, size, inotify) \ - InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify) - -/** - * @extends GenericQueue - * - * @brief Output queue structure. - * @details This structure represents a generic asymmetrical output queue. - * Reading from the queue is non-blocking and can be performed from - * interrupt handlers or from within a kernel lock zone (see - * I-Locked and S-Locked states in @ref system_states). - * Writing the queue can be a blocking operation and is supposed to - * be performed by a system thread. - */ -typedef GenericQueue OutputQueue; - -/** - * @brief Evaluates to @p TRUE if the specified Output Queue is empty. - */ -#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q)) - -/** - * @brief Evaluates to @p TRUE if the specified Output Queue is full. - */ -#define chOQIsFull(q) (chQSpace(q) <= 0) - -/** - * @brief Output queue write. - * @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. - * - * @param[in] oqp pointer to an @p OutputQueue structure - * @param[in] b the byte value to be written in the queue - * @return The operation status: - * @retval Q_OK if the operation succeeded. - * @retval Q_RESET if the queue was reset. - */ -#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE) - -/** - * @brief Data part of a static output queue initializer. - * @details This macro should be used when statically initializing an - * output queue that is part of a bigger structure. - * - * @param[in] name the name of the output queue variable. - * @param[in] buffer pointer to the queue buffer area - * @param[in] size size of the queue buffer area - * @param[in] onotify output notification callback pointer - */ -#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer) + size, \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer), \ - _SEMAPHORE_DATA(name.q_sem, size), \ - onotify \ -} - -/** - * @brief Static output queue initializer. - * @details Statically initialized output queues require no explicit - * initialization using @p chOQInit(). - * - * @param[in] name the name of the output queue variable - * @param[in] buffer pointer to the queue buffer area - * @param[in] size size of the queue buffer area - * @param[in] onotify output notification callback pointer - */ -#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \ - InputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify) - -#ifdef __cplusplus -extern "C" { -#endif - void chIQInit(InputQueue *qp, uint8_t *bp, size_t size, qnotify_t infy); - void chIQResetI(InputQueue *qp); - msg_t chIQPutI(InputQueue *qp, uint8_t b); - msg_t chIQGetTimeout(InputQueue *qp, systime_t time); - size_t chIQReadTimeout(InputQueue *qp, uint8_t *bp, - size_t n, systime_t time); - - void chOQInit(OutputQueue *queue, uint8_t *bp, size_t size, qnotify_t onfy); - void chOQResetI(OutputQueue *queue); - msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t time); - msg_t chOQGetI(OutputQueue *queue); - size_t chOQWriteTimeout(OutputQueue *queue, const uint8_t *bp, - size_t n, systime_t time); -#ifdef __cplusplus -} -#endif -#endif /* CH_USE_QUEUES */ - -#endif /* _QUEUES_H_ */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file queues.h I/O + * @brief Queues macros and structures. + * + * @addtogroup io_queues + * @{ + */ + +#ifndef _QUEUES_H_ +#define _QUEUES_H_ + +#if CH_USE_QUEUES + +/* + * Module dependencies check. + */ +#if !CH_USE_SEMAPHORES +#error "CH_USE_QUEUES requires CH_USE_SEMAPHORES" +#endif + +/** @brief Queue notification callback type.*/ +typedef void (*qnotify_t)(void); + +/** @brief Returned by the queue functions if the operation is successful.*/ +#define Q_OK RDY_OK +/** @brief Returned by the queue functions if a timeout occurs.*/ +#define Q_TIMEOUT RDY_TIMEOUT +/** @brief Returned by the queue functions if the queue is reset.*/ +#define Q_RESET RDY_RESET +/** @brief Returned by the queue functions if the queue is empty.*/ +#define Q_EMPTY -3 +/** @brief Returned by the queue functions if the queue is full.*/ +#define Q_FULL -4 + +/** + * @brief Generic I/O queue structure. + * @details This structure represents a generic Input or Output asymmetrical + * queue. The queue is asymmetrical because one end is meant to be + * accessed from a thread context, and thus can be blocking, the other + * end is accessible from interrupt handlers or from within a kernel + * lock zone (see I-Locked and S-Locked states in + * @ref system_states) and is non-blocking. + */ +typedef struct { + uint8_t *q_buffer; /**< @brief Pointer to the queue buffer.*/ + uint8_t *q_top; /**< @brief Pointer to the first location + after the buffer. */ + uint8_t *q_wrptr; /**< @brief Write pointer. */ + uint8_t *q_rdptr; /**< @brief Read pointer. */ + Semaphore q_sem; /**< @brief Counter @p Semaphore. */ + qnotify_t q_notify; /**< @brief Data notification callback. */ +} GenericQueue; + +/** + * @brief Returns the queue's buffer size. + */ +#define chQSize(q) ((q)->q_top - (q)->q_buffer) + +/** + * @brief Queue space. + * @details Returns the used space if used on an Input Queue and the empty + * space if used on an Output Queue. + * @note The returned value can be less than zero when there are waiting + * threads on the internal semaphore. + */ +#define chQSpace(q) chSemGetCounterI(&(q)->q_sem) + +/** + * @extends GenericQueue + * + * @brief Input queue structure. + * @details This structure represents a generic asymmetrical input queue. + * Writing in the queue is non-blocking and can be performed from + * interrupt handlers or from within a kernel lock zone (see + * I-Locked and S-Locked states in @ref system_states). + * Reading the queue can be a blocking operation and is supposed to + * be performed by a system thread. + */ +typedef GenericQueue InputQueue; + +/** @brief Evaluates to @p TRUE if the specified Input Queue is empty.*/ +#define chIQIsEmpty(q) (chQSpace(q) <= 0) + +/** @brief Evaluates to @p TRUE if the specified Input Queue is full.*/ +#define chIQIsFull(q) (chQSpace(q) >= chQSize(q)) + +/** + * @brief Input queue read. + * @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. + * + * @param[in] iqp pointer to an @p InputQueue structure + * @return A byte value from the queue or: + * @retval Q_RESET if the queue was reset. + */ +#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE) + +/** + * @brief Data part of a static input queue initializer. + * @details This macro should be used when statically initializing an + * input queue that is part of a bigger structure. + * + * @param[in] name the name of the input queue variable + * @param[in] buffer pointer to the queue buffer area + * @param[in] size size of the queue buffer area + * @param[in] inotify input notification callback pointer + */ +#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer) + size, \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer), \ + _SEMAPHORE_DATA(name.q_sem, 0), \ + inotify \ +} + +/** + * @brief Static input queue initializer. + * @details Statically initialized input queues require no explicit + * initialization using @p chIQInit(). + * + * @param[in] name the name of the input queue variable + * @param[in] buffer pointer to the queue buffer area + * @param[in] size size of the queue buffer area + * @param[in] inotify input notification callback pointer + */ +#define INPUTQUEUE_DECL(name, buffer, size, inotify) \ + InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify) + +/** + * @extends GenericQueue + * + * @brief Output queue structure. + * @details This structure represents a generic asymmetrical output queue. + * Reading from the queue is non-blocking and can be performed from + * interrupt handlers or from within a kernel lock zone (see + * I-Locked and S-Locked states in @ref system_states). + * Writing the queue can be a blocking operation and is supposed to + * be performed by a system thread. + */ +typedef GenericQueue OutputQueue; + +/** + * @brief Evaluates to @p TRUE if the specified Output Queue is empty. + */ +#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q)) + +/** + * @brief Evaluates to @p TRUE if the specified Output Queue is full. + */ +#define chOQIsFull(q) (chQSpace(q) <= 0) + +/** + * @brief Output queue write. + * @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. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] b the byte value to be written in the queue + * @return The operation status: + * @retval Q_OK if the operation succeeded. + * @retval Q_RESET if the queue was reset. + */ +#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE) + +/** + * @brief Data part of a static output queue initializer. + * @details This macro should be used when statically initializing an + * output queue that is part of a bigger structure. + * + * @param[in] name the name of the output queue variable. + * @param[in] buffer pointer to the queue buffer area + * @param[in] size size of the queue buffer area + * @param[in] onotify output notification callback pointer + */ +#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer) + size, \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer), \ + _SEMAPHORE_DATA(name.q_sem, size), \ + onotify \ +} + +/** + * @brief Static output queue initializer. + * @details Statically initialized output queues require no explicit + * initialization using @p chOQInit(). + * + * @param[in] name the name of the output queue variable + * @param[in] buffer pointer to the queue buffer area + * @param[in] size size of the queue buffer area + * @param[in] onotify output notification callback pointer + */ +#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \ + InputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify) + +#ifdef __cplusplus +extern "C" { +#endif + void chIQInit(InputQueue *qp, uint8_t *bp, size_t size, qnotify_t infy); + void chIQResetI(InputQueue *qp); + msg_t chIQPutI(InputQueue *qp, uint8_t b); + msg_t chIQGetTimeout(InputQueue *qp, systime_t time); + size_t chIQReadTimeout(InputQueue *qp, uint8_t *bp, + size_t n, systime_t time); + + void chOQInit(OutputQueue *queue, uint8_t *bp, size_t size, qnotify_t onfy); + void chOQResetI(OutputQueue *queue); + msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t time); + msg_t chOQGetI(OutputQueue *queue); + size_t chOQWriteTimeout(OutputQueue *queue, const uint8_t *bp, + size_t n, systime_t time); +#ifdef __cplusplus +} +#endif +#endif /* CH_USE_QUEUES */ + +#endif /* _QUEUES_H_ */ + +/** @} */ diff --git a/os/kernel/include/registry.h b/os/kernel/include/registry.h index afaf3c5f7..2bff903e8 100644 --- a/os/kernel/include/registry.h +++ b/os/kernel/include/registry.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -34,7 +34,7 @@ * @brief Removes a thread from the registry list. * @note This macro is not meant for use in application code. * - * @param[in] tp thread to remove from the registry + * @param[in] tp thread to remove from the registry */ #define REG_REMOVE(tp) { \ (tp)->p_older->p_newer = (tp)->p_newer; \ diff --git a/os/kernel/include/scheduler.h b/os/kernel/include/scheduler.h index e6bc69078..ddb7df979 100644 --- a/os/kernel/include/scheduler.h +++ b/os/kernel/include/scheduler.h @@ -1,134 +1,134 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file scheduler.h - * @brief Scheduler macros and structures. - * - * @addtogroup scheduler - * @{ - */ - -#ifndef _SCHEDULER_H_ -#define _SCHEDULER_H_ - -/** @brief Default thread wakeup low level message.*/ -#define RDY_OK 0 -/** @brief Low level message sent to a thread awakened by a timeout.*/ -#define RDY_TIMEOUT -1 -/** @brief Low level message sent to a thread awakened by a reset operation.*/ -#define RDY_RESET -2 - -#define NOPRIO 0 /**< @brief Ready list header priority. */ -#define IDLEPRIO 1 /**< @brief Idle thread priority. */ -#define LOWPRIO 2 /**< @brief Lowest user priority. */ -#define NORMALPRIO 64 /**< @brief Normal user priority. */ -#define HIGHPRIO 127 /**< @brief Highest user priority. */ -#define ABSPRIO 255 /**< @brief Greatest possible priority. */ - -/** - * @brief Zero time specification for some syscalls with a timeout - * specification. - * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter, - * see the specific function documentation. - */ -#define TIME_IMMEDIATE ((systime_t)-1) - -/** - * @brief Infinite time specification for all the syscalls with a timeout - * specification. - */ -#define TIME_INFINITE ((systime_t)0) - -/** - * @brief Returns the priority of the first thread on the given ready list. - */ -#define firstprio(rlp) ((rlp)->p_next->p_prio) - -/** - * @extends ThreadsQueue - * - * @brief Ready list header. - */ -typedef struct { - ThreadsQueue r_queue; /**< @brief Threads queue. */ - tprio_t r_prio; /**< @brief This field must be - initialized to zero. */ - struct context p_ctx; /**< @brief Not used, present because - offsets. */ -#if CH_USE_REGISTRY - Thread *p_newer; /**< @brief Newer registry element. */ - Thread *p_older; /**< @brief Older registry element. */ -#endif - /* End of the fields shared with the Thread structure.*/ -#if CH_TIME_QUANTUM > 0 - cnt_t r_preempt; /**< @brief Round robin counter. */ -#endif -#ifndef CH_CURRP_REGISTER_CACHE - Thread *r_current; /**< @brief The currently running - thread. */ -#endif -} ReadyList; - -#if !defined(__DOXYGEN__) -extern ReadyList rlist; -#endif - -#ifdef CH_CURRP_REGISTER_CACHE -register Thread *currp asm(CH_CURRP_REGISTER_CACHE); -#else -#define currp rlist.r_current -#endif - -/* - * Scheduler APIs. - */ -#ifdef __cplusplus -extern "C" { -#endif - void scheduler_init(void); - Thread *chSchReadyI(Thread *tp); - void chSchGoSleepS(tstate_t newstate); - msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time); - void chSchWakeupS(Thread *tp, msg_t msg); - void chSchDoRescheduleI(void); - void chSchRescheduleS(void); - bool_t chSchIsRescRequiredExI(void); - void chSchDoYieldS(void); -#ifdef __cplusplus -} -#endif - -/** - * @brief Determines if yielding is possible. - * @details This function returns @p TRUE if there is a ready thread with - * equal or higher priority. - */ -#define chSchCanYieldS() (firstprio(&rlist.r_queue) >= currp->p_prio) - -/** - * @brief Determines if the current thread must reschedule. - * @details This function returns @p TRUE if there is a ready thread with - * higher priority. - */ -#define chSchIsRescRequiredI() (firstprio(&rlist.r_queue) > currp->p_prio) - -#endif /* _SCHEDULER_H_ */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file scheduler.h + * @brief Scheduler macros and structures. + * + * @addtogroup scheduler + * @{ + */ + +#ifndef _SCHEDULER_H_ +#define _SCHEDULER_H_ + +/** @brief Default thread wakeup low level message.*/ +#define RDY_OK 0 +/** @brief Low level message sent to a thread awakened by a timeout.*/ +#define RDY_TIMEOUT -1 +/** @brief Low level message sent to a thread awakened by a reset operation.*/ +#define RDY_RESET -2 + +#define NOPRIO 0 /**< @brief Ready list header priority. */ +#define IDLEPRIO 1 /**< @brief Idle thread priority. */ +#define LOWPRIO 2 /**< @brief Lowest user priority. */ +#define NORMALPRIO 64 /**< @brief Normal user priority. */ +#define HIGHPRIO 127 /**< @brief Highest user priority. */ +#define ABSPRIO 255 /**< @brief Greatest possible priority. */ + +/** + * @brief Zero time specification for some syscalls with a timeout + * specification. + * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter, + * see the specific function documentation. + */ +#define TIME_IMMEDIATE ((systime_t)-1) + +/** + * @brief Infinite time specification for all the syscalls with a timeout + * specification. + */ +#define TIME_INFINITE ((systime_t)0) + +/** + * @brief Returns the priority of the first thread on the given ready list. + */ +#define firstprio(rlp) ((rlp)->p_next->p_prio) + +/** + * @extends ThreadsQueue + * + * @brief Ready list header. + */ +typedef struct { + ThreadsQueue r_queue; /**< @brief Threads queue. */ + tprio_t r_prio; /**< @brief This field must be + initialized to zero. */ + struct context p_ctx; /**< @brief Not used, present because + offsets. */ +#if CH_USE_REGISTRY + Thread *p_newer; /**< @brief Newer registry element. */ + Thread *p_older; /**< @brief Older registry element. */ +#endif + /* End of the fields shared with the Thread structure.*/ +#if CH_TIME_QUANTUM > 0 + cnt_t r_preempt; /**< @brief Round robin counter. */ +#endif +#ifndef CH_CURRP_REGISTER_CACHE + Thread *r_current; /**< @brief The currently running + thread. */ +#endif +} ReadyList; + +#if !defined(__DOXYGEN__) +extern ReadyList rlist; +#endif + +#ifdef CH_CURRP_REGISTER_CACHE +register Thread *currp asm(CH_CURRP_REGISTER_CACHE); +#else +#define currp rlist.r_current +#endif + +/* + * Scheduler APIs. + */ +#ifdef __cplusplus +extern "C" { +#endif + void scheduler_init(void); + Thread *chSchReadyI(Thread *tp); + void chSchGoSleepS(tstate_t newstate); + msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time); + void chSchWakeupS(Thread *tp, msg_t msg); + void chSchDoRescheduleI(void); + void chSchRescheduleS(void); + bool_t chSchIsRescRequiredExI(void); + void chSchDoYieldS(void); +#ifdef __cplusplus +} +#endif + +/** + * @brief Determines if yielding is possible. + * @details This function returns @p TRUE if there is a ready thread with + * equal or higher priority. + */ +#define chSchCanYieldS() (firstprio(&rlist.r_queue) >= currp->p_prio) + +/** + * @brief Determines if the current thread must reschedule. + * @details This function returns @p TRUE if there is a ready thread with + * higher priority. + */ +#define chSchIsRescRequiredI() (firstprio(&rlist.r_queue) > currp->p_prio) + +#endif /* _SCHEDULER_H_ */ + +/** @} */ diff --git a/os/kernel/include/semaphores.h b/os/kernel/include/semaphores.h index b2fbba65c..cced49601 100644 --- a/os/kernel/include/semaphores.h +++ b/os/kernel/include/semaphores.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -62,7 +62,7 @@ extern "C" { * @brief Data part of a static semaphore initializer. * @details This macro should be used when statically initializing a semaphore * that is part of a bigger structure. - * + * * @param[in] name the name of the semaphore variable * @param[in] n the counter initial value, this value must be * non-negative @@ -76,7 +76,7 @@ extern "C" { * * @param[in] name the name of the semaphore variable * @param[in] n the counter initial value, this value must be - * non-negative + * non-negative */ #define SEMAPHORE_DECL(name, n) Semaphore name = _SEMAPHORE_DATA(name, n) diff --git a/os/kernel/include/streams.h b/os/kernel/include/streams.h index b4f7f4901..fa376546c 100644 --- a/os/kernel/include/streams.h +++ b/os/kernel/include/streams.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/include/sys.h b/os/kernel/include/sys.h index a6409d3bf..5d0b6d875 100644 --- a/os/kernel/include/sys.h +++ b/os/kernel/include/sys.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -154,7 +154,7 @@ #define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE() /** - * @brief Standard IRQ handler declaration. + * @brief Standard IRQ handler declaration. * @note @p id can be a function name or a vector number depending on the * port implementation. */ diff --git a/os/kernel/include/threads.h b/os/kernel/include/threads.h index 253b220fe..9f519fea0 100644 --- a/os/kernel/include/threads.h +++ b/os/kernel/include/threads.h @@ -1,330 +1,330 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file threads.h - * @brief Threads macros and structures. - * - * @addtogroup threads - * @{ - */ - -#ifndef _THREADS_H_ -#define _THREADS_H_ - -/* - * Module dependencies check. - */ -#if CH_USE_DYNAMIC && !CH_USE_WAITEXIT -#error "CH_USE_DYNAMIC requires CH_USE_WAITEXIT" -#endif -#if CH_USE_DYNAMIC && !CH_USE_HEAP && !CH_USE_MEMPOOLS -#error "CH_USE_DYNAMIC requires CH_USE_HEAP and/or CH_USE_MEMPOOLS" -#endif - -/** - * @extends ThreadsQueue - * - * @brief Structure representing a thread. - * @note Not all the listed fields are always needed, by switching off some - * not needed ChibiOS/RT subsystems it is possible to save RAM space - * by shrinking the @p Thread structure. - */ -struct Thread { - Thread *p_next; /**< @brief Next in the list/queue. */ - /* End of the fields shared with the ThreadsList structure. */ - Thread *p_prev; /**< @brief Previous in the queue. */ - /* End of the fields shared with the ThreadsQueue structure. */ - tprio_t p_prio; /**< @brief Thread priority. */ - struct context p_ctx; /**< @brief Processor context. */ -#if CH_USE_REGISTRY - Thread *p_newer; /**< @brief Newer registry element. */ - Thread *p_older; /**< @brief Older registry element. */ -#endif - /* End of the fields shared with the ReadyList structure. */ - /** - * @brief Current thread state. - */ - tstate_t p_state; - /** - * @brief Various thread flags. - */ - tmode_t p_flags; -#if CH_USE_DYNAMIC - /** - * @brief References to this thread. - */ - trefs_t p_refs; -#endif -#if CH_USE_NESTED_LOCKS - /** - * @brief Number of nested locks. - */ - cnt_t p_locks; -#endif -#if CH_DBG_THREADS_PROFILING - /** - * @brief Thread consumed time in ticks. - * @note This field can overflow. - */ - volatile systime_t p_time; -#endif - /** - * @brief State-specific fields. - * @note All the fields declared in this union are only valid in the - * specified state or condition and are thus volatile. - */ - union { - /** - * @brief Thread wakeup code. - * @note This field contains the low level message sent to the thread - * by the waking thread or interrupt handler. The value is valid - * after exiting the @p chSchWakeupS() function. - */ - msg_t rdymsg; - /** - * @brief Thread exit code. - * @note The thread termination code is stored in this field in order - * to be retrieved by the thread performing a @p chThdWait() on - * this thread. - */ - msg_t exitcode; - /** - * @brief Pointer to a generic "wait" object. - * @note This field is used to get a generic pointer to a synchronization - * object and is valid when the thread is in one of the wait - * states. - */ - void *wtobjp; -#if CH_USE_EVENTS - /** - * @brief Enabled events mask. - * @note This field is only valied while the thread is in the - * @p THD_STATE_WTOREVT or @p THD_STATE_WTANDEVT states. - */ - eventmask_t ewmask; -#endif - } p_u; -#if CH_USE_WAITEXIT - /** - * @brief Termination waiting list. - */ - ThreadsList p_waiting; -#endif -#if CH_USE_MESSAGES - /** - * @brief Messages queue. - */ - ThreadsQueue p_msgqueue; - /** - * @brief Thread message. - */ - msg_t p_msg; -#endif -#if CH_USE_EVENTS - /** - * @brief Pending events mask. - */ - eventmask_t p_epending; -#endif -#if CH_USE_MUTEXES - /** - * @brief List of the mutexes owned by this thread. - * @note The list is terminated by a @p NULL in this field. - */ - Mutex *p_mtxlist; - /** - * @brief Thread's own, non-inherited, priority. - */ - tprio_t p_realprio; -#endif -#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS - /** - * @brief Memory Pool where the thread workspace is returned. - */ - void *p_mpool; -#endif - /* Extra fields defined in chconf.h.*/ - THREAD_EXT_FIELDS -}; - -/** @brief Thread state: Ready to run, waiting on the ready list.*/ -#define THD_STATE_READY 0 -/** @brief Thread state: Currently running.*/ -#define THD_STATE_CURRENT 1 -/** @brief Thread state: Thread created in suspended state.*/ -#define THD_STATE_SUSPENDED 2 -/** @brief Thread state: Waiting on a semaphore.*/ -#define THD_STATE_WTSEM 3 -/** @brief Thread state: Waiting on a mutex.*/ -#define THD_STATE_WTMTX 4 -/** @brief Thread state: Waiting in @p chCondWait().*/ -#define THD_STATE_WTCOND 5 -/** @brief Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil().*/ -#define THD_STATE_SLEEPING 6 -/** @brief Thread state: Waiting in @p chThdWait().*/ -#define THD_STATE_WTEXIT 7 -/** @brief Thread state: Waiting in @p chEvtWaitXXX().*/ -#define THD_STATE_WTOREVT 8 -/** @brief Thread state: Waiting in @p chEvtWaitAllTimeout().*/ -#define THD_STATE_WTANDEVT 9 -/** @brief Thread state: Waiting in @p chMsgSend().*/ -#define THD_STATE_SNDMSG 10 -/** @brief Thread state: Waiting in @p chMsgWait().*/ -#define THD_STATE_WTMSG 11 -/** @brief Thread state: After termination.*/ -#define THD_STATE_FINAL 12 - -/* - * Various flags into the thread p_flags field. - */ -#define THD_MEM_MODE_MASK 3 /**< @brief Thread memory mode mask. */ -#define THD_MEM_MODE_STATIC 0 /**< @brief Thread memory mode: static. */ -#define THD_MEM_MODE_HEAP 1 /**< @brief Thread memory mode: heap. */ -#define THD_MEM_MODE_MEMPOOL 2 /**< @brief Thread memory mode: pool. */ -#define THD_TERMINATE 4 /**< @brief Termination requested. */ - -/** @brief Thread function.*/ -typedef msg_t (*tfunc_t)(void *); - -/* - * Threads APIs. - */ -#ifdef __cplusplus -extern "C" { -#endif - Thread *init_thread(Thread *tp, tprio_t prio); - Thread *chThdInit(void *wsp, size_t size, - tprio_t prio, tfunc_t pf, void *arg); - Thread *chThdCreateStatic(void *wsp, size_t size, - tprio_t prio, tfunc_t pf, void *arg); -#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP - Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size, - tprio_t prio, tfunc_t pf, void *arg); -#endif -#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS - Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, - tfunc_t pf, void *arg); -#endif - tprio_t chThdSetPriority(tprio_t newprio); - Thread *chThdResume(Thread *tp); - void chThdTerminate(Thread *tp); - void chThdSleep(systime_t time); - void chThdSleepUntil(systime_t time); - void chThdYield(void); - void chThdExit(msg_t msg); -#if CH_USE_DYNAMIC - Thread *chThdAddRef(Thread *tp); - void chThdRelease(Thread *tp); -#endif -#if CH_USE_WAITEXIT - msg_t chThdWait(Thread *tp); -#endif -#ifdef __cplusplus -} -#endif - -/** - * @brief Returns a pointer to the current @p Thread. - */ -#define chThdSelf() currp - -/** - * @brief Returns the current thread priority. - */ -#define chThdGetPriority() (currp->p_prio) - -/** - * @brief Returns the pointer to the @p Thread local storage area, if any. - */ -#define chThdLS() (void *)(currp + 1) - -/** - * @brief Verifies if the specified thread is in the @p THD_STATE_FINAL state. - * - * @param[in] tp the pointer to the thread - * @retval TRUE thread terminated. - * @retval FALSE thread not terminated. - */ -#define chThdTerminated(tp) ((tp)->p_state == THD_STATE_FINAL) - -/** - * @brief Verifies if the current thread has a termination request pending. - * - * @retval TRUE termination request pended. - * @retval FALSE termination request not pended. - */ -#define chThdShouldTerminate() (currp->p_flags & THD_TERMINATE) - -/** - * @brief Resumes a thread created with @p chThdInit(). - * - * @param[in] tp the pointer to the thread - */ -#define chThdResumeI(tp) chSchReadyI(tp) - -/** - * @brief Suspends the invoking thread for the specified time. - * - * @param[in] time the delay in system ticks, the special values are - * handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state. - * - @a TIME_IMMEDIATE this value is accepted but - * interpreted as a normal time specification not as - * an immediate timeout specification. - * . - */ -#define chThdSleepS(time) chSchGoSleepTimeoutS(THD_STATE_SLEEPING, time) - -/** - * @brief Delays the invoking thread for the specified number of seconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] sec the time in seconds - */ -#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec)) - -/** - * @brief Delays the invoking thread for the specified number of - * milliseconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] msec the time in milliseconds - */ -#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec)) - -/** - * @brief Delays the invoking thread for the specified number of - * microseconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] usec the time in microseconds - */ -#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec)) - -#endif /* _THREADS_H_ */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file threads.h + * @brief Threads macros and structures. + * + * @addtogroup threads + * @{ + */ + +#ifndef _THREADS_H_ +#define _THREADS_H_ + +/* + * Module dependencies check. + */ +#if CH_USE_DYNAMIC && !CH_USE_WAITEXIT +#error "CH_USE_DYNAMIC requires CH_USE_WAITEXIT" +#endif +#if CH_USE_DYNAMIC && !CH_USE_HEAP && !CH_USE_MEMPOOLS +#error "CH_USE_DYNAMIC requires CH_USE_HEAP and/or CH_USE_MEMPOOLS" +#endif + +/** + * @extends ThreadsQueue + * + * @brief Structure representing a thread. + * @note Not all the listed fields are always needed, by switching off some + * not needed ChibiOS/RT subsystems it is possible to save RAM space + * by shrinking the @p Thread structure. + */ +struct Thread { + Thread *p_next; /**< @brief Next in the list/queue. */ + /* End of the fields shared with the ThreadsList structure. */ + Thread *p_prev; /**< @brief Previous in the queue. */ + /* End of the fields shared with the ThreadsQueue structure. */ + tprio_t p_prio; /**< @brief Thread priority. */ + struct context p_ctx; /**< @brief Processor context. */ +#if CH_USE_REGISTRY + Thread *p_newer; /**< @brief Newer registry element. */ + Thread *p_older; /**< @brief Older registry element. */ +#endif + /* End of the fields shared with the ReadyList structure. */ + /** + * @brief Current thread state. + */ + tstate_t p_state; + /** + * @brief Various thread flags. + */ + tmode_t p_flags; +#if CH_USE_DYNAMIC + /** + * @brief References to this thread. + */ + trefs_t p_refs; +#endif +#if CH_USE_NESTED_LOCKS + /** + * @brief Number of nested locks. + */ + cnt_t p_locks; +#endif +#if CH_DBG_THREADS_PROFILING + /** + * @brief Thread consumed time in ticks. + * @note This field can overflow. + */ + volatile systime_t p_time; +#endif + /** + * @brief State-specific fields. + * @note All the fields declared in this union are only valid in the + * specified state or condition and are thus volatile. + */ + union { + /** + * @brief Thread wakeup code. + * @note This field contains the low level message sent to the thread + * by the waking thread or interrupt handler. The value is valid + * after exiting the @p chSchWakeupS() function. + */ + msg_t rdymsg; + /** + * @brief Thread exit code. + * @note The thread termination code is stored in this field in order + * to be retrieved by the thread performing a @p chThdWait() on + * this thread. + */ + msg_t exitcode; + /** + * @brief Pointer to a generic "wait" object. + * @note This field is used to get a generic pointer to a synchronization + * object and is valid when the thread is in one of the wait + * states. + */ + void *wtobjp; +#if CH_USE_EVENTS + /** + * @brief Enabled events mask. + * @note This field is only valied while the thread is in the + * @p THD_STATE_WTOREVT or @p THD_STATE_WTANDEVT states. + */ + eventmask_t ewmask; +#endif + } p_u; +#if CH_USE_WAITEXIT + /** + * @brief Termination waiting list. + */ + ThreadsList p_waiting; +#endif +#if CH_USE_MESSAGES + /** + * @brief Messages queue. + */ + ThreadsQueue p_msgqueue; + /** + * @brief Thread message. + */ + msg_t p_msg; +#endif +#if CH_USE_EVENTS + /** + * @brief Pending events mask. + */ + eventmask_t p_epending; +#endif +#if CH_USE_MUTEXES + /** + * @brief List of the mutexes owned by this thread. + * @note The list is terminated by a @p NULL in this field. + */ + Mutex *p_mtxlist; + /** + * @brief Thread's own, non-inherited, priority. + */ + tprio_t p_realprio; +#endif +#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS + /** + * @brief Memory Pool where the thread workspace is returned. + */ + void *p_mpool; +#endif + /* Extra fields defined in chconf.h.*/ + THREAD_EXT_FIELDS +}; + +/** @brief Thread state: Ready to run, waiting on the ready list.*/ +#define THD_STATE_READY 0 +/** @brief Thread state: Currently running.*/ +#define THD_STATE_CURRENT 1 +/** @brief Thread state: Thread created in suspended state.*/ +#define THD_STATE_SUSPENDED 2 +/** @brief Thread state: Waiting on a semaphore.*/ +#define THD_STATE_WTSEM 3 +/** @brief Thread state: Waiting on a mutex.*/ +#define THD_STATE_WTMTX 4 +/** @brief Thread state: Waiting in @p chCondWait().*/ +#define THD_STATE_WTCOND 5 +/** @brief Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil().*/ +#define THD_STATE_SLEEPING 6 +/** @brief Thread state: Waiting in @p chThdWait().*/ +#define THD_STATE_WTEXIT 7 +/** @brief Thread state: Waiting in @p chEvtWaitXXX().*/ +#define THD_STATE_WTOREVT 8 +/** @brief Thread state: Waiting in @p chEvtWaitAllTimeout().*/ +#define THD_STATE_WTANDEVT 9 +/** @brief Thread state: Waiting in @p chMsgSend().*/ +#define THD_STATE_SNDMSG 10 +/** @brief Thread state: Waiting in @p chMsgWait().*/ +#define THD_STATE_WTMSG 11 +/** @brief Thread state: After termination.*/ +#define THD_STATE_FINAL 12 + +/* + * Various flags into the thread p_flags field. + */ +#define THD_MEM_MODE_MASK 3 /**< @brief Thread memory mode mask. */ +#define THD_MEM_MODE_STATIC 0 /**< @brief Thread memory mode: static. */ +#define THD_MEM_MODE_HEAP 1 /**< @brief Thread memory mode: heap. */ +#define THD_MEM_MODE_MEMPOOL 2 /**< @brief Thread memory mode: pool. */ +#define THD_TERMINATE 4 /**< @brief Termination requested. */ + +/** @brief Thread function.*/ +typedef msg_t (*tfunc_t)(void *); + +/* + * Threads APIs. + */ +#ifdef __cplusplus +extern "C" { +#endif + Thread *init_thread(Thread *tp, tprio_t prio); + Thread *chThdInit(void *wsp, size_t size, + tprio_t prio, tfunc_t pf, void *arg); + Thread *chThdCreateStatic(void *wsp, size_t size, + tprio_t prio, tfunc_t pf, void *arg); +#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP + Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size, + tprio_t prio, tfunc_t pf, void *arg); +#endif +#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS + Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, + tfunc_t pf, void *arg); +#endif + tprio_t chThdSetPriority(tprio_t newprio); + Thread *chThdResume(Thread *tp); + void chThdTerminate(Thread *tp); + void chThdSleep(systime_t time); + void chThdSleepUntil(systime_t time); + void chThdYield(void); + void chThdExit(msg_t msg); +#if CH_USE_DYNAMIC + Thread *chThdAddRef(Thread *tp); + void chThdRelease(Thread *tp); +#endif +#if CH_USE_WAITEXIT + msg_t chThdWait(Thread *tp); +#endif +#ifdef __cplusplus +} +#endif + +/** + * @brief Returns a pointer to the current @p Thread. + */ +#define chThdSelf() currp + +/** + * @brief Returns the current thread priority. + */ +#define chThdGetPriority() (currp->p_prio) + +/** + * @brief Returns the pointer to the @p Thread local storage area, if any. + */ +#define chThdLS() (void *)(currp + 1) + +/** + * @brief Verifies if the specified thread is in the @p THD_STATE_FINAL state. + * + * @param[in] tp the pointer to the thread + * @retval TRUE thread terminated. + * @retval FALSE thread not terminated. + */ +#define chThdTerminated(tp) ((tp)->p_state == THD_STATE_FINAL) + +/** + * @brief Verifies if the current thread has a termination request pending. + * + * @retval TRUE termination request pended. + * @retval FALSE termination request not pended. + */ +#define chThdShouldTerminate() (currp->p_flags & THD_TERMINATE) + +/** + * @brief Resumes a thread created with @p chThdInit(). + * + * @param[in] tp the pointer to the thread + */ +#define chThdResumeI(tp) chSchReadyI(tp) + +/** + * @brief Suspends the invoking thread for the specified time. + * + * @param[in] time the delay in system ticks, the special values are + * handled as follow: + * - @a TIME_INFINITE the thread enters an infinite sleep + * state. + * - @a TIME_IMMEDIATE this value is accepted but + * interpreted as a normal time specification not as + * an immediate timeout specification. + * . + */ +#define chThdSleepS(time) chSchGoSleepTimeoutS(THD_STATE_SLEEPING, time) + +/** + * @brief Delays the invoking thread for the specified number of seconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] sec the time in seconds + */ +#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec)) + +/** + * @brief Delays the invoking thread for the specified number of + * milliseconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] msec the time in milliseconds + */ +#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec)) + +/** + * @brief Delays the invoking thread for the specified number of + * microseconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] usec the time in microseconds + */ +#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec)) + +#endif /* _THREADS_H_ */ + +/** @} */ diff --git a/os/kernel/include/vt.h b/os/kernel/include/vt.h index 23396e594..445650332 100644 --- a/os/kernel/include/vt.h +++ b/os/kernel/include/vt.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -55,7 +55,7 @@ typedef void (*vtfunc_t)(void *); /** - * @brief Virtual Timer structure type. + * @brief Virtual Timer structure type. */ typedef struct VirtualTimer VirtualTimer; @@ -94,7 +94,7 @@ typedef struct { extern VTList vtlist; /** - * @brief Virtual timers sticker. + * @brief Virtual timers sticker. */ #define chVTDoTickI() { \ vtlist.vt_systime++; \ diff --git a/os/kernel/kernel.dox b/os/kernel/kernel.dox index 072be41ec..e93ac8c5e 100644 --- a/os/kernel/kernel.dox +++ b/os/kernel/kernel.dox @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -353,4 +353,4 @@ * Internal details, not APIs. * @ingroup kernel */ - \ No newline at end of file + diff --git a/os/kernel/src/chcond.c b/os/kernel/src/chcond.c index 21f3a22e2..f0ec50c4f 100644 --- a/os/kernel/src/chcond.c +++ b/os/kernel/src/chcond.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chdebug.c b/os/kernel/src/chdebug.c index 38626387b..ebe93e8a5 100644 --- a/os/kernel/src/chdebug.c +++ b/os/kernel/src/chdebug.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -64,7 +64,7 @@ void chDbgTrace(Thread *otp, Thread *ntp) { * @brief Pointer to the panic message. * @details This pointer is meant to be accessed through the debugger, it is * written once and then the system is halted. This variable can be - * set to @p NULL if the halt is caused by a stack overflow. + * set to @p NULL if the halt is caused by a stack overflow. */ char *panic_msg; diff --git a/os/kernel/src/chevents.c b/os/kernel/src/chevents.c index 310f04212..e3c0b07ba 100644 --- a/os/kernel/src/chevents.c +++ b/os/kernel/src/chevents.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chheap.c b/os/kernel/src/chheap.c index 91b7d01bc..ce8ce385b 100644 --- a/os/kernel/src/chheap.c +++ b/os/kernel/src/chheap.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chlists.c b/os/kernel/src/chlists.c index 9b309ceea..f722f94cb 100644 --- a/os/kernel/src/chlists.c +++ b/os/kernel/src/chlists.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chmboxes.c b/os/kernel/src/chmboxes.c index aee514f84..3811fc5da 100644 --- a/os/kernel/src/chmboxes.c +++ b/os/kernel/src/chmboxes.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -33,7 +33,7 @@ * * @param[out] mbp the pointer to the Mailbox structure to be initialized * @param[in] buf the circular messages buffer - * @param[in] n the buffer size as number of @p msg_t + * @param[in] n the buffer size as number of @p msg_t */ void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) { diff --git a/os/kernel/src/chmemcore.c b/os/kernel/src/chmemcore.c index d5adbef48..435120a33 100644 --- a/os/kernel/src/chmemcore.c +++ b/os/kernel/src/chmemcore.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -60,7 +60,7 @@ void core_init(void) { * * @param[in] size the size of the block to be allocated * @return A pointer to the allocated memory block. - * @retval NULL allocation failed, core memory exhausted. + * @retval NULL allocation failed, core memory exhausted. */ void *chCoreAlloc(size_t size) { void *p; @@ -95,7 +95,7 @@ void *chCoreAllocI(size_t size) { /** * @brief Core memory left. * - * @return The size, in bytes, of the free core memory. + * @return The size, in bytes, of the free core memory. */ size_t chCoreFree(void) { diff --git a/os/kernel/src/chmempools.c b/os/kernel/src/chmempools.c index 1e827c128..f79e20353 100644 --- a/os/kernel/src/chmempools.c +++ b/os/kernel/src/chmempools.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chmsg.c b/os/kernel/src/chmsg.c index 9b6afd950..411c5fed3 100644 --- a/os/kernel/src/chmsg.c +++ b/os/kernel/src/chmsg.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chmtx.c b/os/kernel/src/chmtx.c index d5335c0aa..336df8a6e 100644 --- a/os/kernel/src/chmtx.c +++ b/os/kernel/src/chmtx.c @@ -1,276 +1,276 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chmtx.c - * @brief Mutexes code. - * - * @addtogroup mutexes - * @{ - */ - -#include "ch.h" - -#if CH_USE_MUTEXES - -/** - * @brief Initializes s @p Mutex structure. - * - * @param[out] mp pointer to a @p Mutex structure - */ -void chMtxInit(Mutex *mp) { - - chDbgCheck(mp != NULL, "chMtxInit"); - - queue_init(&mp->m_queue); - mp->m_owner = NULL; -} - -/** - * @brief Locks the specified mutex. - * - * @param[in] mp pointer to the @p Mutex structure - */ -void chMtxLock(Mutex *mp) { - - chSysLock(); - - chMtxLockS(mp); - - chSysUnlock(); -} - -/** - * @brief Locks the specified mutex. - * - * @param[in] mp pointer to the @p Mutex structure - */ -void chMtxLockS(Mutex *mp) { - Thread *ctp = currp; - - chDbgCheck(mp != NULL, "chMtxLockS"); - - /* Ia the mutex already locked? */ - if (mp->m_owner != NULL) { - /* Priority inheritance protocol; explores the thread-mutex dependencies - boosting the priority of all the affected threads to equal the priority - of the running thread requesting the mutex.*/ - Thread *tp = mp->m_owner; - /* Does the running thread have higher priority than the mutex - ownning thread? */ - while (tp->p_prio < ctp->p_prio) { - /* Make priority of thread tp match the running thread's priority.*/ - tp->p_prio = ctp->p_prio; - /* The following states need priority queues reordering.*/ - switch (tp->p_state) { - case THD_STATE_WTMTX: - /* Re-enqueues the mutex owner with its new priority.*/ - prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp); - tp = ((Mutex *)tp->p_u.wtobjp)->m_owner; - continue; -#if CH_USE_CONDVARS | CH_USE_SEMAPHORES_PRIORITY | CH_USE_MESSAGES_PRIORITY -#if CH_USE_CONDVARS - case THD_STATE_WTCOND: -#endif -#if CH_USE_SEMAPHORES_PRIORITY - case THD_STATE_WTSEM: -#endif -#if CH_USE_MESSAGES_PRIORITY - case THD_STATE_SNDMSG: -#endif - /* Re-enqueues tp with its new priority on the queue.*/ - prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp); - break; -#endif - case THD_STATE_READY: - /* Re-enqueues tp with its new priority on the ready list.*/ - chSchReadyI(dequeue(tp)); - } - break; - } - /* Sleep on the mutex.*/ - prio_insert(ctp, &mp->m_queue); - ctp->p_u.wtobjp = mp; - chSchGoSleepS(THD_STATE_WTMTX); - chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned"); - } - /* The mutex is now inserted in the owned mutexes list.*/ - mp->m_owner = ctp; - mp->m_next = ctp->p_mtxlist; - ctp->p_mtxlist = mp; -} - -/** - * @brief Tries to lock a mutex. - * @details This function does not have any overhead related to - * the priority inheritance mechanism because it does not try to - * enter a sleep state on the mutex. - * - * @param[in] mp pointer to the @p Mutex structure - * @retval TRUE if the mutex was successfully acquired - * @retval FALSE if the lock attempt failed. - */ -bool_t chMtxTryLock(Mutex *mp) { - bool_t b; - - chSysLock(); - - b = chMtxTryLockS(mp); - - chSysUnlock(); - return b; -} - -/** - * @brief Tries to lock a mutex. - * @details This function does not have any overhead related to - * the priority inheritance mechanism because it does not try to - * enter a sleep state on the mutex. - * - * @param[in] mp pointer to the @p Mutex structure - * @retval TRUE if the mutex was successfully acquired - * @retval FALSE if the lock attempt failed. - */ -bool_t chMtxTryLockS(Mutex *mp) { - - chDbgCheck(mp != NULL, "chMtxTryLockS"); - - if (mp->m_owner != NULL) - return FALSE; - mp->m_owner = currp; - mp->m_next = currp->p_mtxlist; - currp->p_mtxlist = mp; - return TRUE; -} - -/** - * @brief Unlocks the next owned mutex in reverse lock order. - * - * @return The pointer to the unlocked mutex. - */ -Mutex *chMtxUnlock(void) { - Thread *ctp = currp; - Mutex *ump, *mp; - - chSysLock(); - chDbgAssert(ctp->p_mtxlist != NULL, - "chMtxUnlock(), #1", - "owned mutexes list empty"); - chDbgAssert(ctp->p_mtxlist->m_owner == ctp, - "chMtxUnlock(), #2", - "ownership failure"); - /* Removes the top Mutex from the Threads's owned mutexes list and matk it - as not owned.*/ - ump = ctp->p_mtxlist; - ctp->p_mtxlist = ump->m_next; - ump->m_owner = NULL; - /* If a thread is waiting on the mutex then the fun part begins.*/ - if (chMtxQueueNotEmptyS(ump)) { - /* Recalculates the optimal thread priority by scanning the owned - mutexes list.*/ - tprio_t newprio = ctp->p_realprio; - mp = ctp->p_mtxlist; - while (mp != NULL) { - /* If the highest priority thread waiting in the mutexes list has a - greater priority than the current thread base priority then the final - priority will have at least that priority.*/ - if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) - newprio = mp->m_queue.p_next->p_prio; - mp = mp->m_next; - } - /* Assigns to the current thread the highest priority among all the - waiting threads.*/ - ctp->p_prio = newprio; - /* Awakens the highest priority thread waiting for the unlocked mutex.*/ - chSchWakeupS(fifo_remove(&ump->m_queue), RDY_OK); - } - chSysUnlock(); - return ump; -} - -/** - * @brief Unlocks the next owned mutex in reverse lock order. - * @note This function does not reschedule internally. - * - * @return The pointer to the unlocked mutex. - */ -Mutex *chMtxUnlockS(void) { - Thread *ctp = currp; - Mutex *ump, *mp; - - chDbgAssert(ctp->p_mtxlist != NULL, - "chMtxUnlockS(), #1", - "owned mutexes list empty"); - chDbgAssert(ctp->p_mtxlist->m_owner == ctp, - "chMtxUnlockS(), #2", - "ownership failure"); - - /* Removes the top Mutex from the owned mutexes list and marks it as not - owned.*/ - ump = ctp->p_mtxlist; - ctp->p_mtxlist = ump->m_next; - ump->m_owner = NULL; - /* If a thread is waiting on the mutex then the fun part begins.*/ - if (chMtxQueueNotEmptyS(ump)) { - /* Recalculates the optimal thread priority by scanning the owned - mutexes list.*/ - tprio_t newprio = ctp->p_realprio; - mp = ctp->p_mtxlist; - while (mp != NULL) { - /* If the highest priority thread waiting in the mutexes list has a - greater priority than the current thread base priority then the final - priority will have at least that priority.*/ - if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) - newprio = mp->m_queue.p_next->p_prio; - mp = mp->m_next; - } - ctp->p_prio = newprio; - chSchReadyI(fifo_remove(&ump->m_queue)); - } - return ump; -} - -/** - * @brief Unlocks all the mutexes owned by the invoking thread. - * @details This function is MUCH MORE efficient than releasing the - * mutexes one by one and not just because the call overhead, - * this function does not have any overhead related to the priority - * inheritance mechanism. - */ -void chMtxUnlockAll(void) { - Thread *ctp = currp; - - chSysLock(); - if (ctp->p_mtxlist != NULL) { - do { - Mutex *mp = ctp->p_mtxlist; - ctp->p_mtxlist = mp->m_next; - mp->m_owner = NULL; - if (chMtxQueueNotEmptyS(mp)) - chSchReadyI(fifo_remove(&mp->m_queue)); - } while (ctp->p_mtxlist != NULL); - ctp->p_prio = ctp->p_realprio; - chSchRescheduleS(); - } - chSysUnlock(); -} - -#endif /* CH_USE_MUTEXES */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmtx.c + * @brief Mutexes code. + * + * @addtogroup mutexes + * @{ + */ + +#include "ch.h" + +#if CH_USE_MUTEXES + +/** + * @brief Initializes s @p Mutex structure. + * + * @param[out] mp pointer to a @p Mutex structure + */ +void chMtxInit(Mutex *mp) { + + chDbgCheck(mp != NULL, "chMtxInit"); + + queue_init(&mp->m_queue); + mp->m_owner = NULL; +} + +/** + * @brief Locks the specified mutex. + * + * @param[in] mp pointer to the @p Mutex structure + */ +void chMtxLock(Mutex *mp) { + + chSysLock(); + + chMtxLockS(mp); + + chSysUnlock(); +} + +/** + * @brief Locks the specified mutex. + * + * @param[in] mp pointer to the @p Mutex structure + */ +void chMtxLockS(Mutex *mp) { + Thread *ctp = currp; + + chDbgCheck(mp != NULL, "chMtxLockS"); + + /* Ia the mutex already locked? */ + if (mp->m_owner != NULL) { + /* Priority inheritance protocol; explores the thread-mutex dependencies + boosting the priority of all the affected threads to equal the priority + of the running thread requesting the mutex.*/ + Thread *tp = mp->m_owner; + /* Does the running thread have higher priority than the mutex + ownning thread? */ + while (tp->p_prio < ctp->p_prio) { + /* Make priority of thread tp match the running thread's priority.*/ + tp->p_prio = ctp->p_prio; + /* The following states need priority queues reordering.*/ + switch (tp->p_state) { + case THD_STATE_WTMTX: + /* Re-enqueues the mutex owner with its new priority.*/ + prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp); + tp = ((Mutex *)tp->p_u.wtobjp)->m_owner; + continue; +#if CH_USE_CONDVARS | CH_USE_SEMAPHORES_PRIORITY | CH_USE_MESSAGES_PRIORITY +#if CH_USE_CONDVARS + case THD_STATE_WTCOND: +#endif +#if CH_USE_SEMAPHORES_PRIORITY + case THD_STATE_WTSEM: +#endif +#if CH_USE_MESSAGES_PRIORITY + case THD_STATE_SNDMSG: +#endif + /* Re-enqueues tp with its new priority on the queue.*/ + prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp); + break; +#endif + case THD_STATE_READY: + /* Re-enqueues tp with its new priority on the ready list.*/ + chSchReadyI(dequeue(tp)); + } + break; + } + /* Sleep on the mutex.*/ + prio_insert(ctp, &mp->m_queue); + ctp->p_u.wtobjp = mp; + chSchGoSleepS(THD_STATE_WTMTX); + chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned"); + } + /* The mutex is now inserted in the owned mutexes list.*/ + mp->m_owner = ctp; + mp->m_next = ctp->p_mtxlist; + ctp->p_mtxlist = mp; +} + +/** + * @brief Tries to lock a mutex. + * @details This function does not have any overhead related to + * the priority inheritance mechanism because it does not try to + * enter a sleep state on the mutex. + * + * @param[in] mp pointer to the @p Mutex structure + * @retval TRUE if the mutex was successfully acquired + * @retval FALSE if the lock attempt failed. + */ +bool_t chMtxTryLock(Mutex *mp) { + bool_t b; + + chSysLock(); + + b = chMtxTryLockS(mp); + + chSysUnlock(); + return b; +} + +/** + * @brief Tries to lock a mutex. + * @details This function does not have any overhead related to + * the priority inheritance mechanism because it does not try to + * enter a sleep state on the mutex. + * + * @param[in] mp pointer to the @p Mutex structure + * @retval TRUE if the mutex was successfully acquired + * @retval FALSE if the lock attempt failed. + */ +bool_t chMtxTryLockS(Mutex *mp) { + + chDbgCheck(mp != NULL, "chMtxTryLockS"); + + if (mp->m_owner != NULL) + return FALSE; + mp->m_owner = currp; + mp->m_next = currp->p_mtxlist; + currp->p_mtxlist = mp; + return TRUE; +} + +/** + * @brief Unlocks the next owned mutex in reverse lock order. + * + * @return The pointer to the unlocked mutex. + */ +Mutex *chMtxUnlock(void) { + Thread *ctp = currp; + Mutex *ump, *mp; + + chSysLock(); + chDbgAssert(ctp->p_mtxlist != NULL, + "chMtxUnlock(), #1", + "owned mutexes list empty"); + chDbgAssert(ctp->p_mtxlist->m_owner == ctp, + "chMtxUnlock(), #2", + "ownership failure"); + /* Removes the top Mutex from the Threads's owned mutexes list and matk it + as not owned.*/ + ump = ctp->p_mtxlist; + ctp->p_mtxlist = ump->m_next; + ump->m_owner = NULL; + /* If a thread is waiting on the mutex then the fun part begins.*/ + if (chMtxQueueNotEmptyS(ump)) { + /* Recalculates the optimal thread priority by scanning the owned + mutexes list.*/ + tprio_t newprio = ctp->p_realprio; + mp = ctp->p_mtxlist; + while (mp != NULL) { + /* If the highest priority thread waiting in the mutexes list has a + greater priority than the current thread base priority then the final + priority will have at least that priority.*/ + if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) + newprio = mp->m_queue.p_next->p_prio; + mp = mp->m_next; + } + /* Assigns to the current thread the highest priority among all the + waiting threads.*/ + ctp->p_prio = newprio; + /* Awakens the highest priority thread waiting for the unlocked mutex.*/ + chSchWakeupS(fifo_remove(&ump->m_queue), RDY_OK); + } + chSysUnlock(); + return ump; +} + +/** + * @brief Unlocks the next owned mutex in reverse lock order. + * @note This function does not reschedule internally. + * + * @return The pointer to the unlocked mutex. + */ +Mutex *chMtxUnlockS(void) { + Thread *ctp = currp; + Mutex *ump, *mp; + + chDbgAssert(ctp->p_mtxlist != NULL, + "chMtxUnlockS(), #1", + "owned mutexes list empty"); + chDbgAssert(ctp->p_mtxlist->m_owner == ctp, + "chMtxUnlockS(), #2", + "ownership failure"); + + /* Removes the top Mutex from the owned mutexes list and marks it as not + owned.*/ + ump = ctp->p_mtxlist; + ctp->p_mtxlist = ump->m_next; + ump->m_owner = NULL; + /* If a thread is waiting on the mutex then the fun part begins.*/ + if (chMtxQueueNotEmptyS(ump)) { + /* Recalculates the optimal thread priority by scanning the owned + mutexes list.*/ + tprio_t newprio = ctp->p_realprio; + mp = ctp->p_mtxlist; + while (mp != NULL) { + /* If the highest priority thread waiting in the mutexes list has a + greater priority than the current thread base priority then the final + priority will have at least that priority.*/ + if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) + newprio = mp->m_queue.p_next->p_prio; + mp = mp->m_next; + } + ctp->p_prio = newprio; + chSchReadyI(fifo_remove(&ump->m_queue)); + } + return ump; +} + +/** + * @brief Unlocks all the mutexes owned by the invoking thread. + * @details This function is MUCH MORE efficient than releasing the + * mutexes one by one and not just because the call overhead, + * this function does not have any overhead related to the priority + * inheritance mechanism. + */ +void chMtxUnlockAll(void) { + Thread *ctp = currp; + + chSysLock(); + if (ctp->p_mtxlist != NULL) { + do { + Mutex *mp = ctp->p_mtxlist; + ctp->p_mtxlist = mp->m_next; + mp->m_owner = NULL; + if (chMtxQueueNotEmptyS(mp)) + chSchReadyI(fifo_remove(&mp->m_queue)); + } while (ctp->p_mtxlist != NULL); + ctp->p_prio = ctp->p_realprio; + chSchRescheduleS(); + } + chSysUnlock(); +} + +#endif /* CH_USE_MUTEXES */ + +/** @} */ diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index 50f1f2401..2f8d1b569 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chregistry.c b/os/kernel/src/chregistry.c index b6555df40..8d4ffa4e8 100644 --- a/os/kernel/src/chregistry.c +++ b/os/kernel/src/chregistry.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -37,7 +37,7 @@ * @note This function cannot return @p NULL because there is always at * least one thread in the system. * - * @return A reference to the first thread. + * @return A reference to the first thread. */ Thread *chRegFirstThread(void) { Thread *tp; @@ -55,7 +55,7 @@ Thread *chRegFirstThread(void) { * @brief Returns the thread next to the specified one. * @details The reference counter of the specified thread is decremented and * the reference counter of the returned thread is incremented. - * + * * @param[in] tp pointer to the thread * @return A reference to the next thread. * @retval NULL if there is no next thread. diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index 5bd016226..8cfd5cd81 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -1,280 +1,280 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chschd.c - * @brief Scheduler code. - * - * @addtogroup scheduler - * @{ - */ - -#include "ch.h" - -/** - * @brief Ready list header. - */ -ReadyList rlist; - -/** - * @brief Scheduler initialization. - * @note Internally invoked by the @p chSysInit(), not an API. - */ -void scheduler_init(void) { - - queue_init(&rlist.r_queue); - rlist.r_prio = NOPRIO; -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif -#if CH_USE_REGISTRY - rlist.p_newer = rlist.p_older = (Thread *)&rlist; -#endif -} - -/** - * @brief Inserts a thread in the Ready List. - * @note The function does not reschedule, the @p chSchRescheduleS() should - * be called soon after. - * - * @param[in] tp the Thread to be made ready - * @return The Thread pointer. - */ -#if CH_OPTIMIZE_SPEED -/* NOTE: it is inlined in this module only.*/ -INLINE Thread *chSchReadyI(Thread *tp) { -#else -Thread *chSchReadyI(Thread *tp) { -#endif - Thread *cp; - - tp->p_state = THD_STATE_READY; - cp = (Thread *)&rlist.r_queue; - do { - cp = cp->p_next; - } while (cp->p_prio >= tp->p_prio); - /* Insertion on p_prev.*/ - tp->p_prev = (tp->p_next = cp)->p_prev; - tp->p_prev->p_next = cp->p_prev = tp; - return tp; -} - -/** - * @brief Puts the current thread to sleep into the specified state. - * @details The thread goes into a sleeping state. The @ref thread_states are - * described into @p threads.h. - * - * @param[in] newstate the new thread state - */ -void chSchGoSleepS(tstate_t newstate) { - Thread *otp; - - (otp = currp)->p_state = newstate; - (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif - chDbgTrace(otp, currp); - chSysSwitchI(otp, currp); -} - -/* - * Timeout wakeup callback. - */ -static void wakeup(void *p) { - Thread *tp = (Thread *)p; - -#if CH_USE_SEMAPHORES || CH_USE_MUTEXES || CH_USE_CONDVARS - switch (tp->p_state) { -#if CH_USE_SEMAPHORES - case THD_STATE_WTSEM: - chSemFastSignalI((Semaphore *)tp->p_u.wtobjp); - /* Falls into, intentional. */ -#endif -#if CH_USE_MUTEXES - case THD_STATE_WTMTX: -#endif -#if CH_USE_CONDVARS - case THD_STATE_WTCOND: -#endif - /* States requiring dequeuing.*/ - dequeue(tp); - } -#endif - chSchReadyI(tp)->p_u.rdymsg = RDY_TIMEOUT; -} - -/** - * @brief Puts the current thread to sleep into the specified state with - * timeout specification. - * @details The thread goes into a sleeping state, if it is not awakened - * explicitly within the specified timeout then it is forcibly - * awakened with a @p RDY_TIMEOUT low level message. The @ref - * thread_states are described into @p threads.h. - * - * @param[in] newstate the new thread state - * @param[in] time the number of ticks before the operation timeouts, the - * special values are handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state, this is equivalent to invoking - * @p chSchGoSleepS() but, of course, less efficient. - * - @a TIME_IMMEDIATE this value is accepted but - * interpreted as a normal time specification not as an - * immediate timeout specification. - * . - * @return The wakeup message. - * @retval RDY_TIMEOUT if a timeout occurs. - */ -msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { - - if (TIME_INFINITE != time) { - VirtualTimer vt; - - chVTSetI(&vt, time, wakeup, currp); - chSchGoSleepS(newstate); - if (chVTIsArmedI(&vt)) - chVTResetI(&vt); - } - else - chSchGoSleepS(newstate); - return currp->p_u.rdymsg; -} - -/** - * @brief Wakes up a thread. - * @details The thread is inserted into the ready list or immediately made - * running depending on its relative priority compared to the current - * thread. - * @note It is equivalent to a @p chSchReadyI() followed by a - * @p chSchRescheduleS() but much more efficient. - * @note The function assumes that the current thread has the highest - * priority. - * - * @param[in] ntp the Thread to be made ready - * @param[in] msg message to the awakened thread - */ -void chSchWakeupS(Thread *ntp, msg_t msg) { - - ntp->p_u.rdymsg = msg; - /* If the waken thread has a not-greater priority than the current - one then it is just inserted in the ready list else it made - running immediately and the invoking thread goes in the ready - list instead.*/ - if (ntp->p_prio <= currp->p_prio) - chSchReadyI(ntp); - else { - Thread *otp = currp; - chSchReadyI(otp); -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif - (currp = ntp)->p_state = THD_STATE_CURRENT; - chDbgTrace(otp, ntp); - chSysSwitchI(otp, ntp); - } -} - -/** - * @brief Switches to the first thread on the runnable queue. - * @note It is intended to be called if @p chSchRescRequiredI() evaluates - * to @p TRUE. - */ -void chSchDoRescheduleI(void) { - - Thread *otp = currp; - /* Pick the first thread from the ready queue and makes it current.*/ - (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; - chSchReadyI(otp); -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif - chDbgTrace(otp, currp); - chSysSwitchI(otp, currp); -} - -/** - * @brief Performs a reschedulation if a higher priority thread is runnable. - * @details If a thread with a higher priority than the current thread is in - * the ready list then make the higher priority thread running. - */ -void chSchRescheduleS(void) { - - if (chSchIsRescRequiredI()) - chSchDoRescheduleI(); -} - -/** - * @brief Evaluates if a reschedulation is required. - * @details The decision is taken by comparing the relative priorities and - * depending on the state of the round robin timeout counter. - * @note This function is meant to be used in the timer interrupt handler - * where @p chVTDoTickI() is invoked. - * - * @retval TRUE if there is a thread that should go in running state. - * @retval FALSE if a reschedulation is not required. - */ -bool_t chSchIsRescRequiredExI(void) { - tprio_t p1 = firstprio(&rlist.r_queue); - tprio_t p2 = currp->p_prio; -#if CH_TIME_QUANTUM > 0 - /* If the running thread has not reached its time quantum, reschedule only - if the first thread on the ready queue has a higher priority. - Otherwise, if the running thread has used up its time quantum, reschedule - if the first thread on the ready queue has equal or higher priority.*/ - return rlist.r_preempt ? p1 > p2 : p1 >= p2; -#else - /* If the round robin preemption feature is not enabled then performs a - simpler comparison.*/ - return p1 > p2; -#endif -} - -/** - * @brief Yields the time slot. - * @details Yields the CPU control to the next thread in the ready list with - * equal priority, if any. - */ -void chSchDoYieldS(void) { - - if (chSchCanYieldS()) { - Thread *cp = (Thread *)&rlist.r_queue; - Thread *otp = currp; - - /* Note, the following insertion code works because we know that on the - ready list there is at least one thread with priority equal or higher - than the current one.*/ - otp->p_state = THD_STATE_READY; - do { - cp = cp->p_prev; - } while (cp->p_prio < otp->p_prio); - /* Insertion on p_next.*/ - otp->p_next = (otp->p_prev = cp)->p_next; - otp->p_next->p_prev = cp->p_next = otp; - - /* Pick the first thread from the ready queue and makes it current.*/ - (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif - chDbgTrace(otp, currp); - chSysSwitchI(otp, currp); - } -} - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chschd.c + * @brief Scheduler code. + * + * @addtogroup scheduler + * @{ + */ + +#include "ch.h" + +/** + * @brief Ready list header. + */ +ReadyList rlist; + +/** + * @brief Scheduler initialization. + * @note Internally invoked by the @p chSysInit(), not an API. + */ +void scheduler_init(void) { + + queue_init(&rlist.r_queue); + rlist.r_prio = NOPRIO; +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif +#if CH_USE_REGISTRY + rlist.p_newer = rlist.p_older = (Thread *)&rlist; +#endif +} + +/** + * @brief Inserts a thread in the Ready List. + * @note The function does not reschedule, the @p chSchRescheduleS() should + * be called soon after. + * + * @param[in] tp the Thread to be made ready + * @return The Thread pointer. + */ +#if CH_OPTIMIZE_SPEED +/* NOTE: it is inlined in this module only.*/ +INLINE Thread *chSchReadyI(Thread *tp) { +#else +Thread *chSchReadyI(Thread *tp) { +#endif + Thread *cp; + + tp->p_state = THD_STATE_READY; + cp = (Thread *)&rlist.r_queue; + do { + cp = cp->p_next; + } while (cp->p_prio >= tp->p_prio); + /* Insertion on p_prev.*/ + tp->p_prev = (tp->p_next = cp)->p_prev; + tp->p_prev->p_next = cp->p_prev = tp; + return tp; +} + +/** + * @brief Puts the current thread to sleep into the specified state. + * @details The thread goes into a sleeping state. The @ref thread_states are + * described into @p threads.h. + * + * @param[in] newstate the new thread state + */ +void chSchGoSleepS(tstate_t newstate) { + Thread *otp; + + (otp = currp)->p_state = newstate; + (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif + chDbgTrace(otp, currp); + chSysSwitchI(otp, currp); +} + +/* + * Timeout wakeup callback. + */ +static void wakeup(void *p) { + Thread *tp = (Thread *)p; + +#if CH_USE_SEMAPHORES || CH_USE_MUTEXES || CH_USE_CONDVARS + switch (tp->p_state) { +#if CH_USE_SEMAPHORES + case THD_STATE_WTSEM: + chSemFastSignalI((Semaphore *)tp->p_u.wtobjp); + /* Falls into, intentional. */ +#endif +#if CH_USE_MUTEXES + case THD_STATE_WTMTX: +#endif +#if CH_USE_CONDVARS + case THD_STATE_WTCOND: +#endif + /* States requiring dequeuing.*/ + dequeue(tp); + } +#endif + chSchReadyI(tp)->p_u.rdymsg = RDY_TIMEOUT; +} + +/** + * @brief Puts the current thread to sleep into the specified state with + * timeout specification. + * @details The thread goes into a sleeping state, if it is not awakened + * explicitly within the specified timeout then it is forcibly + * awakened with a @p RDY_TIMEOUT low level message. The @ref + * thread_states are described into @p threads.h. + * + * @param[in] newstate the new thread state + * @param[in] time the number of ticks before the operation timeouts, the + * special values are handled as follow: + * - @a TIME_INFINITE the thread enters an infinite sleep + * state, this is equivalent to invoking + * @p chSchGoSleepS() but, of course, less efficient. + * - @a TIME_IMMEDIATE this value is accepted but + * interpreted as a normal time specification not as an + * immediate timeout specification. + * . + * @return The wakeup message. + * @retval RDY_TIMEOUT if a timeout occurs. + */ +msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { + + if (TIME_INFINITE != time) { + VirtualTimer vt; + + chVTSetI(&vt, time, wakeup, currp); + chSchGoSleepS(newstate); + if (chVTIsArmedI(&vt)) + chVTResetI(&vt); + } + else + chSchGoSleepS(newstate); + return currp->p_u.rdymsg; +} + +/** + * @brief Wakes up a thread. + * @details The thread is inserted into the ready list or immediately made + * running depending on its relative priority compared to the current + * thread. + * @note It is equivalent to a @p chSchReadyI() followed by a + * @p chSchRescheduleS() but much more efficient. + * @note The function assumes that the current thread has the highest + * priority. + * + * @param[in] ntp the Thread to be made ready + * @param[in] msg message to the awakened thread + */ +void chSchWakeupS(Thread *ntp, msg_t msg) { + + ntp->p_u.rdymsg = msg; + /* If the waken thread has a not-greater priority than the current + one then it is just inserted in the ready list else it made + running immediately and the invoking thread goes in the ready + list instead.*/ + if (ntp->p_prio <= currp->p_prio) + chSchReadyI(ntp); + else { + Thread *otp = currp; + chSchReadyI(otp); +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif + (currp = ntp)->p_state = THD_STATE_CURRENT; + chDbgTrace(otp, ntp); + chSysSwitchI(otp, ntp); + } +} + +/** + * @brief Switches to the first thread on the runnable queue. + * @note It is intended to be called if @p chSchRescRequiredI() evaluates + * to @p TRUE. + */ +void chSchDoRescheduleI(void) { + + Thread *otp = currp; + /* Pick the first thread from the ready queue and makes it current.*/ + (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; + chSchReadyI(otp); +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif + chDbgTrace(otp, currp); + chSysSwitchI(otp, currp); +} + +/** + * @brief Performs a reschedulation if a higher priority thread is runnable. + * @details If a thread with a higher priority than the current thread is in + * the ready list then make the higher priority thread running. + */ +void chSchRescheduleS(void) { + + if (chSchIsRescRequiredI()) + chSchDoRescheduleI(); +} + +/** + * @brief Evaluates if a reschedulation is required. + * @details The decision is taken by comparing the relative priorities and + * depending on the state of the round robin timeout counter. + * @note This function is meant to be used in the timer interrupt handler + * where @p chVTDoTickI() is invoked. + * + * @retval TRUE if there is a thread that should go in running state. + * @retval FALSE if a reschedulation is not required. + */ +bool_t chSchIsRescRequiredExI(void) { + tprio_t p1 = firstprio(&rlist.r_queue); + tprio_t p2 = currp->p_prio; +#if CH_TIME_QUANTUM > 0 + /* If the running thread has not reached its time quantum, reschedule only + if the first thread on the ready queue has a higher priority. + Otherwise, if the running thread has used up its time quantum, reschedule + if the first thread on the ready queue has equal or higher priority.*/ + return rlist.r_preempt ? p1 > p2 : p1 >= p2; +#else + /* If the round robin preemption feature is not enabled then performs a + simpler comparison.*/ + return p1 > p2; +#endif +} + +/** + * @brief Yields the time slot. + * @details Yields the CPU control to the next thread in the ready list with + * equal priority, if any. + */ +void chSchDoYieldS(void) { + + if (chSchCanYieldS()) { + Thread *cp = (Thread *)&rlist.r_queue; + Thread *otp = currp; + + /* Note, the following insertion code works because we know that on the + ready list there is at least one thread with priority equal or higher + than the current one.*/ + otp->p_state = THD_STATE_READY; + do { + cp = cp->p_prev; + } while (cp->p_prio < otp->p_prio); + /* Insertion on p_next.*/ + otp->p_next = (otp->p_prev = cp)->p_next; + otp->p_next->p_prev = cp->p_next = otp; + + /* Pick the first thread from the ready queue and makes it current.*/ + (currp = fifo_remove(&rlist.r_queue))->p_state = THD_STATE_CURRENT; +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif + chDbgTrace(otp, currp); + chSysSwitchI(otp, currp); + } +} + +/** @} */ diff --git a/os/kernel/src/chsem.c b/os/kernel/src/chsem.c index b4ff0d9bc..7af52d8b6 100644 --- a/os/kernel/src/chsem.c +++ b/os/kernel/src/chsem.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. diff --git a/os/kernel/src/chsys.c b/os/kernel/src/chsys.c index 8c252609d..2003f690b 100644 --- a/os/kernel/src/chsys.c +++ b/os/kernel/src/chsys.c @@ -1,130 +1,130 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chsys.c - * @brief System related code. - * - * @addtogroup system - * @{ - */ - -#include "ch.h" - -static WORKING_AREA(idle_thread_wa, IDLE_THREAD_STACK_SIZE); - -/** - * @brief This function implements the idle thread infinite loop. - * @details The function puts the processor in the lowest power mode capable - * to serve interrupts.
- * The priority is internally set to the minimum system value so - * that this thread is executed only if there are no other ready - * threads in the system. - * - * @param[in] p the thread parameter, unused in this scenario - */ -static void idle_thread(void *p) { - - (void)p; - while (TRUE) { - port_wait_for_interrupt(); - IDLE_LOOP_HOOK(); - } -} - -/** - * @brief ChibiOS/RT initialization. - * @details After executing this function the current instructions stream - * becomes the main thread. - * @note Interrupts should be still disabled when @p chSysInit() is invoked - * and are internally enabled. - * @note The main thread is created with priority @p NORMALPRIO. - */ -void chSysInit(void) { - static Thread mainthread; - - port_init(); - scheduler_init(); - vt_init(); -#if CH_USE_MEMCORE - core_init(); -#endif -#if CH_USE_HEAP - heap_init(); -#endif -#if CH_DBG_ENABLE_TRACE - trace_init(); -#endif - - /* Now this instructions flow becomes the main thread.*/ - (currp = init_thread(&mainthread, NORMALPRIO))->p_state = THD_STATE_CURRENT; - chSysEnable(); - - /* This thread has the lowest priority in the system, its role is just to - serve interrupts in its context while keeping the lowest energy saving - mode compatible with the system status.*/ - chThdCreateStatic(idle_thread_wa, sizeof(idle_thread_wa), IDLEPRIO, - (tfunc_t)idle_thread, NULL); -} - -/** - * @brief Handles time ticks for round robin preemption and timer increments. - * @details Decrements the remaining time quantum of the running thread - * and preempts it when the quantum is used up. Increments system - * time and manages the timers. - * - * @note The frequency of the timer determines the system tick granularity - * and, together with the @p CH_TIME_QUANTUM macro, the round robin - * interval. - */ -void chSysTimerHandlerI(void) { - -#if CH_TIME_QUANTUM > 0 - /* Running thread has not used up quantum yet? */ - if (rlist.r_preempt > 0) - /* Decrement remaining quantum.*/ - rlist.r_preempt--; -#endif -#if CH_DBG_THREADS_PROFILING - currp->p_time++; -#endif - chVTDoTickI(); -} - -#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED -void chSysLock(void) { - - chDbgAssert(currp->p_locks >= 0, - "chSysLock(), #1", - "negative nesting counter"); - if (currp->p_locks++ == 0) - port_lock(); -} - -void chSysUnlock(void) { - - chDbgAssert(currp->p_locks > 0, - "chSysUnlock(), #1", - "non-positive nesting counter"); - if (--currp->p_locks == 0) - port_unlock(); -} -#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chsys.c + * @brief System related code. + * + * @addtogroup system + * @{ + */ + +#include "ch.h" + +static WORKING_AREA(idle_thread_wa, IDLE_THREAD_STACK_SIZE); + +/** + * @brief This function implements the idle thread infinite loop. + * @details The function puts the processor in the lowest power mode capable + * to serve interrupts.
+ * The priority is internally set to the minimum system value so + * that this thread is executed only if there are no other ready + * threads in the system. + * + * @param[in] p the thread parameter, unused in this scenario + */ +static void idle_thread(void *p) { + + (void)p; + while (TRUE) { + port_wait_for_interrupt(); + IDLE_LOOP_HOOK(); + } +} + +/** + * @brief ChibiOS/RT initialization. + * @details After executing this function the current instructions stream + * becomes the main thread. + * @note Interrupts should be still disabled when @p chSysInit() is invoked + * and are internally enabled. + * @note The main thread is created with priority @p NORMALPRIO. + */ +void chSysInit(void) { + static Thread mainthread; + + port_init(); + scheduler_init(); + vt_init(); +#if CH_USE_MEMCORE + core_init(); +#endif +#if CH_USE_HEAP + heap_init(); +#endif +#if CH_DBG_ENABLE_TRACE + trace_init(); +#endif + + /* Now this instructions flow becomes the main thread.*/ + (currp = init_thread(&mainthread, NORMALPRIO))->p_state = THD_STATE_CURRENT; + chSysEnable(); + + /* This thread has the lowest priority in the system, its role is just to + serve interrupts in its context while keeping the lowest energy saving + mode compatible with the system status.*/ + chThdCreateStatic(idle_thread_wa, sizeof(idle_thread_wa), IDLEPRIO, + (tfunc_t)idle_thread, NULL); +} + +/** + * @brief Handles time ticks for round robin preemption and timer increments. + * @details Decrements the remaining time quantum of the running thread + * and preempts it when the quantum is used up. Increments system + * time and manages the timers. + * + * @note The frequency of the timer determines the system tick granularity + * and, together with the @p CH_TIME_QUANTUM macro, the round robin + * interval. + */ +void chSysTimerHandlerI(void) { + +#if CH_TIME_QUANTUM > 0 + /* Running thread has not used up quantum yet? */ + if (rlist.r_preempt > 0) + /* Decrement remaining quantum.*/ + rlist.r_preempt--; +#endif +#if CH_DBG_THREADS_PROFILING + currp->p_time++; +#endif + chVTDoTickI(); +} + +#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED +void chSysLock(void) { + + chDbgAssert(currp->p_locks >= 0, + "chSysLock(), #1", + "negative nesting counter"); + if (currp->p_locks++ == 0) + port_lock(); +} + +void chSysUnlock(void) { + + chDbgAssert(currp->p_locks > 0, + "chSysUnlock(), #1", + "non-positive nesting counter"); + if (--currp->p_locks == 0) + port_unlock(); +} +#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */ + +/** @} */ diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c index 6f67f7093..79ea23f94 100644 --- a/os/kernel/src/chthreads.c +++ b/os/kernel/src/chthreads.c @@ -1,446 +1,446 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chthreads.c - * @brief Threads code. - * - * @addtogroup threads - * @{ - */ - -#include "ch.h" - -/** - * @brief Initializes a thread structure. - * - * @param[in] tp pointer to the thread - * @param[in] prio the priority level for the new thread - * @return The same thread pointer passed as parameter. - */ -Thread *init_thread(Thread *tp, tprio_t prio) { - - tp->p_flags = THD_MEM_MODE_STATIC; - tp->p_prio = prio; - tp->p_state = THD_STATE_SUSPENDED; -#if CH_USE_REGISTRY - REG_INSERT(tp); -#endif -#if CH_USE_DYNAMIC - tp->p_refs = 1; -#endif -#if CH_USE_NESTED_LOCKS - tp->p_locks = 0; -#endif -#if CH_DBG_THREADS_PROFILING - tp->p_time = 0; -#endif -#if CH_USE_MUTEXES - tp->p_realprio = prio; - tp->p_mtxlist = NULL; -#endif -#if CH_USE_WAITEXIT - list_init(&tp->p_waiting); -#endif -#if CH_USE_MESSAGES - queue_init(&tp->p_msgqueue); -#endif -#if CH_USE_EVENTS - tp->p_epending = 0; -#endif - THREAD_EXT_INIT(tp); - return tp; -} - -#if CH_DBG_FILL_THREADS -static void memfill(uint8_t *startp, uint8_t *endp, uint8_t v) { - - while (startp < endp) - *startp++ = v; -} -#endif - -/** - * @brief Initializes a new thread. - * @details The new thread is initialized but not inserted in the ready list, - * the initial state is @p THD_STATE_SUSPENDED. - * @note A thread can terminate by calling @p chThdExit() or by simply - * returning from its main function. - * @note This function can be invoked from within an interrupt handler - * even if it is not an I-Class API because it does not touch - * any critical kernel data structure. - * - * @param[out] wsp pointer to a working area dedicated to the thread stack - * @param[in] size size of the working area - * @param[in] prio the priority level for the new thread - * @param[in] pf the thread function - * @param[in] arg an argument passed to the thread function. It can be - * @p NULL. - * @return The pointer to the @p Thread structure allocated for - * the thread into the working space area. - */ -Thread *chThdInit(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) { - /* Thread structure is layed out in the lower part of the thread workspace */ - Thread *tp = wsp; - - chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) && - (prio <= HIGHPRIO) && (pf != NULL), - "chThdInit"); -#if CH_DBG_FILL_THREADS - memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE); - memfill((uint8_t *)wsp + sizeof(Thread), - (uint8_t *)wsp + size, STACK_FILL_VALUE); -#endif - SETUP_CONTEXT(wsp, size, pf, arg); - return init_thread(tp, prio); -} - -/** - * @brief Creates a new thread into a static memory area. - * @note A thread can terminate by calling @p chThdExit() or by simply - * returning from its main function. - * - * @param[out] wsp pointer to a working area dedicated to the thread stack - * @param[in] size size of the working area - * @param[in] prio the priority level for the new thread - * @param[in] pf the thread function - * @param[in] arg an argument passed to the thread function. It can be - * @p NULL. - * @return The pointer to the @p Thread structure allocated for - * the thread into the working space area. - */ -Thread *chThdCreateStatic(void *wsp, size_t size, - tprio_t prio, tfunc_t pf, void *arg) { - - return chThdResume(chThdInit(wsp, size, prio, pf, arg)); -} - -#if CH_USE_DYNAMIC && CH_USE_HEAP -/** - * @brief Creates a new thread allocating the memory from the heap. - * @note A thread can terminate by calling @p chThdExit() or by simply - * returning from its main function. - * @note The memory allocated for the thread is not released when the thread - * terminates but when a @p chThdWait() is performed. - * @note The function is available only if the @p CH_USE_DYNAMIC, - * @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled - * in @p chconf.h. - * - * @param[in] heapp heap from which allocate the memory or @p NULL for the - * default heap - * @param[in] size size of the working area to be allocated - * @param[in] prio the priority level for the new thread - * @param[in] pf the thread function - * @param[in] arg an argument passed to the thread function. It can be - * @p NULL. - * @return The pointer to the @p Thread structure allocated for - * the thread into the working space area. - * @retval NULL if the memory cannot be allocated. - */ -Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size, - tprio_t prio, tfunc_t pf, void *arg) { - void *wsp; - Thread *tp; - - wsp = chHeapAlloc(heapp, size); - if (wsp == NULL) - return NULL; - tp = chThdInit(wsp, size, prio, pf, arg); - tp->p_flags = THD_MEM_MODE_HEAP; - return chThdResume(tp); -} -#endif /* CH_USE_DYNAMIC && CH_USE_HEAP */ - -#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS -/** - * @brief Creates a new thread allocating the memory from the specified - * Memory Pool. - * @note A thread can terminate by calling @p chThdExit() or by simply - * returning from its main function. - * @note The memory allocated for the thread is not released when the thread - * terminates but when a @p chThdWait() is performed. - * @note The function is available only if the @p CH_USE_DYNAMIC, - * @p CH_USE_MEMPOOLS and @p CH_USE_WAITEXIT options are enabled - * in @p chconf.h. - * - * @param[in] mp pointer to the memory pool object - * @param[in] prio the priority level for the new thread - * @param[in] pf the thread function - * @param[in] arg an argument passed to the thread function. It can be - * @p NULL. - * @return The pointer to the @p Thread structure allocated for - * the thread into the working space area. - * @retval NULL if the memory pool is empty. - */ -Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, - tfunc_t pf, void *arg) { - void *wsp; - Thread *tp; - - chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool"); - - wsp = chPoolAlloc(mp); - if (wsp == NULL) - return NULL; - tp = chThdInit(wsp, mp->mp_object_size, prio, pf, arg); - tp->p_flags = THD_MEM_MODE_MEMPOOL; - tp->p_mpool = mp; - return chThdResume(tp); -} -#endif /* CH_USE_DYNAMIC && CH_USE_MEMPOOLS */ - -/** - * @brief Changes the running thread priority level then reschedules if - * necessary. - * @note The function returns the real thread priority regardless of the - * current priority that could be higher than the real priority - * because the priority inheritance mechanism. - * - * @param[in] newprio the new priority level of the running thread - * @return The old priority level. - */ -tprio_t chThdSetPriority(tprio_t newprio) { - tprio_t oldprio; - - chDbgCheck((newprio >= LOWPRIO) && (newprio <= HIGHPRIO), - "chThdSetPriority"); - - chSysLock(); -#if CH_USE_MUTEXES - oldprio = currp->p_realprio; - if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio)) - currp->p_prio = newprio; - currp->p_realprio = newprio; -#else - oldprio = currp->p_prio; - currp->p_prio = newprio; -#endif - chSchRescheduleS(); - chSysUnlock(); - return oldprio; -} - -/** - * @brief Resumes a suspended thread. - * @note Use this function to resume threads created with @p chThdInit(). - * - * @param[in] tp pointer to the thread - * @return The pointer to the thread. - */ -Thread *chThdResume(Thread *tp) { - - chSysLock(); - chDbgAssert(tp->p_state == THD_STATE_SUSPENDED, - "chThdResume(), #1", - "thread not in THD_STATE_SUSPENDED state"); - chSchWakeupS(tp, RDY_OK); - chSysUnlock(); - return tp; -} - -/** - * @brief Requests a thread termination. - * @note The thread is not terminated but a termination request is added to - * its @p p_flags field. The thread can read this status by - * invoking @p chThdShouldTerminate() and then terminate cleanly. - * - * @param[in] tp pointer to the thread - */ -void chThdTerminate(Thread *tp) { - - chSysLock(); - tp->p_flags |= THD_TERMINATE; - chSysUnlock(); -} - -/** - * @brief Suspends the invoking thread for the specified time. - * - * @param[in] time the delay in system ticks, the special values are - * handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state. - * - @a TIME_IMMEDIATE this value is accepted but - * interpreted as a normal time specification not as an - * immediate timeout specification. - * . - */ -void chThdSleep(systime_t time) { - - chDbgCheck(time != TIME_INFINITE, "chThdSleep"); - - chSysLock(); - chThdSleepS(time); - chSysUnlock(); -} - -/** - * @brief Suspends the invoking thread until the system time arrives to the - * specified value. - * - * @param[in] time absolute system time - */ -void chThdSleepUntil(systime_t time) { - - chSysLock(); - if ((time -= chTimeNow()) > 0) - chThdSleepS(time); - chSysUnlock(); -} - -/** - * @brief Yields the time slot. - * @details Yields the CPU control to the next thread in the ready list with - * equal priority, if any. - */ -void chThdYield(void) { - - chSysLock(); - chSchDoYieldS(); - chSysUnlock(); -} - -/** - * @brief Terminates the current thread by specifying an exit status code. - * - * @param[in] msg thread exit code. The code can be retrieved by using - * @p chThdWait(). - */ -void chThdExit(msg_t msg) { - Thread *tp = currp; - - chSysLock(); - tp->p_u.exitcode = msg; - THREAD_EXT_EXIT(tp); -#if CH_USE_WAITEXIT - while (notempty(&tp->p_waiting)) - chSchReadyI(list_remove(&tp->p_waiting)); -#endif -#if CH_USE_REGISTRY - REG_REMOVE(tp); -#endif - chSchGoSleepS(THD_STATE_FINAL); -} - -#if CH_USE_DYNAMIC || defined(__DOXYGEN__) -/** - * @brief Adds a reference to a thread object. - * - * @param[in] tp pointer to the thread - * @return The same thread pointer passed as parameter - * representing the new reference. - */ -Thread *chThdAddRef(Thread *tp) { - - chSysLock(); - chDbgAssert(tp->p_refs < 255, "chThdAddRef(), #1", "too many references"); - tp->p_refs++; - chSysUnlock(); - return tp; -} - -/** - * @brief Releases a reference to a thread object. - * @details If the references counter reaches zero and the thread - * is in the @p THD_STATE_FINAL state then the thread's memory is - * returned to the proper allocator. - * @note Static threads are not affected. - * - * @param[in] tp pointer to the thread - */ -void chThdRelease(Thread *tp) { - trefs_t refs; - - chSysLock(); - chDbgAssert(tp->p_refs > 0, "chThdRelease(), #1", "not referenced"); - refs = --tp->p_refs; - chSysUnlock(); - - /* If the references counter reaches zero then the memory can be returned - to the proper allocator. Of course static threads are not affected.*/ - if (refs == 0) { - switch (tp->p_flags & THD_MEM_MODE_MASK) { -#if CH_USE_HEAP - case THD_MEM_MODE_HEAP: - chHeapFree(tp); - break; -#endif -#if CH_USE_MEMPOOLS - case THD_MEM_MODE_MEMPOOL: - chPoolFree(tp->p_mpool, tp); - break; -#endif - } - } -} -#endif /* CH_USE_DYNAMIC */ - -#if CH_USE_WAITEXIT || defined(__DOXYGEN__) -/** - * @brief Blocks the execution of the invoking thread until the specified - * thread terminates then the exit code is returned. - * @details This function waits for the specified thread to terminate then - * decrements its reference counter, if the counter reaches zero then - * the thread working area is returned to the proper allocator.
- * The memory used by the exited thread is handled in different ways - * depending on the API that spawned the thread: - * - If the thread was spawned by @p chThdCreateStatic() or by - * @p chThdInit() then nothing happens and the thread working area - * is not released or modified in any way. This is the default, - * totally static, behavior. - * - If the thread was spawned by @p chThdCreateFromHeap() then - * the working area is returned to the system heap. - * - If the thread was spawned by @p chThdCreateFromMemoryPool() - * then the working area is returned to the owning memory pool. - * . - * Please read the @ref article_lifecycle article for more details. - * @note After invoking @p chThdWait() the thread pointer becomes invalid - * and must not be used as parameter for further system calls. - * @note The function is available only if the @p CH_USE_WAITEXIT - * option is enabled in @p chconf.h. - * @note If @p CH_USE_DYNAMIC is not specified this function just waits for - * the thread termination, no memory allocators are involved. - * - * @param[in] tp pointer to the thread - * @return The exit code from the terminated thread. - */ -msg_t chThdWait(Thread *tp) { - msg_t msg; - - chDbgCheck(tp != NULL, "chThdWait"); - - chSysLock(); - chDbgAssert(tp != currp, "chThdWait(), #1", "waiting self"); -#if CH_USE_DYNAMIC - chDbgAssert(tp->p_refs > 0, "chThdWait(), #2", "not referenced"); -#endif - if (tp->p_state != THD_STATE_FINAL) { - list_insert(currp, &tp->p_waiting); - chSchGoSleepS(THD_STATE_WTEXIT); - } - msg = tp->p_u.exitcode; - chSysUnlock(); -#if CH_USE_DYNAMIC - chThdRelease(tp); -#endif - return msg; -} -#endif /* CH_USE_WAITEXIT */ - -/** @} */ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chthreads.c + * @brief Threads code. + * + * @addtogroup threads + * @{ + */ + +#include "ch.h" + +/** + * @brief Initializes a thread structure. + * + * @param[in] tp pointer to the thread + * @param[in] prio the priority level for the new thread + * @return The same thread pointer passed as parameter. + */ +Thread *init_thread(Thread *tp, tprio_t prio) { + + tp->p_flags = THD_MEM_MODE_STATIC; + tp->p_prio = prio; + tp->p_state = THD_STATE_SUSPENDED; +#if CH_USE_REGISTRY + REG_INSERT(tp); +#endif +#if CH_USE_DYNAMIC + tp->p_refs = 1; +#endif +#if CH_USE_NESTED_LOCKS + tp->p_locks = 0; +#endif +#if CH_DBG_THREADS_PROFILING + tp->p_time = 0; +#endif +#if CH_USE_MUTEXES + tp->p_realprio = prio; + tp->p_mtxlist = NULL; +#endif +#if CH_USE_WAITEXIT + list_init(&tp->p_waiting); +#endif +#if CH_USE_MESSAGES + queue_init(&tp->p_msgqueue); +#endif +#if CH_USE_EVENTS + tp->p_epending = 0; +#endif + THREAD_EXT_INIT(tp); + return tp; +} + +#if CH_DBG_FILL_THREADS +static void memfill(uint8_t *startp, uint8_t *endp, uint8_t v) { + + while (startp < endp) + *startp++ = v; +} +#endif + +/** + * @brief Initializes a new thread. + * @details The new thread is initialized but not inserted in the ready list, + * the initial state is @p THD_STATE_SUSPENDED. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * @note This function can be invoked from within an interrupt handler + * even if it is not an I-Class API because it does not touch + * any critical kernel data structure. + * + * @param[out] wsp pointer to a working area dedicated to the thread stack + * @param[in] size size of the working area + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p Thread structure allocated for + * the thread into the working space area. + */ +Thread *chThdInit(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) { + /* Thread structure is layed out in the lower part of the thread workspace */ + Thread *tp = wsp; + + chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) && + (prio <= HIGHPRIO) && (pf != NULL), + "chThdInit"); +#if CH_DBG_FILL_THREADS + memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE); + memfill((uint8_t *)wsp + sizeof(Thread), + (uint8_t *)wsp + size, STACK_FILL_VALUE); +#endif + SETUP_CONTEXT(wsp, size, pf, arg); + return init_thread(tp, prio); +} + +/** + * @brief Creates a new thread into a static memory area. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * + * @param[out] wsp pointer to a working area dedicated to the thread stack + * @param[in] size size of the working area + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p Thread structure allocated for + * the thread into the working space area. + */ +Thread *chThdCreateStatic(void *wsp, size_t size, + tprio_t prio, tfunc_t pf, void *arg) { + + return chThdResume(chThdInit(wsp, size, prio, pf, arg)); +} + +#if CH_USE_DYNAMIC && CH_USE_HEAP +/** + * @brief Creates a new thread allocating the memory from the heap. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * @note The memory allocated for the thread is not released when the thread + * terminates but when a @p chThdWait() is performed. + * @note The function is available only if the @p CH_USE_DYNAMIC, + * @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled + * in @p chconf.h. + * + * @param[in] heapp heap from which allocate the memory or @p NULL for the + * default heap + * @param[in] size size of the working area to be allocated + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p Thread structure allocated for + * the thread into the working space area. + * @retval NULL if the memory cannot be allocated. + */ +Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size, + tprio_t prio, tfunc_t pf, void *arg) { + void *wsp; + Thread *tp; + + wsp = chHeapAlloc(heapp, size); + if (wsp == NULL) + return NULL; + tp = chThdInit(wsp, size, prio, pf, arg); + tp->p_flags = THD_MEM_MODE_HEAP; + return chThdResume(tp); +} +#endif /* CH_USE_DYNAMIC && CH_USE_HEAP */ + +#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS +/** + * @brief Creates a new thread allocating the memory from the specified + * Memory Pool. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * @note The memory allocated for the thread is not released when the thread + * terminates but when a @p chThdWait() is performed. + * @note The function is available only if the @p CH_USE_DYNAMIC, + * @p CH_USE_MEMPOOLS and @p CH_USE_WAITEXIT options are enabled + * in @p chconf.h. + * + * @param[in] mp pointer to the memory pool object + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p Thread structure allocated for + * the thread into the working space area. + * @retval NULL if the memory pool is empty. + */ +Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, + tfunc_t pf, void *arg) { + void *wsp; + Thread *tp; + + chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool"); + + wsp = chPoolAlloc(mp); + if (wsp == NULL) + return NULL; + tp = chThdInit(wsp, mp->mp_object_size, prio, pf, arg); + tp->p_flags = THD_MEM_MODE_MEMPOOL; + tp->p_mpool = mp; + return chThdResume(tp); +} +#endif /* CH_USE_DYNAMIC && CH_USE_MEMPOOLS */ + +/** + * @brief Changes the running thread priority level then reschedules if + * necessary. + * @note The function returns the real thread priority regardless of the + * current priority that could be higher than the real priority + * because the priority inheritance mechanism. + * + * @param[in] newprio the new priority level of the running thread + * @return The old priority level. + */ +tprio_t chThdSetPriority(tprio_t newprio) { + tprio_t oldprio; + + chDbgCheck((newprio >= LOWPRIO) && (newprio <= HIGHPRIO), + "chThdSetPriority"); + + chSysLock(); +#if CH_USE_MUTEXES + oldprio = currp->p_realprio; + if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio)) + currp->p_prio = newprio; + currp->p_realprio = newprio; +#else + oldprio = currp->p_prio; + currp->p_prio = newprio; +#endif + chSchRescheduleS(); + chSysUnlock(); + return oldprio; +} + +/** + * @brief Resumes a suspended thread. + * @note Use this function to resume threads created with @p chThdInit(). + * + * @param[in] tp pointer to the thread + * @return The pointer to the thread. + */ +Thread *chThdResume(Thread *tp) { + + chSysLock(); + chDbgAssert(tp->p_state == THD_STATE_SUSPENDED, + "chThdResume(), #1", + "thread not in THD_STATE_SUSPENDED state"); + chSchWakeupS(tp, RDY_OK); + chSysUnlock(); + return tp; +} + +/** + * @brief Requests a thread termination. + * @note The thread is not terminated but a termination request is added to + * its @p p_flags field. The thread can read this status by + * invoking @p chThdShouldTerminate() and then terminate cleanly. + * + * @param[in] tp pointer to the thread + */ +void chThdTerminate(Thread *tp) { + + chSysLock(); + tp->p_flags |= THD_TERMINATE; + chSysUnlock(); +} + +/** + * @brief Suspends the invoking thread for the specified time. + * + * @param[in] time the delay in system ticks, the special values are + * handled as follow: + * - @a TIME_INFINITE the thread enters an infinite sleep + * state. + * - @a TIME_IMMEDIATE this value is accepted but + * interpreted as a normal time specification not as an + * immediate timeout specification. + * . + */ +void chThdSleep(systime_t time) { + + chDbgCheck(time != TIME_INFINITE, "chThdSleep"); + + chSysLock(); + chThdSleepS(time); + chSysUnlock(); +} + +/** + * @brief Suspends the invoking thread until the system time arrives to the + * specified value. + * + * @param[in] time absolute system time + */ +void chThdSleepUntil(systime_t time) { + + chSysLock(); + if ((time -= chTimeNow()) > 0) + chThdSleepS(time); + chSysUnlock(); +} + +/** + * @brief Yields the time slot. + * @details Yields the CPU control to the next thread in the ready list with + * equal priority, if any. + */ +void chThdYield(void) { + + chSysLock(); + chSchDoYieldS(); + chSysUnlock(); +} + +/** + * @brief Terminates the current thread by specifying an exit status code. + * + * @param[in] msg thread exit code. The code can be retrieved by using + * @p chThdWait(). + */ +void chThdExit(msg_t msg) { + Thread *tp = currp; + + chSysLock(); + tp->p_u.exitcode = msg; + THREAD_EXT_EXIT(tp); +#if CH_USE_WAITEXIT + while (notempty(&tp->p_waiting)) + chSchReadyI(list_remove(&tp->p_waiting)); +#endif +#if CH_USE_REGISTRY + REG_REMOVE(tp); +#endif + chSchGoSleepS(THD_STATE_FINAL); +} + +#if CH_USE_DYNAMIC || defined(__DOXYGEN__) +/** + * @brief Adds a reference to a thread object. + * + * @param[in] tp pointer to the thread + * @return The same thread pointer passed as parameter + * representing the new reference. + */ +Thread *chThdAddRef(Thread *tp) { + + chSysLock(); + chDbgAssert(tp->p_refs < 255, "chThdAddRef(), #1", "too many references"); + tp->p_refs++; + chSysUnlock(); + return tp; +} + +/** + * @brief Releases a reference to a thread object. + * @details If the references counter reaches zero and the thread + * is in the @p THD_STATE_FINAL state then the thread's memory is + * returned to the proper allocator. + * @note Static threads are not affected. + * + * @param[in] tp pointer to the thread + */ +void chThdRelease(Thread *tp) { + trefs_t refs; + + chSysLock(); + chDbgAssert(tp->p_refs > 0, "chThdRelease(), #1", "not referenced"); + refs = --tp->p_refs; + chSysUnlock(); + + /* If the references counter reaches zero then the memory can be returned + to the proper allocator. Of course static threads are not affected.*/ + if (refs == 0) { + switch (tp->p_flags & THD_MEM_MODE_MASK) { +#if CH_USE_HEAP + case THD_MEM_MODE_HEAP: + chHeapFree(tp); + break; +#endif +#if CH_USE_MEMPOOLS + case THD_MEM_MODE_MEMPOOL: + chPoolFree(tp->p_mpool, tp); + break; +#endif + } + } +} +#endif /* CH_USE_DYNAMIC */ + +#if CH_USE_WAITEXIT || defined(__DOXYGEN__) +/** + * @brief Blocks the execution of the invoking thread until the specified + * thread terminates then the exit code is returned. + * @details This function waits for the specified thread to terminate then + * decrements its reference counter, if the counter reaches zero then + * the thread working area is returned to the proper allocator.
+ * The memory used by the exited thread is handled in different ways + * depending on the API that spawned the thread: + * - If the thread was spawned by @p chThdCreateStatic() or by + * @p chThdInit() then nothing happens and the thread working area + * is not released or modified in any way. This is the default, + * totally static, behavior. + * - If the thread was spawned by @p chThdCreateFromHeap() then + * the working area is returned to the system heap. + * - If the thread was spawned by @p chThdCreateFromMemoryPool() + * then the working area is returned to the owning memory pool. + * . + * Please read the @ref article_lifecycle article for more details. + * @note After invoking @p chThdWait() the thread pointer becomes invalid + * and must not be used as parameter for further system calls. + * @note The function is available only if the @p CH_USE_WAITEXIT + * option is enabled in @p chconf.h. + * @note If @p CH_USE_DYNAMIC is not specified this function just waits for + * the thread termination, no memory allocators are involved. + * + * @param[in] tp pointer to the thread + * @return The exit code from the terminated thread. + */ +msg_t chThdWait(Thread *tp) { + msg_t msg; + + chDbgCheck(tp != NULL, "chThdWait"); + + chSysLock(); + chDbgAssert(tp != currp, "chThdWait(), #1", "waiting self"); +#if CH_USE_DYNAMIC + chDbgAssert(tp->p_refs > 0, "chThdWait(), #2", "not referenced"); +#endif + if (tp->p_state != THD_STATE_FINAL) { + list_insert(currp, &tp->p_waiting); + chSchGoSleepS(THD_STATE_WTEXIT); + } + msg = tp->p_u.exitcode; + chSysUnlock(); +#if CH_USE_DYNAMIC + chThdRelease(tp); +#endif + return msg; +} +#endif /* CH_USE_WAITEXIT */ + +/** @} */ diff --git a/os/kernel/src/chvt.c b/os/kernel/src/chvt.c index 9558a1cb7..b48e7f4f4 100644 --- a/os/kernel/src/chvt.c +++ b/os/kernel/src/chvt.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -28,7 +28,7 @@ #include "ch.h" /** - * @brief Virtual timers delta list header. + * @brief Virtual timers delta list header. */ VTList vtlist; diff --git a/os/kernel/templates/chconf.h b/os/kernel/templates/chconf.h index 6f8233b7f..02d38baf4 100644 --- a/os/kernel/templates/chconf.h +++ b/os/kernel/templates/chconf.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -404,7 +404,7 @@ * @brief Debug option, stacks initialization. * @details If enabled then the threads working area is filled with a byte * value when a thread is created. This can be useful for the - * runtime measurement of the used stack. + * runtime measurement of the used stack. * * @note The default is @p FALSE. */ diff --git a/os/kernel/templates/chcore.c b/os/kernel/templates/chcore.c index d1bad3c02..2bca5eb6c 100644 --- a/os/kernel/templates/chcore.c +++ b/os/kernel/templates/chcore.c @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -33,7 +33,7 @@ /** * @brief Port-related initialization code. - * @note This function is usually empty. + * @note This function is usually empty. */ void port_init(void) { } @@ -41,7 +41,7 @@ void port_init(void) { /** * @brief Kernel-lock action. * @details Usually this function just disables interrupts but may perform more - * actions. + * actions. */ void port_lock(void) { } @@ -74,20 +74,20 @@ void port_unlock_from_isr(void) { /** * @brief Disables all the interrupt sources. - * @note Of course non maskable interrupt sources are not included. + * @note Of course non maskable interrupt sources are not included. */ void port_disable(void) { } /** * @brief Disables the interrupt sources that are not supposed to preempt - * the kernel. + * the kernel. */ void port_suspend(void) { } /** - * @brief Enables all the interrupt sources. + * @brief Enables all the interrupt sources. */ void port_enable(void) { } @@ -97,7 +97,7 @@ void port_enable(void) { * @details The function is meant to return when an interrupt becomes pending. * The simplest implementation is an empty function or macro but this * would not take advantage of architecture-specific power saving - * modes. + * modes. */ void port_wait_for_interrupt(void) { } @@ -107,7 +107,7 @@ void port_wait_for_interrupt(void) { * @details This function is invoked by the operating system when an * unrecoverable error is detected (as example because a programming * error in the application code that triggers an assertion while in - * debug mode). + * debug mode). */ void port_halt(void) { diff --git a/os/kernel/templates/chcore.h b/os/kernel/templates/chcore.h index bf72fc042..0e78dbcf5 100644 --- a/os/kernel/templates/chcore.h +++ b/os/kernel/templates/chcore.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -41,7 +41,7 @@ #define CH_ARCHITECTURE_NAME "" /** - * @brief Name of the architecture variant (optional). + * @brief Name of the architecture variant (optional). */ #define CH_ARCHITECTURE_VARIANT_NAME "" @@ -144,7 +144,7 @@ struct context { /** * @brief IRQ handler function declaration. * @note @p id can be a function name or a vector number depending on the - * port implementation. + * port implementation. */ #define PORT_IRQ_HANDLER(id) void id(void) diff --git a/os/kernel/templates/chtypes.h b/os/kernel/templates/chtypes.h index f790d847c..5c771e999 100644 --- a/os/kernel/templates/chtypes.h +++ b/os/kernel/templates/chtypes.h @@ -1,5 +1,5 @@ /* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. -- cgit v1.2.3