aboutsummaryrefslogtreecommitdiffstats
path: root/os/kernel/src
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-02-21 07:24:53 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-02-21 07:24:53 +0000
commit157b6f9695e7f72f2d54b231c19cb4045710ed01 (patch)
treea856d81bf5f173c207510fdeb7367e218f12b3db /os/kernel/src
parenta90a90ffcf0f90b2a4b6c24dc5a60e72652549f1 (diff)
downloadChibiOS-157b6f9695e7f72f2d54b231c19cb4045710ed01.tar.gz
ChibiOS-157b6f9695e7f72f2d54b231c19cb4045710ed01.tar.bz2
ChibiOS-157b6f9695e7f72f2d54b231c19cb4045710ed01.zip
Updated license dates.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1646 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/kernel/src')
-rw-r--r--os/kernel/src/chcond.c2
-rw-r--r--os/kernel/src/chdebug.c4
-rw-r--r--os/kernel/src/chevents.c2
-rw-r--r--os/kernel/src/chheap.c2
-rw-r--r--os/kernel/src/chlists.c2
-rw-r--r--os/kernel/src/chmboxes.c4
-rw-r--r--os/kernel/src/chmemcore.c6
-rw-r--r--os/kernel/src/chmempools.c2
-rw-r--r--os/kernel/src/chmsg.c2
-rw-r--r--os/kernel/src/chmtx.c552
-rw-r--r--os/kernel/src/chqueues.c2
-rw-r--r--os/kernel/src/chregistry.c6
-rw-r--r--os/kernel/src/chschd.c560
-rw-r--r--os/kernel/src/chsem.c2
-rw-r--r--os/kernel/src/chsys.c260
-rw-r--r--os/kernel/src/chthreads.c892
-rw-r--r--os/kernel/src/chvt.c4
17 files changed, 1152 insertions, 1152 deletions
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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @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 <b>MUCH MORE</b> 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <b>MUCH MORE</b> 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @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.<br>
- * 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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.<br>
+ * 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @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 <b>and</b> 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.<br>
- * 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <b>and</b> 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.<br>
+ * 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;