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.
|
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
|
||||||
|
|
|
@ -66,7 +66,8 @@ void chSysInit(void) {
|
||||||
*/
|
*/
|
||||||
void chSysTimerHandlerI(void) {
|
void chSysTimerHandlerI(void) {
|
||||||
|
|
||||||
rlist.r_preempt--;
|
if (rlist.r_preempt > 0)
|
||||||
|
rlist.r_preempt--;
|
||||||
#ifdef CH_USE_SYSTEMTIME
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
rlist.r_stime++;
|
rlist.r_stime++;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
||||||
|
|
34
src/chmtx.c
34
src/chmtx.c
|
@ -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)
|
currp->p_prio = newprio;
|
||||||
chSchWakeupS(tp, RDY_OK);
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/chschd.c
21
src/chschd.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue