From aaad958769e757093a258cfdd5c75f515534fd7a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 13 Aug 2011 07:06:02 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3224 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/include/chschd.h | 39 ++++++++++++++++++++---- os/kernel/include/chsys.h | 15 ++++++++-- os/kernel/src/chschd.c | 74 ++++++++++++++++++++++------------------------ 3 files changed, 81 insertions(+), 47 deletions(-) (limited to 'os/kernel') diff --git a/os/kernel/include/chschd.h b/os/kernel/include/chschd.h index cd545a05e..0e933e8ba 100644 --- a/os/kernel/include/chschd.h +++ b/os/kernel/include/chschd.h @@ -134,14 +134,14 @@ extern "C" { #if !defined(PORT_OPTIMIZED_WAKEUPS) void chSchWakeupS(Thread *tp, msg_t msg); #endif -#if !defined(PORT_OPTIMIZED_DORESCHEDULEI) - void chSchDoRescheduleI(void); -#endif #if !defined(PORT_OPTIMIZED_RESCHEDULES) void chSchRescheduleS(void); #endif -#if !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI) - bool_t chSchIsRescRequiredExI(void); +#if !defined(PORT_OPTIMIZED_ISPREEMPTIONREQUIRED) + bool_t chSchIsPreemptionRequired(void); +#endif +#if !defined(PORT_OPTIMIZED_DORESCHEDULE) + void chSchDoReschedule(void); #endif #ifdef __cplusplus } @@ -179,10 +179,37 @@ extern "C" { #if !defined(PORT_OPTIMIZED_DOYIELDS) || defined(__DOXYGEN__) #define chSchDoYieldS() { \ if (chSchCanYieldS()) \ - chSchDoRescheduleI(); \ + chSchDoReschedule(); \ } #endif /* !defined(PORT_OPTIMIZED_DOYIELDS) */ +/** + * @brief Inlineable preemption code. + * @details This is the common preemption code, this function must be invoked + * exclusively from the port layer. + * + * @special + */ +#if (CH_TIME_QUANTUM > 0) || defined(__DOXYGEN__) +#define chSchPreemption() { \ + tprio_t p1 = firstprio(&rlist.r_queue); \ + tprio_t p2 = currp->p_prio; \ + if (rlist.r_preempt) { \ + if (p1 > p2) \ + chSchDoReschedule(); \ + } \ + else { \ + if (p1 >= p2) \ + chSchDoReschedule(); \ + } \ +} +#else /* CH_TIME_QUANTUM == 0 */ +#define chSchPreemption() { \ + if (p1 >= p2) \ + chSchDoReschedule(); \ +} +#endif /* CH_TIME_QUANTUM == 0 */ + #endif /* _CHSCHD_H_ */ /** @} */ diff --git a/os/kernel/include/chsys.h b/os/kernel/include/chsys.h index 994b1301f..7c3a77d5c 100644 --- a/os/kernel/include/chsys.h +++ b/os/kernel/include/chsys.h @@ -66,14 +66,15 @@ /** * @brief Performs a context switch. - * @note This function should nevel be used from user code directly. + * @note Not a user function, it is meant to be invoked by the scheduler + * itself or from within the port layer. * * @param[in] ntp the thread to be switched in * @param[in] otp the thread to be switched out * * @special */ -#define chSysSwitchI(ntp, otp) { \ +#define chSysSwitch(ntp, otp) { \ dbg_trace(otp); \ port_switch(ntp, otp); \ } @@ -180,6 +181,8 @@ * @brief IRQ handler enter code. * @note Usually IRQ handlers functions are also declared naked. * @note On some architectures this macro can be empty. + * + * @special */ #define CH_IRQ_PROLOGUE() { \ PORT_IRQ_PROLOGUE(); \ @@ -190,7 +193,9 @@ * @brief IRQ handler exit code. * @note Usually IRQ handlers function are also declared naked. * @note This macro usually performs the final reschedule by using - * @p chSchRescRequiredI() and @p chSchDoRescheduleI(). + * @p chSchIsPreemptionRequired() and @p chSchDoReschedule(). + * + * @special */ #define CH_IRQ_EPILOGUE() { \ dbg_check_leave_isr(); \ @@ -201,6 +206,8 @@ * @brief Standard normal IRQ handler declaration. * @note @p id can be a function name or a vector number depending on the * port implementation. + * + * @special */ #define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) @@ -209,6 +216,8 @@ * @note @p id can be a function name or a vector number depending on the * port implementation. * @note Not all architectures support fast interrupts. + * + * @special */ #define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id) diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index b481a0b6a..f2014b8c7 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -76,7 +76,6 @@ Thread *chSchReadyI(Thread *tp) { Thread *cp; /* Integrity checks.*/ - chDbgCheckClassI(); chDbgAssert((tp->p_state != THD_STATE_READY) && (tp->p_state != THD_STATE_FINAL), "chSchReadyI(), #1", @@ -116,7 +115,7 @@ void chSchGoSleepS(tstate_t newstate) { #endif setcurrp(fifo_remove(&rlist.r_queue)); currp->p_state = THD_STATE_CURRENT; - chSysSwitchI(currp, otp); + chSysSwitch(currp, otp); } #endif /* !defined(PORT_OPTIMIZED_GOSLEEPS) */ @@ -228,36 +227,11 @@ void chSchWakeupS(Thread *ntp, msg_t msg) { #endif setcurrp(ntp); ntp->p_state = THD_STATE_CURRENT; - chSysSwitchI(ntp, otp); + chSysSwitch(ntp, otp); } } #endif /* !defined(PORT_OPTIMIZED_WAKEUPS) */ -/** - * @brief Switches to the first thread on the runnable queue. - * @note It is intended to be called if @p chSchRescRequiredI() evaluates - * to @p TRUE. - * - * @iclass - */ -#if !defined(PORT_OPTIMIZED_DORESCHEDULEI) || defined(__DOXYGEN__) -void chSchDoRescheduleI(void) { - Thread *otp; - - chDbgCheckClassI(); - -#if CH_TIME_QUANTUM > 0 - rlist.r_preempt = CH_TIME_QUANTUM; -#endif - otp = currp; - /* Picks the first thread from the ready queue and makes it current.*/ - setcurrp(fifo_remove(&rlist.r_queue)); - currp->p_state = THD_STATE_CURRENT; - chSchReadyI(otp); - chSysSwitchI(currp, otp); -} -#endif /* !defined(PORT_OPTIMIZED_DORESCHEDULEI) */ - /** * @brief Performs a reschedule if a higher priority thread is runnable. * @details If a thread with a higher priority than the current thread is in @@ -271,24 +245,25 @@ void chSchRescheduleS(void) { chDbgCheckClassS(); if (chSchIsRescRequiredI()) - chSchDoRescheduleI(); + chSchDoReschedule(); } #endif /* !defined(PORT_OPTIMIZED_RESCHEDULES) */ /** - * @brief Evaluates if a reschedule is required. + * @brief Evaluates if preemption 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. + * @note Not a user function, it is meant to be invoked by the scheduler + * itself or from within the port layer. * - * @retval TRUE if there is a thread that should go in running state. - * @retval FALSE if a reschedule is not required. + * @retval TRUE if there is a thread that must go in running state + * immediately. + * @retval FALSE if preemption is not required. * - * @iclass + * @special */ -#if !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI) || defined(__DOXYGEN__) -bool_t chSchIsRescRequiredExI(void) { +#if !defined(PORT_OPTIMIZED_ISPREEMPTIONREQUIRED) || defined(__DOXYGEN__) +bool_t chSchIsPreemptionRequired(void) { tprio_t p1 = firstprio(&rlist.r_queue); tprio_t p2 = currp->p_prio; #if CH_TIME_QUANTUM > 0 @@ -303,6 +278,29 @@ bool_t chSchIsRescRequiredExI(void) { return p1 > p2; #endif } -#endif /* !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI) */ +#endif /* !defined(PORT_OPTIMIZED_ISPREEMPTIONREQUIRED) */ + +/** + * @brief Switches to the first thread on the runnable queue. + * @note Not a user function, it is meant to be invoked by the scheduler + * itself or from within the port layer. + * + * @special + */ +#if !defined(PORT_OPTIMIZED_DORESCHEDULE) || defined(__DOXYGEN__) +void chSchDoReschedule(void) { + Thread *otp; + +#if CH_TIME_QUANTUM > 0 + rlist.r_preempt = CH_TIME_QUANTUM; +#endif + otp = currp; + /* Picks the first thread from the ready queue and makes it current.*/ + setcurrp(fifo_remove(&rlist.r_queue)); + currp->p_state = THD_STATE_CURRENT; + chSchReadyI(otp); + chSysSwitch(currp, otp); +} +#endif /* !defined(PORT_OPTIMIZED_DORESCHEDULE) */ /** @} */ -- cgit v1.2.3