git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@155 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
6c8aadd17a
commit
cf3378588c
|
@ -50,9 +50,14 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet.
|
|||
various mechanisms and the correct use cases.
|
||||
- RT Semaphores subsystem removed, the Mutexes implements a better solution
|
||||
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
|
||||
chSchWakeupS() function source. The benchmark suite reports a 6% increase
|
||||
in the context switch performance.
|
||||
chSchWakeupS() function source. This change makes the ready list insertion
|
||||
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.
|
||||
- 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
|
||||
|
|
|
@ -66,7 +66,8 @@ void chSysInit(void) {
|
|||
*/
|
||||
void chSysTimerHandlerI(void) {
|
||||
|
||||
rlist.r_preempt--;
|
||||
if (rlist.r_preempt > 0)
|
||||
rlist.r_preempt--;
|
||||
#ifdef CH_USE_SYSTEMTIME
|
||||
rlist.r_stime++;
|
||||
#endif
|
||||
|
|
|
@ -18,12 +18,29 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Messages
|
||||
* @addtogroup Threads
|
||||
* @{
|
||||
*/
|
||||
#include <ch.h>
|
||||
|
||||
#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.
|
||||
* @param tp the pointer to the thread to be inserted in the list
|
||||
|
|
34
src/chmtx.c
34
src/chmtx.c
|
@ -36,25 +36,6 @@ void chMtxInit(Mutex *mp) {
|
|||
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.
|
||||
* @param mp pointer to the \p Mutex structure
|
||||
|
@ -86,7 +67,7 @@ void chMtxLockS(Mutex *mp) {
|
|||
tp->p_prio = currp->p_prio;
|
||||
switch (tp->p_state) {
|
||||
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;
|
||||
continue;
|
||||
case PRREADY:
|
||||
|
@ -97,7 +78,7 @@ void chMtxLockS(Mutex *mp) {
|
|||
/*
|
||||
* Goes to sleep on the mutex.
|
||||
*/
|
||||
prio_enq(currp, &mp->m_queue);
|
||||
prio_insert(currp, &mp->m_queue);
|
||||
currp->p_mtxp = mp;
|
||||
chSchGoSleepS(PRWTMTX);
|
||||
chDbgAssert(mp->m_owner == NULL, "chmtx.c, chMtxLockS()");
|
||||
|
@ -189,15 +170,8 @@ void chMtxUnlockS(void) {
|
|||
newprio = mp->m_queue.p_next->p_prio;
|
||||
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;
|
||||
chSchReadyI(tp, RDY_OK);
|
||||
chSchRescheduleS();
|
||||
}
|
||||
currp->p_prio = newprio;
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
src/chschd.c
21
src/chschd.c
|
@ -35,7 +35,7 @@ ReadyList rlist;
|
|||
void chSchInit(void) {
|
||||
|
||||
fifo_init(&rlist.r_queue);
|
||||
rlist.r_prio = ABSPRIO;
|
||||
// rlist.r_prio = ABSPRIO;
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
#ifdef CH_USE_SYSTEMTIME
|
||||
rlist.r_stime = 0;
|
||||
|
@ -58,15 +58,10 @@ INLINE void chSchReadyI(Thread *tp, t_msg msg) {
|
|||
#else
|
||||
void chSchReadyI(Thread *tp, t_msg msg) {
|
||||
#endif
|
||||
Thread *cp = rlist.r_queue.p_prev;
|
||||
|
||||
tp->p_state = PRREADY;
|
||||
tp->p_rdymsg = msg;
|
||||
while (cp->p_prio < tp->p_prio)
|
||||
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;
|
||||
prio_insert(tp, &rlist.r_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,8 +99,6 @@ void chSchGoSleepS(t_tstate newstate) {
|
|||
* @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.
|
||||
* @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) {
|
||||
|
||||
|
@ -113,15 +106,13 @@ void chSchWakeupS(Thread *ntp, t_msg msg) {
|
|||
chSchReadyI(ntp, msg);
|
||||
else {
|
||||
Thread *otp = currp;
|
||||
/* Optimization, assumes that the invoking thread has the highest priority
|
||||
which is always true unless the priority was willingly changed.
|
||||
This assumption allows us to place the thread always on top of the
|
||||
ready list without have to scan it, free lunch.*/
|
||||
/* Note, does a prio_insert() instead of a chSchReadyI() because of the
|
||||
relative priority between the two threads, prio_insert() scans the
|
||||
list starting from the highest priority end downward.*/
|
||||
/* chSchReadyI(otp, RDY_OK);*/
|
||||
otp->p_state = PRREADY;
|
||||
otp->p_rdymsg = RDY_OK;
|
||||
otp->p_next = (otp->p_prev = (Thread *)&rlist.r_queue)->p_next;
|
||||
otp->p_next->p_prev = rlist.r_queue.p_next = otp;
|
||||
prio_insert(otp, &rlist.r_queue);
|
||||
(currp = ntp)->p_state = PRCURR;
|
||||
ntp->p_rdymsg = msg;
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
* this is true for GCC, not sure about other compilers.
|
||||
*/
|
||||
#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) {
|
||||
|
||||
tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct {
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void prio_insert(Thread *tp, ThreadsQueue *tqp);
|
||||
void fifo_insert(Thread *tp, ThreadsQueue *tqp);
|
||||
Thread *fifo_remove(ThreadsQueue *tqp);
|
||||
Thread *dequeue(Thread *tp);
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
*/
|
||||
typedef struct {
|
||||
ThreadsQueue r_queue;
|
||||
t_prio r_prio;
|
||||
t_cnt r_preempt;
|
||||
#ifndef CH_CURRP_REGISTER_CACHE
|
||||
Thread *r_current;
|
||||
|
|
Loading…
Reference in New Issue