aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2008-07-22 09:55:51 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2008-07-22 09:55:51 +0000
commit49c3629538ee20a1df4ee5bbe664464e4904db5d (patch)
tree5c3379181ca4b45af5c1e8b2dde0e596e2220fcf /src
parent71a1820c4a0be292590ed63c284539a68cd22fbb (diff)
downloadChibiOS-49c3629538ee20a1df4ee5bbe664464e4904db5d.tar.gz
ChibiOS-49c3629538ee20a1df4ee5bbe664464e4904db5d.tar.bz2
ChibiOS-49c3629538ee20a1df4ee5bbe664464e4904db5d.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@346 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'src')
-rw-r--r--src/chinit.c167
-rw-r--r--src/chmtx.c503
-rw-r--r--src/chschd.c408
-rw-r--r--src/chthreads.c569
-rw-r--r--src/include/queues.h368
-rw-r--r--src/include/scheduler.h162
-rw-r--r--src/include/threads.h483
7 files changed, 1356 insertions, 1304 deletions
diff --git a/src/chinit.c b/src/chinit.c
index 5b2c0cd24..b8d36a6e5 100644
--- a/src/chinit.c
+++ b/src/chinit.c
@@ -1,81 +1,86 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup Initialization
- * @{
- */
-
-#include <ch.h>
-
-/**
- * ChibiOS/RT initialization. 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;
- static WorkingArea(waIdleThread, IDLE_THREAD_STACK_SIZE);
-
- chSchInit();
- chDbgInit();
-#ifdef CH_USE_VIRTUAL_TIMERS
- chVTInit();
-#endif
- /*
- * Now this instructions flow becomes the main thread.
- */
- init_thread(NORMALPRIO, 0, &mainthread);
- mainthread.p_state = PRCURR;
- currp = &mainthread;
-
- chSysUnlock();
-
- /*
- * The idle thread is created using the port-provided implementation.
- * 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.
- */
- chThdCreateFast(IDLEPRIO, waIdleThread,
- sizeof(waIdleThread), (tfunc_t)_IdleThread);
-}
-
-/**
- * Preemption routine, this function must be called into an interrupt
- * handler invoked by a system timer.
- * 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 (rlist.r_preempt > 0)
- rlist.r_preempt--;
-#ifdef CH_USE_SYSTEMTIME
- rlist.r_stime++;
-#endif
-
-#ifdef CH_USE_VIRTUAL_TIMERS
- chVTDoTickI();
-#endif
-}
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Initialization
+ * @{
+ */
+
+#include <ch.h>
+
+/**
+ * ChibiOS/RT initialization. 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;
+ static WorkingArea(waIdleThread, IDLE_THREAD_STACK_SIZE);
+
+ chSchInit();
+ chDbgInit();
+#ifdef CH_USE_VIRTUAL_TIMERS
+ chVTInit();
+#endif
+ /*
+ * Now this instructions flow becomes the main thread.
+ */
+ init_thread(NORMALPRIO, 0, &mainthread);
+ mainthread.p_state = PRCURR;
+ currp = &mainthread;
+
+ chSysUnlock();
+
+ /*
+ * The idle thread is created using the port-provided implementation.
+ * 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.
+ */
+ chThdCreateFast(IDLEPRIO, waIdleThread,
+ sizeof(waIdleThread), (tfunc_t)_IdleThread);
+}
+
+/**
+ * Handles time ticks for round robin preemption and timer increments.
+ *
+ * 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) {
+ /* running thread has not used up quantum yet? */
+ if (rlist.r_preempt > 0)
+ /* decrement remaining quantum */
+ rlist.r_preempt--;
+#ifdef CH_USE_SYSTEMTIME
+ rlist.r_stime++;
+#endif
+
+#ifdef CH_USE_VIRTUAL_TIMERS
+ chVTDoTickI();
+#endif
+}
+
+/** @} */
diff --git a/src/chmtx.c b/src/chmtx.c
index a6379836d..2e95afca6 100644
--- a/src/chmtx.c
+++ b/src/chmtx.c
@@ -1,243 +1,260 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup Mutexes
- * @{
- */
-
-#include <ch.h>
-
-#ifdef CH_USE_MUTEXES
-
-/**
- * Initializes s \p Mutex structure.
- * @param mp pointer to a \p Mutex structure
- */
-void chMtxInit(Mutex *mp) {
-
- fifo_init(&mp->m_queue);
- mp->m_owner = NULL;
-}
-
-/**
- * Locks the specified mutex.
- * @param mp pointer to the \p Mutex structure
- */
-void chMtxLock(Mutex *mp) {
-
- chSysLock();
-
- chMtxLockS(mp);
-
- chSysUnlock();
-}
-
-/**
- * Locks the specified mutex.
- * @param mp pointer to the \p Mutex structure
- * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
- * block.
- */
-void chMtxLockS(Mutex *mp) {
-
- if (mp->m_owner != NULL) {
- /*
- * Inheritance, explores the thread-mutex dependances adjusting
- * the priority of all the affected threads.
- */
- Thread *tp = mp->m_owner;
- while (tp->p_prio < currp->p_prio) {
- tp->p_prio = currp->p_prio;
- /*
- * The following states need priority queues reordering.
- */
- switch (tp->p_state) {
- case PRWTMTX:
- prio_insert(dequeue(tp), &tp->p_wtmtxp->m_queue);
- tp = tp->p_wtmtxp->m_owner;
- continue;
-#ifdef CH_USE_MESSAGES_PRIORITY
- case PRSNDMSG:
- if (tp->p_flags & P_MSGBYPRIO)
- prio_insert(dequeue(tp), &tp->p_wtthdp->p_msgqueue);
-#endif
- case PRREADY:
- chSchReadyI(dequeue(tp));
- }
- break;
- }
- /*
- * Goes to sleep on the mutex.
- */
- prio_insert(currp, &mp->m_queue);
- currp->p_wtmtxp = mp;
- chSchGoSleepS(PRWTMTX);
- chDbgAssert(mp->m_owner == NULL, "chmtx.c, chMtxLockS()");
- }
- /*
- * The mutex is now inserted in the owned mutexes list.
- */
- mp->m_owner = currp;
- mp->m_next = currp->p_mtxlist;
- currp->p_mtxlist = mp;
-}
-
-/**
- * Tries to lock a mutex. 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 mp pointer to the \p Mutex structure
- * @return \p TRUE if the mutex was successfully acquired else \p FALSE
- */
-bool_t chMtxTryLock(Mutex *mp) {
- bool_t b;
-
- chSysLock();
-
- b = chMtxTryLockS(mp);
-
- chSysUnlock();
- return b;
-}
-
-/**
- * Tries to lock a mutex. 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 mp pointer to the \p Mutex structure
- * @return \p TRUE if the mutex was successfully acquired else \p FALSE
- * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
- * block.
- */
-bool_t chMtxTryLockS(Mutex *mp) {
-
- if (mp->m_owner != NULL)
- return FALSE;
- mp->m_owner = currp;
- mp->m_next = currp->p_mtxlist;
- currp->p_mtxlist = mp;
- return TRUE;
-}
-
-/**
- * Unlocks the next owned mutex in reverse lock order.
- */
-void chMtxUnlock(void) {
- Mutex *mp;
-
- chSysLock();
-
- chDbgAssert((currp->p_mtxlist != NULL) && (currp->p_mtxlist->m_owner == currp),
- "chmtx.c, chMtxUnlock()");
-
- /*
- * Removes the top Mutex from the owned mutexes list and marks it as not owned.
- */
- mp = currp->p_mtxlist;
- currp->p_mtxlist = mp->m_next;
- mp->m_owner = NULL;
- /*
- * If a thread is waiting on the mutex then the hard part begins.
- */
- if (chMtxQueueNotEmptyS(mp)) {
- Thread *tp = fifo_remove(&mp->m_queue);
- /*
- * Recalculates the optimal thread priority by scanning the owned mutexes list.
- */
- tprio_t newprio = currp->p_realprio;
- mp = currp->p_mtxlist;
- while (mp != NULL) {
- if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
- newprio = mp->m_queue.p_next->p_prio;
- mp = mp->m_next;
- }
- currp->p_prio = newprio;
- chSchWakeupS(tp, RDY_OK);
- }
-
- chSysUnlock();
-}
-
-/**
- * Unlocks the next owned mutex in reverse lock order.
- * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
- * block.
- * @note This function does not reschedule internally.
- */
-void chMtxUnlockS(void) {
- Mutex *mp;
-
- chDbgAssert((currp->p_mtxlist != NULL) && (currp->p_mtxlist->m_owner == currp),
- "chmtx.c, chMtxUnlockS()");
-
- /*
- * Removes the top Mutex from the owned mutexes list and marks it as not owned.
- */
- mp = currp->p_mtxlist;
- currp->p_mtxlist = mp->m_next;
- mp->m_owner = NULL;
- /*
- * If a thread is waiting on the mutex then the hard part begins.
- */
- if (chMtxQueueNotEmptyS(mp)) {
- Thread *tp = fifo_remove(&mp->m_queue);
- /*
- * Recalculates the optimal thread priority by scanning the owned mutexes list.
- */
- tprio_t newprio = currp->p_realprio;
- mp = currp->p_mtxlist;
- while (mp != NULL) {
- if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
- newprio = mp->m_queue.p_next->p_prio;
- mp = mp->m_next;
- }
- currp->p_prio = newprio;
- chSchReadyI(tp);
- }
-}
-
-/**
- * Unlocks all the mutexes owned by the invoking thread, this 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) {
-
- chSysLock();
-
- if (currp->p_mtxlist != NULL) {
- do {
- Mutex *mp = currp->p_mtxlist;
- currp->p_mtxlist = mp->m_next;
- mp->m_owner = NULL;
- if (chMtxQueueNotEmptyS(mp))
- chSchReadyI(fifo_remove(&mp->m_queue));
- } while (currp->p_mtxlist != NULL);
- currp->p_prio = currp->p_realprio;
- chSchRescheduleS();
- }
-
- chSysUnlock();
-}
-
-#endif /* CH_USE_MUTEXES */
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Mutexes
+ * @{
+ */
+
+#include <ch.h>
+
+#ifdef CH_USE_MUTEXES
+
+/**
+ * Initializes s \p Mutex structure.
+ * @param mp pointer to a \p Mutex structure
+ */
+void chMtxInit(Mutex *mp) {
+
+ fifo_init(&mp->m_queue);
+ mp->m_owner = NULL;
+}
+
+/**
+ * Locks the specified mutex.
+ * @param mp pointer to the \p Mutex structure
+ */
+void chMtxLock(Mutex *mp) {
+
+ chSysLock();
+
+ chMtxLockS(mp);
+
+ chSysUnlock();
+}
+
+/**
+ * Locks the specified mutex.
+ *
+ * @param mp pointer to the \p Mutex structure
+ * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
+ * block.
+ */
+void chMtxLockS(Mutex *mp) {
+ /* the mutex is 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;
+ /* { tp is the thread currently owning the mutex } */
+ /* the running thread has higher priority than tp? */
+ while (tp->p_prio < currp->p_prio) {
+ /* make priority of thread tp match the running thread's priority */
+ tp->p_prio = currp->p_prio;
+ /*
+ * The following states need priority queues reordering.
+ */
+ switch (tp->p_state) {
+ /* thread tp is waiting on a mutex? */
+ case PRWTMTX:
+ /* requeue tp with its new priority on the mutex wait queue */
+ prio_insert(dequeue(tp), &tp->p_wtmtxp->m_queue);
+ /* boost the owner of this mutex if needed */
+ tp = tp->p_wtmtxp->m_owner;
+ continue;
+#ifdef CH_USE_MESSAGES_PRIORITY
+ case PRSNDMSG:
+ if (tp->p_flags & P_MSGBYPRIO)
+ /* requeue tp with its new priority on (?) */
+ prio_insert(dequeue(tp), &tp->p_wtthdp->p_msgqueue);
+ break;
+#endif
+ /* thread tp is ready? */
+ case PRREADY:
+ /* requeue tp with its new priority on the ready list */
+ chSchReadyI(dequeue(tp));
+ }
+ break;
+ }
+ /*
+ * Goes to sleep on the mutex.
+ */
+ prio_insert(currp, &mp->m_queue);
+ currp->p_wtmtxp = mp;
+ chSchGoSleepS(PRWTMTX);
+ chDbgAssert(mp->m_owner == NULL, "chmtx.c, chMtxLockS()");
+ }
+ /*
+ * The mutex is now inserted in the owned mutexes list.
+ */
+ mp->m_owner = currp;
+ mp->m_next = currp->p_mtxlist;
+ currp->p_mtxlist = mp;
+}
+
+/**
+ * Tries to lock a mutex. 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 mp pointer to the \p Mutex structure
+ * @return \p TRUE if the mutex was successfully acquired else \p FALSE
+ */
+bool_t chMtxTryLock(Mutex *mp) {
+ bool_t b;
+
+ chSysLock();
+
+ b = chMtxTryLockS(mp);
+
+ chSysUnlock();
+ return b;
+}
+
+/**
+ * Tries to lock a mutex. 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 mp pointer to the \p Mutex structure
+ * @return \p TRUE if the mutex was successfully acquired else \p FALSE
+ * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
+ * block.
+ */
+bool_t chMtxTryLockS(Mutex *mp) {
+
+ if (mp->m_owner != NULL)
+ return FALSE;
+ mp->m_owner = currp;
+ mp->m_next = currp->p_mtxlist;
+ currp->p_mtxlist = mp;
+ return TRUE;
+}
+
+/**
+ * Unlocks the next owned mutex in reverse lock order.
+ */
+void chMtxUnlock(void) {
+ Mutex *mp;
+
+ chSysLock();
+
+ chDbgAssert((currp->p_mtxlist != NULL) && (currp->p_mtxlist->m_owner == currp),
+ "chmtx.c, chMtxUnlock()");
+
+ /*
+ * Removes the top Mutex from the owned mutexes list and marks it as not owned.
+ */
+ mp = currp->p_mtxlist;
+ currp->p_mtxlist = mp->m_next;
+ mp->m_owner = NULL;
+ /*
+ * If a thread is waiting on the mutex then the hard part begins.
+ */
+ if (chMtxQueueNotEmptyS(mp)) {
+ /* get the highest priority thread waiting for the unlocked mutex */
+ Thread *tp = fifo_remove(&mp->m_queue);
+ /*
+ * Recalculates the optimal thread priority by scanning the owned mutexes list.
+ */
+ tprio_t newprio = currp->p_realprio;
+ /* iterate mp over all the (other) mutexes the current thread still owns */
+ mp = currp->p_mtxlist;
+ while (mp != NULL) {
+ /* mutex mp has a higher priority thread pending? */
+ if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
+ /* boost current thread's priority to waiting thread */
+ newprio = mp->m_queue.p_next->p_prio;
+ mp = mp->m_next;
+ }
+ /* (possibly) boost the priority of the current thread */
+ currp->p_prio = newprio;
+ /* awaken the highest priority thread waiting for the unlocked mutex */
+ chSchWakeupS(tp, RDY_OK);
+ }
+ chSysUnlock();
+}
+
+/**
+ * Unlocks the next owned mutex in reverse lock order.
+ * @note This function must be called within a \p chSysLock() / \p chSysUnlock()
+ * block.
+ * @note This function does not reschedule internally.
+ */
+void chMtxUnlockS(void) {
+ Mutex *mp;
+
+ chDbgAssert((currp->p_mtxlist != NULL) && (currp->p_mtxlist->m_owner == currp),
+ "chmtx.c, chMtxUnlockS()");
+
+ /*
+ * Removes the top Mutex from the owned mutexes list and marks it as not owned.
+ */
+ mp = currp->p_mtxlist;
+ currp->p_mtxlist = mp->m_next;
+ mp->m_owner = NULL;
+ /*
+ * If a thread is waiting on the mutex then the hard part begins.
+ */
+ if (chMtxQueueNotEmptyS(mp)) {
+ Thread *tp = fifo_remove(&mp->m_queue);
+ /*
+ * Recalculates the optimal thread priority by scanning the owned mutexes list.
+ */
+ tprio_t newprio = currp->p_realprio;
+ mp = currp->p_mtxlist;
+ while (mp != NULL) {
+ if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
+ newprio = mp->m_queue.p_next->p_prio;
+ mp = mp->m_next;
+ }
+ currp->p_prio = newprio;
+ chSchReadyI(tp);
+ }
+}
+
+/**
+ * Unlocks all the mutexes owned by the invoking thread, this 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) {
+
+ chSysLock();
+
+ if (currp->p_mtxlist != NULL) {
+ do {
+ Mutex *mp = currp->p_mtxlist;
+ currp->p_mtxlist = mp->m_next;
+ mp->m_owner = NULL;
+ if (chMtxQueueNotEmptyS(mp))
+ chSchReadyI(fifo_remove(&mp->m_queue));
+ } while (currp->p_mtxlist != NULL);
+ currp->p_prio = currp->p_realprio;
+ chSchRescheduleS();
+ }
+
+ chSysUnlock();
+}
+
+#endif /* CH_USE_MUTEXES */
+
+/** @} */
diff --git a/src/chschd.c b/src/chschd.c
index 70c867535..6a82eb1d8 100644
--- a/src/chschd.c
+++ b/src/chschd.c
@@ -1,193 +1,215 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup Scheduler
- * @{
- */
-
-#include <ch.h>
-
-/** @cond never */
-ReadyList rlist;
-/** @endcond */
-
-/**
- * Scheduler initialization.
- * @note Internally invoked by the \p chSysInit().
- */
-void chSchInit(void) {
-
- fifo_init(&rlist.r_queue);
- rlist.r_prio = NOPRIO;
- rlist.r_preempt = CH_TIME_QUANTUM;
-#ifdef CH_USE_SYSTEMTIME
- rlist.r_stime = 0;
-#endif
-}
-
-/**
- * Inserts a thread in the Ready List.
- * @param tp the Thread to be made ready
- * @return the Thread pointer
- * @note The function must be called in the system mutex zone.
- * @note The function does not reschedule, the \p chSchRescheduleS() should
- * be called soon after.
- * @note The function is not meant to be used in the user code directly.
- */
-#ifdef 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 = PRREADY;
- cp = rlist.r_queue.p_next;
- while (cp->p_prio >= tp->p_prio)
- cp = cp->p_next;
- /* Insertion on p_prev.*/
- tp->p_prev = (tp->p_next = cp)->p_prev;
- tp->p_prev->p_next = cp->p_prev = tp;
- return tp;
-}
-
-/**
- * Puts the current thread to sleep into the specified state, the next highest
- * priority thread becomes running. The threads states are described into
- * \p threads.h
- * @param newstate the new thread state
- * @note The function must be called in the system mutex zone.
- * @note The function is not meant to be used in the user code directly.
- */
-void chSchGoSleepS(tstate_t newstate) {
- Thread *otp;
-
- (otp = currp)->p_state = newstate;
- (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
- rlist.r_preempt = CH_TIME_QUANTUM;
-#ifdef CH_USE_TRACE
- chDbgTrace(otp, currp);
-#endif
- chSysSwitchI(otp, currp);
-}
-
-#ifdef CH_USE_VIRTUAL_TIMERS
-/*
- * Timeout wakeup callback.
- */
-static void wakeup(void *p) {
-
-#ifdef CH_USE_SEMAPHORES
- if (((Thread *)p)->p_state == PRWTSEM)
- chSemFastSignalI(((Thread *)p)->p_wtsemp);
-#endif
- chSchReadyI(p)->p_rdymsg = RDY_TIMEOUT;
-}
-
-/**
- * Puts the current thread to sleep into the specified state, the next highest
- * priority thread becomes running. The thread is automatically awakened after
- * the specified time elapsed.
- * @param newstate the new thread state
- * @param time the number of ticks before the operation timouts
- * @return the wakeup message, it is \p RDY_TIMEOUT if a timeout occurs
- * @note The function must be called in the system mutex zone.
- * @note The function is not meant to be used in the user code directly.
- */
-msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
- VirtualTimer vt;
-
- chVTSetI(&vt, time, wakeup, currp);
- chSchGoSleepS(newstate);
- if (chVTIsArmedI(&vt))
- chVTResetI(&vt);
- return currp->p_rdymsg;
-}
-#endif /* CH_USE_VIRTUAL_TIMERS */
-
-/**
- * Wakeups a thread, the thread is inserted into the ready list or made
- * running directly depending on its relative priority compared to the current
- * thread.
- * @param ntp the Thread to be made ready
- * @param msg message to the awakened thread
- * @note The function must be called in the system mutex zone.
- * @note The function is not meant to be used in the user code directly.
- * @note It is equivalent to a \p chSchReadyI() followed by a
- * \p chSchRescheduleS() but much more efficient.
- */
-void chSchWakeupS(Thread *ntp, msg_t msg) {
-
- ntp->p_rdymsg = msg;
- if (ntp->p_prio <= currp->p_prio)
- chSchReadyI(ntp);
- else {
- Thread *otp = currp;
- chSchReadyI(otp);
- (currp = ntp)->p_state = PRCURR;
- rlist.r_preempt = CH_TIME_QUANTUM;
-#ifdef CH_USE_TRACE
- chDbgTrace(otp, ntp);
-#endif
- chSysSwitchI(otp, ntp);
- }
-}
-
-/**
- * Performs a reschedulation. It is meant to be called if
- * \p chSchRescRequired() evaluates to \p TRUE.
- */
-void chSchDoRescheduleI(void) {
- Thread *otp = currp;
-
- chSchReadyI(otp);
- (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
- rlist.r_preempt = CH_TIME_QUANTUM;
-#ifdef CH_USE_TRACE
- chDbgTrace(otp, currp);
-#endif
- chSysSwitchI(otp, currp);
-}
-
-/**
- * If a thread with an higher priority than the current thread is in the
- * ready list then it becomes running.
- * @note The function must be called in the system mutex zone.
- */
-void chSchRescheduleS(void) {
-
- if (firstprio(&rlist.r_queue) > currp->p_prio)
- chSchDoRescheduleI();
-}
-
-/**
- * Evaluates if a reschedulation is required.
- * @return \p TRUE if there is a thread that should go in running state
- * immediatly else \p FALSE.
- */
-bool_t chSchRescRequiredI(void) {
- tprio_t p1 = firstprio(&rlist.r_queue);
- tprio_t p2 = currp->p_prio;
-
- return rlist.r_preempt ? p1 > p2 : p1 >= p2;
-}
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Scheduler
+ * @{
+ */
+
+#include <ch.h>
+
+/** @cond never */
+ReadyList rlist;
+/** @endcond */
+
+/**
+ * Scheduler initialization.
+ * @note Internally invoked by the \p chSysInit().
+ */
+void chSchInit(void) {
+
+ fifo_init(&rlist.r_queue);
+ rlist.r_prio = NOPRIO;
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#ifdef CH_USE_SYSTEMTIME
+ rlist.r_stime = 0;
+#endif
+}
+
+/**
+ * Inserts a thread in the Ready List.
+ *
+ * @param tp the Thread to be made ready
+ * @return the Thread pointer
+ * @note The function must be called in the system mutex zone.
+ * @note The function does not reschedule, the \p chSchRescheduleS() should
+ * be called soon after.
+ * @note The function is not meant to be used in the user code directly.
+ */
+#ifdef 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 = PRREADY;
+ cp = rlist.r_queue.p_next;
+ while (cp->p_prio >= tp->p_prio)
+ cp = cp->p_next;
+ /* Insertion on p_prev.*/
+ tp->p_prev = (tp->p_next = cp)->p_prev;
+ tp->p_prev->p_next = cp->p_prev = tp;
+ return tp;
+}
+
+/**
+ * Puts the current thread to sleep into the specified state, the next highest
+ * priority thread becomes running. The threads states are described into
+ * \p threads.h
+ * @param newstate the new thread state
+ * @note The function must be called in the system mutex zone.
+ * @note The function is not meant to be used in the user code directly.
+ */
+void chSchGoSleepS(tstate_t newstate) {
+ Thread *otp;
+
+ (otp = currp)->p_state = newstate;
+ (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#ifdef CH_USE_TRACE
+ chDbgTrace(otp, currp);
+#endif
+ chSysSwitchI(otp, currp);
+}
+
+#ifdef CH_USE_VIRTUAL_TIMERS
+/*
+ * Timeout wakeup callback.
+ */
+static void wakeup(void *p) {
+
+#ifdef CH_USE_SEMAPHORES
+ if (((Thread *)p)->p_state == PRWTSEM)
+ chSemFastSignalI(((Thread *)p)->p_wtsemp);
+#endif
+ chSchReadyI(p)->p_rdymsg = RDY_TIMEOUT;
+}
+
+/**
+ * Put the current thread to sleep.
+ *
+ * Puts the current thread to sleep into the specified state. The next highest
+ * priority thread becomes running. The thread put to sleep is awakened after
+ * the specified time has elapsed.
+ *
+ * @param newstate the new thread state
+ * @param time the number of ticks before the operation timouts
+ * @return the wakeup message, it is \p RDY_TIMEOUT if a timeout occurs
+ * @note The function must be called in the system mutex zone.
+ * @note The function is not meant to be used in the user code directly.
+ */
+msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
+ VirtualTimer vt;
+
+ chVTSetI(&vt, time, wakeup, currp);
+ chSchGoSleepS(newstate);
+ if (chVTIsArmedI(&vt))
+ chVTResetI(&vt);
+ return currp->p_rdymsg;
+}
+#endif /* CH_USE_VIRTUAL_TIMERS */
+
+/**
+ * Wakes up a thread.
+ *
+ * Wakes up a thread. The thread is inserted into the ready list or immediately
+ * made running depending on its relative priority compared to the current
+ * thread.
+ * @param ntp the Thread to be made ready
+ * @param msg message to the awakened thread
+ * @note The function must be called in the system mutex zone.
+ * @note The function is not meant to be used in the user code directly.
+ * @note It is equivalent to a \p chSchReadyI() followed by a
+ * \p chSchRescheduleS() but much more efficient.
+ */
+void chSchWakeupS(Thread *ntp, msg_t msg) {
+ ntp->p_rdymsg = msg;
+ /* the woken thread has equal or lower priority than the running thread? */
+ if (ntp->p_prio <= currp->p_prio)
+ /* put the woken thread on the ready queue */
+ chSchReadyI(ntp);
+ /* the woken thread has higher priority than the running thread */
+ else {
+ /* put the running thread on the ready queue */
+ Thread *otp = currp;
+ chSchReadyI(otp);
+ (currp = ntp)->p_state = PRCURR;
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#ifdef CH_USE_TRACE
+ chDbgTrace(otp, ntp);
+#endif
+ /* switch the thread context */
+ chSysSwitchI(otp, ntp);
+ }
+}
+
+/**
+ * Switch to the first thread on the runnable queue.
+ *
+ * Intended to be called if \p chSchRescRequired() evaluates to \p TRUE.
+ */
+void chSchDoRescheduleI(void) {
+ /* put the running thread on the ready queue */
+ Thread *otp = currp;
+ chSchReadyI(otp);
+ /* pick the first thread from the ready queue */
+ (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#ifdef CH_USE_TRACE
+ chDbgTrace(otp, currp);
+#endif
+ /* switch thread context */
+ chSysSwitchI(otp, currp);
+}
+
+/**
+ * Reschedule only if a higher priority thread is runnable.
+ *
+ * If a thread with a higher priority than the current thread is in the
+ * ready list then make the higher priority thread running.
+ *
+ * @note The function must be called in the system mutex zone.
+ */
+void chSchRescheduleS(void) {
+ /* first thread in the runnable queue has higher priority than the running
+ * thread? */
+ if (firstprio(&rlist.r_queue) > currp->p_prio)
+ chSchDoRescheduleI();
+}
+
+/**
+ * Evaluates if rescheduling is required.
+ *
+ * @return \p TRUE if there is a thread that should go in running state
+ * immediately else \p FALSE.
+ */
+bool_t chSchRescRequiredI(void) {
+ tprio_t p1 = firstprio(&rlist.r_queue);
+ tprio_t p2 = currp->p_prio;
+ /* 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;
+}
+
+/** @} */
diff --git a/src/chthreads.c b/src/chthreads.c
index e19e04acf..990b9bdba 100644
--- a/src/chthreads.c
+++ b/src/chthreads.c
@@ -1,282 +1,287 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup Threads
- * @{
- */
-
-#include <ch.h>
-
-/*
- * Initializes a thread structure.
- */
-void init_thread(tprio_t prio, tmode_t mode, Thread *tp) {
- static tid_t nextid = 0;
-
- tp->p_tid = nextid++;
- tp->p_flags = mode;
- tp->p_prio = prio;
-#ifdef CH_USE_MUTEXES
- tp->p_realprio = prio;
- tp->p_mtxlist = NULL;
-#endif
-#ifdef CH_USE_WAITEXIT
- list_init(&tp->p_waiting);
-#endif
-#ifdef CH_USE_MESSAGES
- fifo_init(&tp->p_msgqueue);
-#endif
-#ifdef CH_USE_EVENTS
- tp->p_epending = 0;
-#endif
-#ifdef CH_USE_EXIT_EVENT
- chEvtInit(&tp->p_exitesource);
-#endif
-}
-
-#ifdef CH_USE_DEBUG
-static void memfill(uint8_t *p, uint32_t n, uint8_t v) {
-
- while (n)
- *p++ = v, n--;
-}
-#endif
-
-/**
- * Creates a new thread.
- * @param prio the priority level for the new thread. Usually the threads are
- * created with priority \p NORMALPRIO, priorities
- * can range from \p LOWPRIO to \p HIGHPRIO.
- * @param mode the creation option flags for the thread. The following options
- * can be OR'ed in this parameter:<br>
- * <ul>
- * <li>\p P_SUSPENDED, the thread is created in the
- * \p PRSUSPENDED state and a subsequent call to
- * \p chThdResume() will make it ready for
- * execution.</li>
- * <li>\p P_TERMINATED, this flag is usually set
- * by the \p chThdTerminate() function and it is not
- * normally used as parameter for this function. The
- * result would be to create a thread with a termination
- * request already pending.</li>
- * </ul>
- * @param workspace pointer to a working area dedicated to the thread stack
- * @param wsize size of the working area.
- * @param pf the thread function. Returning from this function automatically
- * terminates the thread.
- * @param 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.
- * @note A thread can terminate by calling \p chThdExit() or by simply
- * returning from its main function.
- */
-Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
- size_t wsize, tfunc_t pf, void *arg) {
- Thread *tp = workspace;
-
- chDbgAssert((wsize >= UserStackSize(0)) && (prio <= HIGHPRIO) &&
- (workspace != NULL) && (pf != NULL),
- "chthreads.c, chThdCreate()");
-#ifdef CH_USE_DEBUG
- memfill(workspace, wsize, MEM_FILL_PATTERN);
-#endif
- SETUP_CONTEXT(workspace, wsize, pf, arg);
- init_thread(prio, mode, tp);
-#ifdef CH_USE_RESUME
- if (tp->p_flags & P_SUSPENDED)
- tp->p_state = PRSUSPENDED;
- else {
-#endif
- chSysLock();
- chSchWakeupS(tp, RDY_OK);
- chSysUnlock();
-#ifdef CH_USE_RESUME
- }
-#endif
- return tp;
-}
-
-/**
- * Creates a new thread.
- * @param prio the priority level for the new thread. Usually the threads are
- * created with priority \p NORMALPRIO, priorities
- * can range from \p LOWPRIO to \p HIGHPRIO.
- * @param workspace pointer to a working area dedicated to the thread stack
- * @param wsize size of the working area.
- * @param pf the thread function. Returning from this function automatically
- * terminates the thread.
- * @return the pointer to the \p Thread structure allocated for the
- * thread into the working space area.
- * @note A thread can terminate by calling \p chThdExit() or by simply
- * returning from its main function.
- */
-Thread *chThdCreateFast(tprio_t prio, void *workspace,
- size_t wsize, tfunc_t pf) {
- Thread *tp = workspace;
-
- chDbgAssert((wsize >= UserStackSize(0)) && (prio <= HIGHPRIO) &&
- (workspace != NULL) && (pf != NULL),
- "chthreads.c, chThdCreateFast()");
-#ifdef CH_USE_DEBUG
- memfill(workspace, wsize, MEM_FILL_PATTERN);
-#endif
- SETUP_CONTEXT(workspace, wsize, pf, NULL);
- init_thread(prio, 0, tp);
- chSysLock();
- chSchWakeupS(tp, RDY_OK);
- chSysUnlock();
- return tp;
-}
-
-/**
- * Changes the thread priority, reschedules if necessary.
- * @param newprio the new priority of the invoking thread
- */
-void chThdSetPriority(tprio_t newprio) {
-
- chDbgAssert(newprio <= HIGHPRIO, "chthreads.c, chThdSetPriority()")
- chSysLock();
-
-#ifdef CH_USE_MUTEXES
- if (currp->p_prio != currp->p_realprio) {
- if (newprio > currp->p_prio)
- currp->p_prio = newprio;
- }
- else
- currp->p_prio = newprio;
- currp->p_realprio = newprio;
-#else
- currp->p_prio = newprio;
-#endif
- chSchRescheduleS();
-
- chSysUnlock();
-}
-
-#ifdef CH_USE_SUSPEND
-/**
- * Suspends the invoking thread.
- *
- * @param tpp pointer to a \p Thread pointer, the \p Thread pointer is set
- * to point to the suspended process before it enters the
- * \p PRSUSPENDED state, it is set to \p NULL after it is resumed.
- * This allows to implement a "test and resume" on the variable
- * into interrupt handlers.
- * @note The function is available only if the \p CH_USE_SUSPEND
- * option is enabled in \p chconf.h.
- */
-void chThdSuspend(Thread **tpp) {
-
- chSysLock();
-
- chDbgAssert(*tpp == NULL, "chthreads.c, chThdSuspend()");
- *tpp = currp;
- chSchGoSleepS(PRSUSPENDED);
- *tpp = NULL;
-
- chSysUnlock();
-}
-#endif /* CH_USE_SUSPEND */
-
-#ifdef CH_USE_RESUME
-/**
- * Resumes a thread created with the \p P_SUSPENDED option or suspended with
- * \p chThdSuspend().
- * @param tp the pointer to the thread
- * @note The function has no effect on threads in any other state than
- * \p PRSUSPENDED.
- * @note The function is available only if the \p CH_USE_RESUME
- * option is enabled in \p chconf.h.
- */
-void chThdResume(Thread *tp) {
-
- chSysLock();
-
- if ((tp)->p_state == PRSUSPENDED)
- chSchWakeupS(tp, RDY_OK);
-
- chSysUnlock();
-}
-#endif
-
-#ifdef CH_USE_TERMINATE
-/**
- * Requests a thread termination.
- * @param tp the pointer to the thread
- * @note The thread is not termitated 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.
- */
-void chThdTerminate(Thread *tp) {
-
- chSysLock();
-
- tp->p_flags |= P_TERMINATE;
-
- chSysUnlock();
-}
-#endif
-
-/**
- * Terminates the current thread by specifying an exit status code.
- * @param msg the thread exit code. The code can be retrieved by using
- * \p chThdWait().
- */
-void chThdExit(msg_t msg) {
-
- chSysLock();
-
- currp->p_exitcode = msg;
-#ifdef CH_USE_WAITEXIT
- while (notempty(&currp->p_waiting))
- chSchReadyI(list_remove(&currp->p_waiting));
-#endif
-#ifdef CH_USE_EXIT_EVENT
- chEvtSendI(&currp->p_exitesource);
-#endif
- chSchGoSleepS(PREXIT);
-}
-
-#ifdef CH_USE_WAITEXIT
-/**
- * Blocks the execution of the invoking thread until the specified thread
- * terminates then the exit code is returned.
- * @param tp the pointer to the thread
- * @return the exit code
- * @note The function is available only if the \p CH_USE_WAITEXIT
- * option is enabled in \p chconf.h.
- */
-msg_t chThdWait(Thread *tp) {
- msg_t msg;
-
- chSysLock();
-
- if (tp->p_state != PREXIT) {
- list_insert(currp, &tp->p_waiting);
- chSchGoSleepS(PRWAIT);
- }
- msg = tp->p_exitcode;
-
- chSysUnlock();
- return msg;
-}
-#endif /* CH_USE_WAITEXIT */
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Threads
+ * @{
+ */
+
+#include <ch.h>
+
+/*
+ * Initializes a thread structure.
+ */
+void init_thread(tprio_t prio, tmode_t mode, Thread *tp) {
+ static tid_t nextid = 0;
+
+ tp->p_tid = nextid++;
+ tp->p_flags = mode;
+ tp->p_prio = prio;
+#ifdef CH_USE_MUTEXES
+ /* realprio is the thread's own, non-inherited, priority */
+ tp->p_realprio = prio;
+ tp->p_mtxlist = NULL;
+#endif
+#ifdef CH_USE_WAITEXIT
+ list_init(&tp->p_waiting);
+#endif
+#ifdef CH_USE_MESSAGES
+ fifo_init(&tp->p_msgqueue);
+#endif
+#ifdef CH_USE_EVENTS
+ tp->p_epending = 0;
+#endif
+#ifdef CH_USE_EXIT_EVENT
+ chEvtInit(&tp->p_exitesource);
+#endif
+}
+
+#ifdef CH_USE_DEBUG
+static void memfill(uint8_t *p, uint32_t n, uint8_t v) {
+
+ while (n)
+ *p++ = v, n--;
+}
+#endif
+
+/**
+ * Creates a new thread.
+ * @param prio the priority level for the new thread. Usually the threads are
+ * created with priority \p NORMALPRIO, priorities
+ * can range from \p LOWPRIO to \p HIGHPRIO.
+ * @param mode the creation option flags for the thread. The following options
+ * can be OR'ed in this parameter:<br>
+ * <ul>
+ * <li>\p P_SUSPENDED, the thread is created in the
+ * \p PRSUSPENDED state and a subsequent call to
+ * \p chThdResume() will make it ready for
+ * execution.</li>
+ * <li>\p P_TERMINATED, this flag is usually set
+ * by the \p chThdTerminate() function and it is not
+ * normally used as parameter for this function. The
+ * result would be to create a thread with a termination
+ * request already pending.</li>
+ * </ul>
+ * @param workspace pointer to a working area dedicated to the thread stack
+ * @param wsize size of the working area.
+ * @param pf the thread function. Returning from this function automatically
+ * terminates the thread.
+ * @param 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.
+ * @note A thread can terminate by calling \p chThdExit() or by simply
+ * returning from its main function.
+ */
+Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
+ size_t wsize, tfunc_t pf, void *arg) {
+ /* thread structure is layed out in the lower part of the thread workspace */
+ Thread *tp = workspace;
+
+ chDbgAssert((wsize >= UserStackSize(0)) && (prio <= HIGHPRIO) &&
+ (workspace != NULL) && (pf != NULL),
+ "chthreads.c, chThdCreate()");
+#ifdef CH_USE_DEBUG
+ memfill(workspace, wsize, MEM_FILL_PATTERN);
+#endif
+ SETUP_CONTEXT(workspace, wsize, pf, arg);
+ init_thread(prio, mode, tp);
+#ifdef CH_USE_RESUME
+ if (tp->p_flags & P_SUSPENDED)
+ tp->p_state = PRSUSPENDED;
+ else {
+#endif
+ chSysLock();
+ chSchWakeupS(tp, RDY_OK);
+ chSysUnlock();
+#ifdef CH_USE_RESUME
+ }
+#endif
+ return tp;
+}
+
+/**
+ * Creates a new thread.
+ * @param prio the priority level for the new thread. Usually the threads are
+ * created with priority \p NORMALPRIO, priorities
+ * can range from \p LOWPRIO to \p HIGHPRIO.
+ * @param workspace pointer to a working area dedicated to the thread stack
+ * @param wsize size of the working area.
+ * @param pf the thread function. Returning from this function automatically
+ * terminates the thread.
+ * @return the pointer to the \p Thread structure allocated for the
+ * thread into the working space area.
+ * @note A thread can terminate by calling \p chThdExit() or by simply
+ * returning from its main function.
+ */
+Thread *chThdCreateFast(tprio_t prio, void *workspace,
+ size_t wsize, tfunc_t pf) {
+ Thread *tp = workspace;
+
+ chDbgAssert((wsize >= UserStackSize(0)) && (prio <= HIGHPRIO) &&
+ (workspace != NULL) && (pf != NULL),
+ "chthreads.c, chThdCreateFast()");
+#ifdef CH_USE_DEBUG
+ memfill(workspace, wsize, MEM_FILL_PATTERN);
+#endif
+ SETUP_CONTEXT(workspace, wsize, pf, NULL);
+ init_thread(prio, 0, tp);
+ chSysLock();
+ chSchWakeupS(tp, RDY_OK);
+ chSysUnlock();
+ return tp;
+}
+
+/**
+ * Changes the running thread priority, reschedules if necessary.
+ *
+ * @param newprio the new priority of the running thread
+ */
+void chThdSetPriority(tprio_t newprio) {
+
+ chDbgAssert(newprio <= HIGHPRIO, "chthreads.c, chThdSetPriority()")
+ chSysLock();
+
+#ifdef CH_USE_MUTEXES
+ if (currp->p_prio != currp->p_realprio) {
+ if (newprio > currp->p_prio)
+ currp->p_prio = newprio;
+ }
+ else
+ currp->p_prio = newprio;
+ currp->p_realprio = newprio;
+#else
+ currp->p_prio = newprio;
+#endif
+ chSchRescheduleS();
+
+ chSysUnlock();
+}
+
+#ifdef CH_USE_SUSPEND
+/**
+ * Suspends the invoking thread.
+ *
+ * @param tpp pointer to a \p Thread pointer, the \p Thread pointer is set
+ * to point to the suspended process before it enters the
+ * \p PRSUSPENDED state, it is set to \p NULL after it is resumed.
+ * This allows to implement a "test and resume" on the variable
+ * into interrupt handlers.
+ * @note The function is available only if the \p CH_USE_SUSPEND
+ * option is enabled in \p chconf.h.
+ */
+void chThdSuspend(Thread **tpp) {
+
+ chSysLock();
+
+ chDbgAssert(*tpp == NULL, "chthreads.c, chThdSuspend()");
+ *tpp = currp;
+ chSchGoSleepS(PRSUSPENDED);
+ *tpp = NULL;
+
+ chSysUnlock();
+}
+#endif /* CH_USE_SUSPEND */
+
+#ifdef CH_USE_RESUME
+/**
+ * Resumes a thread created with the \p P_SUSPENDED option or suspended with
+ * \p chThdSuspend().
+ * @param tp the pointer to the thread
+ * @note The function has no effect on threads in any other state than
+ * \p PRSUSPENDED.
+ * @note The function is available only if the \p CH_USE_RESUME
+ * option is enabled in \p chconf.h.
+ */
+void chThdResume(Thread *tp) {
+
+ chSysLock();
+
+ if ((tp)->p_state == PRSUSPENDED)
+ chSchWakeupS(tp, RDY_OK);
+
+ chSysUnlock();
+}
+#endif
+
+#ifdef CH_USE_TERMINATE
+/**
+ * Requests a thread termination.
+ * @param tp the pointer to the thread
+ * @note The thread is not termitated 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.
+ */
+void chThdTerminate(Thread *tp) {
+
+ chSysLock();
+
+ tp->p_flags |= P_TERMINATE;
+
+ chSysUnlock();
+}
+#endif
+
+/**
+ * Terminates the current thread by specifying an exit status code.
+ *
+ * @param msg the thread exit code. The code can be retrieved by using
+ * \p chThdWait().
+ */
+void chThdExit(msg_t msg) {
+
+ chSysLock();
+
+ currp->p_exitcode = msg;
+#ifdef CH_USE_WAITEXIT
+ while (notempty(&currp->p_waiting))
+ chSchReadyI(list_remove(&currp->p_waiting));
+#endif
+#ifdef CH_USE_EXIT_EVENT
+ chEvtSendI(&currp->p_exitesource);
+#endif
+ chSchGoSleepS(PREXIT);
+}
+
+#ifdef CH_USE_WAITEXIT
+/**
+ * Blocks the execution of the invoking thread until the specified thread
+ * terminates then the exit code is returned.
+ *
+ * @param tp the pointer to the thread
+ * @return the exit code
+ * @note The function is available only if the \p CH_USE_WAITEXIT
+ * option is enabled in \p chconf.h.
+ */
+msg_t chThdWait(Thread *tp) {
+ msg_t msg;
+
+ chSysLock();
+
+ if (tp->p_state != PREXIT) {
+ list_insert(currp, &tp->p_waiting);
+ chSchGoSleepS(PRWAIT);
+ }
+ msg = tp->p_exitcode;
+
+ chSysUnlock();
+ return msg;
+}
+#endif /* CH_USE_WAITEXIT */
+
+/** @} */
diff --git a/src/include/queues.h b/src/include/queues.h
index 5c480e8cf..0a373b5ea 100644
--- a/src/include/queues.h
+++ b/src/include/queues.h
@@ -1,184 +1,184 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup IOQueues
- * @{
- */
-
-#ifndef _QUEUES_H_
-#define _QUEUES_H_
-
-/** Queue notification callback type.*/
-typedef void (*qnotify_t)(void);
-
-/** Returned by the queue functions if the operation is successful.*/
-#define Q_OK RDY_OK
-/** Returned by the queue functions if a timeout occurs.*/
-#define Q_TIMEOUT RDY_TIMEOUT
-/** Returned by the queue functions if the queue is reset.*/
-#define Q_RESET RDY_RESET
-/** Returned by the queue functions if the queue is empty.*/
-#define Q_EMPTY -3
-/** Returned by the queue functions if the queue is full.*/
-#define Q_FULL -4
-
-#ifdef CH_USE_QUEUES
-/**
- * I/O queue structure, it is used by both Input and Output Queues,
- * the difference is on how the semaphore is initialized.
- */
-typedef struct {
- /** Pointer to the queue buffer.*/
- uint8_t *q_buffer;
- /** Pointer to the first location after the buffer.*/
- uint8_t *q_top;
- /** Write pointer.*/
- uint8_t *q_wrptr;
- /** Read pointer.*/
- uint8_t *q_rdptr;
- /** Counter semaphore.*/
- Semaphore q_sem;
- /** Data notification callback.*/
- qnotify_t q_notify;
-} Queue;
-
-/** Returns the queue's buffer size.*/
-#define chQSize(q) \
- ((q)->q_top - (q)->q_buffer)
-
-/** Returns the used space if used on an Input Queue and the empty space if
- * used on an Output Queue.*/
-#define chQSpace(q) \
- ((q)->q_sem.s_cnt)
-
-/** Evaluates to TRUE if the specified Input Queue is empty.*/
-#define chIQIsEmpty(q) \
- (chQSpace(q) <= 0)
-
-/** Evaluates to TRUE if the specified Input Queue is full.*/
-#define chIQIsFull(q) \
- (chQSpace(q) >= chQSize(q))
-
-/** Evaluates to TRUE if the specified Output Queue is empty.*/
-#define chOQIsEmpty(q) \
- (chQSpace(q) >= chQSize(q))
-
-/** Evaluates to TRUE if the specified Output Queue is full.*/
-#define chOQIsFull(q) \
- (chQSpace(q) <= 0)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- /*
- * Input Queues functions. An Input Queue is usually written into by an
- * interrupt handler and read from a thread.
- */
- void chIQInit(Queue *qp, uint8_t *buffer, size_t size, qnotify_t inotify);
- void chIQReset(Queue *qp);
- msg_t chIQPutI(Queue *qp, uint8_t b);
- msg_t chIQGet(Queue *qp);
- size_t chIQRead(Queue *qp, uint8_t *buffer, size_t n);
-#ifdef CH_USE_QUEUES_TIMEOUT
- msg_t chIQGetTimeout(Queue *qp, systime_t time);
-#endif
-
- /*
- * Output Queues functions. An Output Queue is usually written into by a
- * thread and read from an interrupt handler.
- */
- void chOQInit(Queue *queue, uint8_t *buffer, size_t size, qnotify_t onotify);
- void chOQReset(Queue *queue);
- void chOQPut(Queue *queue, uint8_t b);
- msg_t chOQGetI(Queue *queue);
- size_t chOQWrite(Queue *queue, uint8_t *buffer, size_t n);
-#ifdef __cplusplus
-}
-#endif
-#endif /* CH_USE_QUEUES */
-
-#ifdef CH_USE_QUEUES_HALFDUPLEX
-/**
- * Half duplex queue structure.
- */
-typedef struct {
- /** Pointer to the queue buffer.*/
- uint8_t *hdq_buffer;
- /** Pointer to the first location after the buffer.*/
- uint8_t *hdq_top;
- /** Write pointer.*/
- uint8_t *hdq_wrptr;
- /** Read pointer.*/
- uint8_t *hdq_rdptr;
- /** Input counter semaphore.*/
- Semaphore hdq_isem;
- /** Output counter semaphore.*/
- Semaphore hdq_osem;
- /** Input data notification callback.*/
- qnotify_t hdq_inotify;
- /** Output data notification callback.*/
- qnotify_t hdq_onotify;
-} HalfDuplexQueue;
-
-/** Returns the queue's buffer size.*/
-#define chHDQSize(q) \
- ((q)->hdq_top - (q)->hdq_buffer)
-
-/** Returns the queue space when in transmission mode.*/
-#define chHDQEmptySpace(q) \
- ((q)->hdq_osem.s_cnt)
-
-/** Returns the number of the bytes in the queue when in receive mode.*/
-#define chHDQFilledSpace(q) \
- ((q)->hdq_isem.s_cnt)
-
-/** Evaluates to TRUE if the queue is in transmit mode.*/
-#define chHDQIsTransmitting(q) \
- (chHDQEmptySpace(q) < chHDQSize(q))
-
-/** Evaluates to TRUE if the queue is in receive mode.*/
-#define chHDQIsReceiving(q) \
- (chHDQEmptySpaceQ(q) >= chHDQSize(q))
-
-/** Evaluates to TRUE if the receive queue is full.*/
-#define chHDQIsFullReceive(q) \
- (chHDQFilledSpace(q) >= chHDQSize(q))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void chHDQInit(HalfDuplexQueue *qp, uint8_t *buffer, size_t size,
- qnotify_t inotify, qnotify_t onotify);
- msg_t chHDQGetReceive(HalfDuplexQueue *qp);
- void chHDQPutTransmit(HalfDuplexQueue *qp, uint8_t b);
- msg_t chHDQGetTransmitI(HalfDuplexQueue *qp);
- msg_t chHDQPutReceiveI(HalfDuplexQueue *qp, uint8_t b);
-#ifdef CH_USE_QUEUES_TIMEOUT
- msg_t chHDQGetReceiveTimeout(HalfDuplexQueue *qp, systime_t time);
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CH_USE_QUEUES_HALFDUPLEX */
-
-#endif /* _QUEUES_H_ */
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup IOQueues
+ * @{
+ */
+
+#ifndef _QUEUES_H_
+#define _QUEUES_H_
+
+/** Queue notification callback type. */
+typedef void (*qnotify_t)(void);
+
+/** Returned by the queue functions if the operation is successful. */
+#define Q_OK RDY_OK
+/** Returned by the queue functions if a timeout occurs. */
+#define Q_TIMEOUT RDY_TIMEOUT
+/** Returned by the queue functions if the queue is reset. */
+#define Q_RESET RDY_RESET
+/** Returned by the queue functions if the queue is empty. */
+#define Q_EMPTY -3
+/** Returned by the queue functions if the queue is full. */
+#define Q_FULL -4
+
+#ifdef CH_USE_QUEUES
+/**
+ * I/O queue structure, it is used by both Input and Output Queues,
+ * the difference is on how the semaphore is initialized.
+ */
+typedef struct {
+ /** Pointer to the queue buffer. */
+ uint8_t *q_buffer;
+ /** Pointer to the first location after the buffer. */
+ uint8_t *q_top;
+ /** Write pointer. */
+ uint8_t *q_wrptr;
+ /** Read pointer. */
+ uint8_t *q_rdptr;
+ /** Counter semaphore. */
+ Semaphore q_sem;
+ /** Data notification callback. */
+ qnotify_t q_notify;
+} Queue;
+
+/** Returns the queue's buffer size. */
+#define chQSize(q) \
+ ((q)->q_top - (q)->q_buffer)
+
+/** Returns the used space if used on an Input Queue and the empty space if
+ * used on an Output Queue. */
+#define chQSpace(q) \
+ ((q)->q_sem.s_cnt)
+
+/** Evaluates to TRUE if the specified Input Queue is empty. */
+#define chIQIsEmpty(q) \
+ (chQSpace(q) <= 0)
+
+/** Evaluates to TRUE if the specified Input Queue is full. */
+#define chIQIsFull(q) \
+ (chQSpace(q) >= chQSize(q))
+
+/** Evaluates to TRUE if the specified Output Queue is empty. */
+#define chOQIsEmpty(q) \
+ (chQSpace(q) >= chQSize(q))
+
+/** Evaluates to TRUE if the specified Output Queue is full. */
+#define chOQIsFull(q) \
+ (chQSpace(q) <= 0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /*
+ * Input Queues functions. An Input Queue is usually written into by an
+ * interrupt handler and read from a thread.
+ */
+ void chIQInit(Queue *qp, uint8_t *buffer, size_t size, qnotify_t inotify);
+ void chIQReset(Queue *qp);
+ msg_t chIQPutI(Queue *qp, uint8_t b);
+ msg_t chIQGet(Queue *qp);
+ size_t chIQRead(Queue *qp, uint8_t *buffer, size_t n);
+#ifdef CH_USE_QUEUES_TIMEOUT
+ msg_t chIQGetTimeout(Queue *qp, systime_t time);
+#endif
+
+ /*
+ * Output Queues functions. An Output Queue is usually written into by a
+ * thread and read from an interrupt handler.
+ */
+ void chOQInit(Queue *queue, uint8_t *buffer, size_t size, qnotify_t onotify);
+ void chOQReset(Queue *queue);
+ void chOQPut(Queue *queue, uint8_t b);
+ msg_t chOQGetI(Queue *queue);
+ size_t chOQWrite(Queue *queue, uint8_t *buffer, size_t n);
+#ifdef __cplusplus
+}
+#endif
+#endif /* CH_USE_QUEUES */
+
+#ifdef CH_USE_QUEUES_HALFDUPLEX
+/**
+ * Half duplex queue structure.
+ */
+typedef struct {
+ /** Pointer to the queue buffer. */
+ uint8_t *hdq_buffer;
+ /** Pointer to the first location after the buffer. */
+ uint8_t *hdq_top;
+ /** Write pointer.*/
+ uint8_t *hdq_wrptr;
+ /** Read pointer.*/
+ uint8_t *hdq_rdptr;
+ /** Input counter semaphore. */
+ Semaphore hdq_isem;
+ /** Output counter semaphore. */
+ Semaphore hdq_osem;
+ /** Input data notification callback. */
+ qnotify_t hdq_inotify;
+ /** Output data notification callback. */
+ qnotify_t hdq_onotify;
+} HalfDuplexQueue;
+
+/** Returns the queue's buffer size. */
+#define chHDQSize(q) \
+ ((q)->hdq_top - (q)->hdq_buffer)
+
+/** Returns the queue space when in transmission mode. */
+#define chHDQEmptySpace(q) \
+ ((q)->hdq_osem.s_cnt)
+
+/** Returns the number of the bytes in the queue when in receive mode. */
+#define chHDQFilledSpace(q) \
+ ((q)->hdq_isem.s_cnt)
+
+/** Evaluates to TRUE if the queue is in transmit mode. */
+#define chHDQIsTransmitting(q) \
+ (chHDQEmptySpace(q) < chHDQSize(q))
+
+/** Evaluates to TRUE if the queue is in receive mode. */
+#define chHDQIsReceiving(q) \
+ (chHDQEmptySpaceQ(q) >= chHDQSize(q))
+
+/** Evaluates to TRUE if the receive queue is full. */
+#define chHDQIsFullReceive(q) \
+ (chHDQFilledSpace(q) >= chHDQSize(q))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chHDQInit(HalfDuplexQueue *qp, uint8_t *buffer, size_t size,
+ qnotify_t inotify, qnotify_t onotify);
+ msg_t chHDQGetReceive(HalfDuplexQueue *qp);
+ void chHDQPutTransmit(HalfDuplexQueue *qp, uint8_t b);
+ msg_t chHDQGetTransmitI(HalfDuplexQueue *qp);
+ msg_t chHDQPutReceiveI(HalfDuplexQueue *qp, uint8_t b);
+#ifdef CH_USE_QUEUES_TIMEOUT
+ msg_t chHDQGetReceiveTimeout(HalfDuplexQueue *qp, systime_t time);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_USE_QUEUES_HALFDUPLEX */
+
+#endif /* _QUEUES_H_ */
+
+/** @} */
diff --git a/src/include/scheduler.h b/src/include/scheduler.h
index 0235a7c97..3a6486efe 100644
--- a/src/include/scheduler.h
+++ b/src/include/scheduler.h
@@ -1,80 +1,82 @@
-/*
- 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/>.
-*/
-
-/**
- * @addtogroup Scheduler
- * @{
- */
-
-#ifndef _SCHEDULER_H_
-#define _SCHEDULER_H_
-
-/** Normal \p chSchReadyI() message.*/
-#define RDY_OK 0
-/** Returned if the thread was made ready because a timeout.*/
-#define RDY_TIMEOUT -1
-/** Returned if the thread was made ready because a reset.*/
-#define RDY_RESET -2
-
-#define firstprio(rlp) ((rlp)->p_next->p_prio)
-
-/**
- * Ready list header.
- */
-typedef struct {
- ThreadsQueue r_queue;
- tprio_t r_prio;
- cnt_t r_preempt;
-#ifndef CH_CURRP_REGISTER_CACHE
- Thread *r_current;
-#endif
-#ifdef CH_USE_SYSTEMTIME
- volatile systime_t r_stime;
-#endif
-} ReadyList;
-
-extern ReadyList rlist;
-
-/*
- * Scheduler APIs.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
- void chSchInit(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 chSchRescRequiredI(void);
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef CH_CURRP_REGISTER_CACHE
-register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
-#else
-#define currp rlist.r_current
-#endif
-
-#endif /* _SCHEDULER_H_ */
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Scheduler
+ * @{
+ */
+
+#ifndef _SCHEDULER_H_
+#define _SCHEDULER_H_
+
+/** Normal \p chSchReadyI() message. */
+#define RDY_OK 0
+/** Returned when the thread was made ready because of a timeout. */
+#define RDY_TIMEOUT -1
+/** Returned when the thread was made ready because of a reset. */
+#define RDY_RESET -2
+
+/** The priority of the first thread on the given ready list. */
+#define firstprio(rlp) ((rlp)->p_next->p_prio)
+
+/**
+ * Ready list header.
+ */
+typedef struct {
+ ThreadsQueue r_queue;
+ tprio_t r_prio;
+ cnt_t r_preempt;
+#ifndef CH_CURRP_REGISTER_CACHE
+ /** the currently running thread */
+ Thread *r_current;
+#endif
+#ifdef CH_USE_SYSTEMTIME
+ volatile systime_t r_stime;
+#endif
+} ReadyList;
+
+extern ReadyList rlist;
+
+/*
+ * Scheduler APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSchInit(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 chSchRescRequiredI(void);
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef CH_CURRP_REGISTER_CACHE
+register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
+#else
+#define currp rlist.r_current
+#endif
+
+#endif /* _SCHEDULER_H_ */
+
+/** @} */
diff --git a/src/include/threads.h b/src/include/threads.h
index 5bfd51423..b7b1a3e29 100644
--- a/src/include/threads.h
+++ b/src/include/threads.h
@@ -1,241 +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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @addtogroup Threads
- * @{
- */
-
-#ifndef _THREADS_H_
-#define _THREADS_H_
-
-/**
- * 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 {
- /** Next \p Thread in the threads list.*/
- Thread *p_next;
- /* End of the fields shared with the ThreadsList structure. */
- /** Previous \p Thread in the threads list.*/
- Thread *p_prev;
- /* End of the fields shared with the ThreadsQueue structure. */
- /** The thread priority.*/
- tprio_t p_prio;
- /* End of the fields shared with the ReadyList structure. */
- /** Thread identifier. */
- tid_t p_tid;
- /** Current thread state.*/
- tstate_t p_state;
- /** Mode flags.*/
- tmode_t p_flags;
- /** Machine dependent processor context.*/
- Context p_ctx;
- /*
- * The following fields are merged in unions because they are all
- * state-specific fields. This trick saves some extra space for each
- * thread in the system.
- */
- union {
- /** Thread wakeup code (only valid when exiting the \p PRREADY state).*/
- msg_t p_rdymsg;
- /** The thread exit code (only while in \p PREXIT state).*/
- msg_t p_exitcode;
-#ifdef CH_USE_SEMAPHORES
- /** Semaphore where the thread is waiting on (only in \p PRWTSEM state).*/
- Semaphore *p_wtsemp;
-#endif
-#ifdef CH_USE_MUTEXES
- /** Mutex where the thread is waiting on (only in \p PRWTMTX state).*/
- Mutex *p_wtmtxp;
-#endif
-#ifdef CH_USE_MESSAGES
- /** Destination thread for message send (only in \p PRSNDMSG state).*/
- Thread *p_wtthdp;
-#endif
-#ifdef CH_USE_EVENTS
- /** Enabled events mask (only while in \p PRWTEVENT state).*/
- eventmask_t p_ewmask;
-#endif
-#ifdef CH_USE_TRACE
- /** Kernel object where the thread is waiting on. It is only valid when
- the thread is some sleeping states.*/
- void *p_wtobjp;
-#endif
- };
- /*
- * Start of the optional fields.
- */
-#ifdef CH_USE_WAITEXIT
- /** The list of the threads waiting for this thread termination.*/
- ThreadsList p_waiting;
-#endif
-#ifdef CH_USE_EXIT_EVENT
- /** The thread termination \p EventSource.*/
- EventSource p_exitesource;
-#endif
-#ifdef CH_USE_MESSAGES
- ThreadsQueue p_msgqueue;
- msg_t p_msg;
-#endif
-#ifdef CH_USE_EVENTS
- /** Pending events mask.*/
- eventmask_t p_epending;
-#endif
-#ifdef CH_USE_MUTEXES
- /** Owner mutexes list, \p NULL terminated.*/
- Mutex *p_mtxlist;
- tprio_t p_realprio;
-#endif
-};
-
-/** Thread state: Thread in the ready list.*/
-#define PRREADY 0
-/** Thread state: Current.*/
-#define PRCURR 1
-/** Thread state: Thread created in suspended state.*/
-#define PRSUSPENDED 2
-/** Thread state: Waiting on a semaphore.*/
-#define PRWTSEM 3
-/** Thread state: Waiting on a mutex.*/
-#define PRWTMTX 4
-/** Thread state: Waiting in \p chThdSleep() or \p chThdSleepUntil().*/
-#define PRSLEEP 5
-/** Thread state: Waiting in \p chThdWait().*/
-#define PRWAIT 6
-/** Thread state: Waiting in \p chEvtWait().*/
-#define PRWTEVENT 7
-/** Thread state: Waiting in \p chMsgSend().*/
-#define PRSNDMSG 8
-/** Thread state: Waiting in \p chMsgWait().*/
-#define PRWTMSG 9
-/** Thread state: After termination.*/
-#define PREXIT 10
-
-#ifdef CH_USE_TERMINATE
-/** Thread option: Termination requested flag.*/
-#define P_TERMINATE 1
-#endif
-#ifdef CH_USE_RESUME
-/** Thread option: Create suspended thread.*/
-#define P_SUSPENDED 2
-#endif
-#ifdef CH_USE_MESSAGES_PRIORITY
-/** Thread option: Serve messages by priority instead of FIFO order.*/
-#define P_MSGBYPRIO 4
-#endif
-
-/** Pseudo priority used by the ready list header, do not use.*/
-#define NOPRIO 0
-/** Idle thread priority.*/
-#define IDLEPRIO 1
-/** Lowest user priority.*/
-#define LOWPRIO 2
-/** Normal user priority.*/
-#define NORMALPRIO 64
-/** Highest user priority.*/
-#define HIGHPRIO 127
-/** Greatest possible priority.*/
-#define ABSPRIO 255
-
-/* Not an API, don't use into the application code.*/
-void init_thread(tprio_t prio, tmode_t mode, Thread *tp);
-
-/** Thread function.*/
-typedef msg_t (*tfunc_t)(void *);
-
-/*
- * Threads APIs.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
- Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
- size_t wsize, tfunc_t pf, void *arg);
- Thread *chThdCreateFast(tprio_t prio, void *workspace,
- size_t wsize, tfunc_t pf);
- void chThdSetPriority(tprio_t newprio);
- void chThdExit(msg_t msg);
-#ifdef CH_USE_RESUME
- void chThdResume(Thread *tp);
-#endif
-#ifdef CH_USE_SUSPEND
- void chThdSuspend(Thread **tpp);
-#endif
-#ifdef CH_USE_TERMINATE
- void chThdTerminate(Thread *tp);
-#endif
-#ifdef CH_USE_WAITEXIT
- msg_t chThdWait(Thread *tp);
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/** Returns the pointer to the \p Thread currently in execution.*/
-#define chThdSelf() currp
-
-/** Returns the thread priority.*/
-#define chThdGetPriority() (currp->p_prio)
-
-/** Returns the pointer to the \p Thread local storage area, if any.*/
-#define chThdLS() (void *)(currp + 1)
-
-/** Verifies if the specified thread is in the \p PREXIT state.*/
-#define chThdTerminated(tp) ((tp)->p_state == PREXIT)
-
-/**
- * Verifies if the current thread has a termination request pending.
- */
-#define chThdShouldTerminate() (currp->p_flags & P_TERMINATE)
-
-/**
- * Returns the exit event source for the specified thread. The source is
- * signaled when the thread terminates.
- * @param tp the pointer to the thread
- * @note When registering on a thread termination make sure the thread
- * is still alive, if you do that after the thread termination
- * then you would miss the event. There are two ways to ensure
- * this:<br>
- * <ul>
- * <li>Create the thread suspended, register on the event source
- * and then resume the thread (recommended).</li>
- * <li>Create the thread with a lower priority then register on it.
- * This does not work if the hardware is capable of multiple
- * physical threads.</li>
- * </ul>
- * @note You dont need to unregister from a terminated thread because
- * the event source becomes inactive.
- * @note The function is available only if the \p CH_USE_EXIT_EVENT
- * option is enabled in \p chconf.h.
- */
-#define chThdGetExitEventSource(tp) (&(tp)->p_exitesource)
-
-/**
- * Resumes a thread created with the \p P_SUSPENDED option or suspended with
- * \p chThdSuspend().
- * @param tp the pointer to the thread
- */
-#define chThdResumeI(tp) chSchReadyI((tp), RDY_OK)
-
-#endif /* _THREADS_H_ */
-
-/** @} */
+/*
+ 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/>.
+*/
+
+/**
+ * @addtogroup Threads
+ * @{
+ */
+
+#ifndef _THREADS_H_
+#define _THREADS_H_
+
+/**
+ * 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 {
+ /** Next \p Thread in the threads list.*/
+ Thread *p_next;
+ /* End of the fields shared with the ThreadsList structure. */
+ /** Previous \p Thread in the threads list.*/
+ Thread *p_prev;
+ /* End of the fields shared with the ThreadsQueue structure. */
+ /** The thread priority.*/
+ tprio_t p_prio;
+ /* End of the fields shared with the ReadyList structure. */
+ /** Thread identifier. */
+ tid_t p_tid;
+ /** Current thread state.*/
+ tstate_t p_state;
+ /** Mode flags. */
+ tmode_t p_flags;
+ /** Machine dependent processor context.*/
+ Context p_ctx;
+ /*
+ * The following fields are merged in unions because they are all
+ * state-specific fields. This trick saves some extra space for each
+ * thread in the system.
+ */
+ union {
+ /** Thread wakeup code (only valid when exiting the \p PRREADY state). */
+ msg_t p_rdymsg;
+ /** The thread exit code (only while in \p PREXIT state).*/
+ msg_t p_exitcode;
+#ifdef CH_USE_SEMAPHORES
+ /** Semaphore where the thread is waiting on (only in \p PRWTSEM state). */
+ Semaphore *p_wtsemp;
+#endif
+#ifdef CH_USE_MUTEXES
+ /** Mutex where the thread is waiting on (only in \p PRWTMTX state). */
+ Mutex *p_wtmtxp;
+#endif
+#ifdef CH_USE_MESSAGES
+ /** Destination thread for message send (only in \p PRSNDMSG state). */
+ Thread *p_wtthdp;
+#endif
+#ifdef CH_USE_EVENTS
+ /** Enabled events mask (only while in \p PRWTEVENT state). */
+ eventmask_t p_ewmask;
+#endif
+#ifdef CH_USE_TRACE
+ /** Kernel object where the thread is waiting on. It is only valid when
+ the thread is some sleeping states. */
+ void *p_wtobjp;
+#endif
+ };
+ /*
+ * Start of the optional fields.
+ */
+#ifdef CH_USE_WAITEXIT
+ /** The list of the threads waiting for this thread termination.*/
+ ThreadsList p_waiting;
+#endif
+#ifdef CH_USE_EXIT_EVENT
+ /** The thread termination \p EventSource.*/
+ EventSource p_exitesource;
+#endif
+#ifdef CH_USE_MESSAGES
+ ThreadsQueue p_msgqueue;
+ msg_t p_msg;
+#endif
+#ifdef CH_USE_EVENTS
+ /** Pending events mask.*/
+ eventmask_t p_epending;
+#endif
+#ifdef CH_USE_MUTEXES
+ /** List of mutexes owned by this thread, \p NULL terminated.*/
+ Mutex *p_mtxlist;
+ /** Thread's own, non-inherited, priority */
+ tprio_t p_realprio;
+#endif
+};
+
+/** Thread state: Thread in the ready list.*/
+#define PRREADY 0
+/** Thread state: Current.*/
+#define PRCURR 1
+/** Thread state: Thread created in suspended state.*/
+#define PRSUSPENDED 2
+/** Thread state: Waiting on a semaphore.*/
+#define PRWTSEM 3
+/** Thread state: Waiting on a mutex.*/
+#define PRWTMTX 4
+/** Thread state: Waiting in \p chThdSleep() or \p chThdSleepUntil().*/
+#define PRSLEEP 5
+/** Thread state: Waiting in \p chThdWait().*/
+#define PRWAIT 6
+/** Thread state: Waiting in \p chEvtWait().*/
+#define PRWTEVENT 7
+/** Thread state: Waiting in \p chMsgSend().*/
+#define PRSNDMSG 8
+/** Thread state: Waiting in \p chMsgWait().*/
+#define PRWTMSG 9
+/** Thread state: After termination.*/
+#define PREXIT 10
+
+#ifdef CH_USE_TERMINATE
+/** Thread option: Termination requested flag.*/
+#define P_TERMINATE 1
+#endif
+#ifdef CH_USE_RESUME
+/** Thread option: Create suspended thread.*/
+#define P_SUSPENDED 2
+#endif
+#ifdef CH_USE_MESSAGES_PRIORITY
+/** Thread option: Serve messages by priority instead of FIFO order.*/
+#define P_MSGBYPRIO 4
+#endif
+
+/** Pseudo priority used by the ready list header, do not use.*/
+#define NOPRIO 0
+/** Idle thread priority.*/
+#define IDLEPRIO 1
+/** Lowest user priority.*/
+#define LOWPRIO 2
+/** Normal user priority.*/
+#define NORMALPRIO 64
+/** Highest user priority.*/
+#define HIGHPRIO 127
+/** Greatest possible priority.*/
+#define ABSPRIO 255
+
+/* Not an API, don't use into the application code.*/
+void init_thread(tprio_t prio, tmode_t mode, Thread *tp);
+
+/** Thread function.*/
+typedef msg_t (*tfunc_t)(void *);
+
+/*
+ * Threads APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
+ size_t wsize, tfunc_t pf, void *arg);
+ Thread *chThdCreateFast(tprio_t prio, void *workspace,
+ size_t wsize, tfunc_t pf);
+ void chThdSetPriority(tprio_t newprio);
+ void chThdExit(msg_t msg);
+#ifdef CH_USE_RESUME
+ void chThdResume(Thread *tp);
+#endif
+#ifdef CH_USE_SUSPEND
+ void chThdSuspend(Thread **tpp);
+#endif
+#ifdef CH_USE_TERMINATE
+ void chThdTerminate(Thread *tp);
+#endif
+#ifdef CH_USE_WAITEXIT
+ msg_t chThdWait(Thread *tp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/** Returns the pointer to the \p Thread currently in execution.*/
+#define chThdSelf() currp
+
+/** Returns the thread priority.*/
+#define chThdGetPriority() (currp->p_prio)
+
+/** Returns the pointer to the \p Thread local storage area, if any.*/
+#define chThdLS() (void *)(currp + 1)
+
+/** Verifies if the specified thread is in the \p PREXIT state.*/
+#define chThdTerminated(tp) ((tp)->p_state == PREXIT)
+
+/**
+ * Verifies if the current thread has a termination request pending.
+ */
+#define chThdShouldTerminate() (currp->p_flags & P_TERMINATE)
+
+/**
+ * Returns the exit event source for the specified thread. The source is
+ * signaled when the thread terminates.
+ * @param tp the pointer to the thread
+ * @note When registering on a thread termination make sure the thread
+ * is still alive, if you do that after the thread termination
+ * then you would miss the event. There are two ways to ensure
+ * this:<br>
+ * <ul>
+ * <li>Create the thread suspended, register on the event source
+ * and then resume the thread (recommended).</li>
+ * <li>Create the thread with a lower priority then register on it.
+ * This does not work if the hardware is capable of multiple
+ * physical threads.</li>
+ * </ul>
+ * @note You dont need to unregister from a terminated thread because
+ * the event source becomes inactive.
+ * @note The function is available only if the \p CH_USE_EXIT_EVENT
+ * option is enabled in \p chconf.h.
+ */
+#define chThdGetExitEventSource(tp) (&(tp)->p_exitesource)
+
+/**
+ * Resumes a thread created with the \p P_SUSPENDED option or suspended with
+ * \p chThdSuspend().
+ * @param tp the pointer to the thread
+ */
+#define chThdResumeI(tp) chSchReadyI((tp), RDY_OK)
+
+#endif /* _THREADS_H_ */
+
+/** @} */