aboutsummaryrefslogtreecommitdiffstats
path: root/src/chschd.c
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/chschd.c
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/chschd.c')
-rw-r--r--src/chschd.c408
1 files changed, 215 insertions, 193 deletions
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;
+}
+
+/** @} */