git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@155 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2007-12-22 11:34:39 +00:00
parent 6c8aadd17a
commit cf3378588c
8 changed files with 48 additions and 50 deletions

View File

@ -50,9 +50,14 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet.
various mechanisms and the correct use cases. various mechanisms and the correct use cases.
- RT Semaphores subsystem removed, the Mutexes implements a better solution - RT Semaphores subsystem removed, the Mutexes implements a better solution
for the same problem. for the same problem.
- Fixed a bug in the round robin scheduling mode, see the bug tracker for
details and a fix for previous versions.
- More performance improvements to the scheduler, see the remarks into the - More performance improvements to the scheduler, see the remarks into the
chSchWakeupS() function source. The benchmark suite reports a 6% increase chSchWakeupS() function source. This change makes the ready list insertion
in the context switch performance. time in many cases constant (not influenced by the number of ready threads).
The worst case is always proportional to the number of threads in the ready
list but the normal case is much more often constant than linear. See the
new benchmarks added to the test suite.
- Added mutexes test cases and new benchmarks to the test suite. - Added mutexes test cases and new benchmarks to the test suite.
- Modified the test suite in order to have each test case to have the same - Modified the test suite in order to have each test case to have the same
alignment enforced on functions. This is done to reduce MAM/Cache alignment alignment enforced on functions. This is done to reduce MAM/Cache alignment

View File

@ -66,6 +66,7 @@ void chSysInit(void) {
*/ */
void chSysTimerHandlerI(void) { void chSysTimerHandlerI(void) {
if (rlist.r_preempt > 0)
rlist.r_preempt--; rlist.r_preempt--;
#ifdef CH_USE_SYSTEMTIME #ifdef CH_USE_SYSTEMTIME
rlist.r_stime++; rlist.r_stime++;

View File

@ -18,12 +18,29 @@
*/ */
/** /**
* @addtogroup Messages * @addtogroup Threads
* @{ * @{
*/ */
#include <ch.h> #include <ch.h>
#ifndef CH_OPTIMIZE_SPEED #ifndef CH_OPTIMIZE_SPEED
/*
* Inserts a thread into a priority ordered queue.
* @param tp the pointer to the thread to be inserted in the list
* @param tqp the pointer to the threads list header
* @note the insertion is done by scanning the list from the highest priority
* toward the lowest
*/
void prio_insert(Thread *tp, ThreadsQueue *tqp) {
Thread *cp = tqp->p_next;
while ((cp != (Thread *)tqp) && (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;
}
/* /*
* Inserts a thread into a FIFO queue. * Inserts a thread into a FIFO queue.
* @param tp the pointer to the thread to be inserted in the list * @param tp the pointer to the thread to be inserted in the list

View File

@ -36,25 +36,6 @@ void chMtxInit(Mutex *mp) {
mp->m_owner = NULL; mp->m_owner = NULL;
} }
/*
* Inserts a thread into a list ordering it by priority.
* @param tp the pointer to the thread to be inserted in the list
* @param tqp the pointer to the threads list header
*/
#ifdef CH_OPTIMIZE_SPEED
static INLINE void prio_enq(Thread *tp, ThreadsQueue *tqp) {
#else
static void prio_enq(Thread *tp, ThreadsQueue *tqp) {
#endif
Thread *cp = tqp->p_next;
while ((cp != (Thread *)tqp) && (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;
}
/** /**
* Locks the specified mutex. * Locks the specified mutex.
* @param mp pointer to the \p Mutex structure * @param mp pointer to the \p Mutex structure
@ -86,7 +67,7 @@ void chMtxLockS(Mutex *mp) {
tp->p_prio = currp->p_prio; tp->p_prio = currp->p_prio;
switch (tp->p_state) { switch (tp->p_state) {
case PRWTMTX: case PRWTMTX:
prio_enq(dequeue(tp), &tp->p_mtxp->m_queue); prio_insert(dequeue(tp), &tp->p_mtxp->m_queue);
tp = tp->p_mtxp->m_owner; tp = tp->p_mtxp->m_owner;
continue; continue;
case PRREADY: case PRREADY:
@ -97,7 +78,7 @@ void chMtxLockS(Mutex *mp) {
/* /*
* Goes to sleep on the mutex. * Goes to sleep on the mutex.
*/ */
prio_enq(currp, &mp->m_queue); prio_insert(currp, &mp->m_queue);
currp->p_mtxp = mp; currp->p_mtxp = mp;
chSchGoSleepS(PRWTMTX); chSchGoSleepS(PRWTMTX);
chDbgAssert(mp->m_owner == NULL, "chmtx.c, chMtxLockS()"); chDbgAssert(mp->m_owner == NULL, "chmtx.c, chMtxLockS()");
@ -189,15 +170,8 @@ void chMtxUnlockS(void) {
newprio = mp->m_queue.p_next->p_prio; newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next; mp = mp->m_next;
} }
if (currp->p_prio == newprio)
chSchWakeupS(tp, RDY_OK);
else {
/* Note, changing priority and use chSchWakeupS() is wrong because the
internal optimization, see the chSchWakeupS() notes.*/
currp->p_prio = newprio; currp->p_prio = newprio;
chSchReadyI(tp, RDY_OK); chSchWakeupS(tp, RDY_OK);
chSchRescheduleS();
}
} }
} }

View File

@ -35,7 +35,7 @@ ReadyList rlist;
void chSchInit(void) { void chSchInit(void) {
fifo_init(&rlist.r_queue); fifo_init(&rlist.r_queue);
rlist.r_prio = ABSPRIO; // rlist.r_prio = ABSPRIO;
rlist.r_preempt = CH_TIME_QUANTUM; rlist.r_preempt = CH_TIME_QUANTUM;
#ifdef CH_USE_SYSTEMTIME #ifdef CH_USE_SYSTEMTIME
rlist.r_stime = 0; rlist.r_stime = 0;
@ -58,15 +58,10 @@ INLINE void chSchReadyI(Thread *tp, t_msg msg) {
#else #else
void chSchReadyI(Thread *tp, t_msg msg) { void chSchReadyI(Thread *tp, t_msg msg) {
#endif #endif
Thread *cp = rlist.r_queue.p_prev;
tp->p_state = PRREADY; tp->p_state = PRREADY;
tp->p_rdymsg = msg; tp->p_rdymsg = msg;
while (cp->p_prio < tp->p_prio) prio_insert(tp, &rlist.r_queue);
cp = cp->p_prev;
/* Insertion on p_next.*/
tp->p_next = (tp->p_prev = cp)->p_next;
tp->p_next->p_prev = cp->p_next = tp;
} }
/** /**
@ -104,8 +99,6 @@ void chSchGoSleepS(t_tstate newstate) {
* @note The function is not meant to be used in the user code directly. * @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 * @note It is equivalent to a \p chSchReadyI() followed by a
* \p chSchRescheduleS() but much more efficient. * \p chSchRescheduleS() but much more efficient.
* @note The function assumes that the invoking thread is the highest priority
* thread, so you can't use it to change priority and reschedule.
*/ */
void chSchWakeupS(Thread *ntp, t_msg msg) { void chSchWakeupS(Thread *ntp, t_msg msg) {
@ -113,15 +106,13 @@ void chSchWakeupS(Thread *ntp, t_msg msg) {
chSchReadyI(ntp, msg); chSchReadyI(ntp, msg);
else { else {
Thread *otp = currp; Thread *otp = currp;
/* Optimization, assumes that the invoking thread has the highest priority /* Note, does a prio_insert() instead of a chSchReadyI() because of the
which is always true unless the priority was willingly changed. relative priority between the two threads, prio_insert() scans the
This assumption allows us to place the thread always on top of the list starting from the highest priority end downward.*/
ready list without have to scan it, free lunch.*/
/* chSchReadyI(otp, RDY_OK);*/ /* chSchReadyI(otp, RDY_OK);*/
otp->p_state = PRREADY; otp->p_state = PRREADY;
otp->p_rdymsg = RDY_OK; otp->p_rdymsg = RDY_OK;
otp->p_next = (otp->p_prev = (Thread *)&rlist.r_queue)->p_next; prio_insert(otp, &rlist.r_queue);
otp->p_next->p_prev = rlist.r_queue.p_next = otp;
(currp = ntp)->p_state = PRCURR; (currp = ntp)->p_state = PRCURR;
ntp->p_rdymsg = msg; ntp->p_rdymsg = msg;
rlist.r_preempt = CH_TIME_QUANTUM; rlist.r_preempt = CH_TIME_QUANTUM;

View File

@ -26,6 +26,16 @@
* this is true for GCC, not sure about other compilers. * this is true for GCC, not sure about other compilers.
*/ */
#ifdef CH_OPTIMIZE_SPEED #ifdef CH_OPTIMIZE_SPEED
static INLINE void prio_insert(Thread *tp, ThreadsQueue *tqp) {
Thread *cp = tqp->p_next;
while ((cp != (Thread *)tqp) && (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;
}
static INLINE void fifo_insert(Thread *tp, ThreadsQueue *tqp) { static INLINE void fifo_insert(Thread *tp, ThreadsQueue *tqp) {
tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev; tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;

View File

@ -59,6 +59,7 @@ typedef struct {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void prio_insert(Thread *tp, ThreadsQueue *tqp);
void fifo_insert(Thread *tp, ThreadsQueue *tqp); void fifo_insert(Thread *tp, ThreadsQueue *tqp);
Thread *fifo_remove(ThreadsQueue *tqp); Thread *fifo_remove(ThreadsQueue *tqp);
Thread *dequeue(Thread *tp); Thread *dequeue(Thread *tp);

View File

@ -39,7 +39,6 @@
*/ */
typedef struct { typedef struct {
ThreadsQueue r_queue; ThreadsQueue r_queue;
t_prio r_prio;
t_cnt r_preempt; t_cnt r_preempt;
#ifndef CH_CURRP_REGISTER_CACHE #ifndef CH_CURRP_REGISTER_CACHE
Thread *r_current; Thread *r_current;