aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2012-06-30 14:54:42 +0000
committerDimitri Sokolyuk <demon@dim13.org>2012-06-30 14:54:42 +0000
commit9356a5c8c67c62d0c308db0a325a3c8762e92801 (patch)
tree4f33e9f150262dea45661adc17c0580e38b57f5a /kernel
parent3c8bee15d6fdc43c270972c66ccc029624752ab9 (diff)
merge overflow and task switch: saves stack and cycles
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kernel.c61
1 files changed, 30 insertions, 31 deletions
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 48be5fe..1f79e52 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -37,6 +37,7 @@
#define SPAN(from, to) ((int32_t)((to) - (from)))
#define SLICE MSEC(1)
#define TIMEOUT WDTO_500MS
+#define swtch TIMER1_COMPB_vect
struct task {
uint32_t release; /* release time */
@@ -66,28 +67,6 @@ struct kern {
uint8_t reboot;
} kern;
-NAKED(swtch)
-{
- struct queue *rq;
-
- pusha();
-
- /* pick hightes rq, cannot fail */
- for (rq = kern.rq; TAILQ_EMPTY(rq); rq++)
- ;
-
- /* switch context */
- kern.cur->sp = SP;
- kern.cur = TAILQ_FIRST(rq);
- SP = kern.cur->sp;
-
- /* set task slice timeout */
- OCR1B = TCNT1 + SLICE;
-
- popa();
- ret();
-}
-
ISR(TIMER1_OVF_vect)
{
if (!kern.reboot)
@@ -119,17 +98,37 @@ ISR(TIMER1_COMPA_vect)
OCR1A = TCNT1 + SPAN(now, tp->release);
}
-ISR(TIMER1_COMPB_vect)
+ISR(TIMER1_COMPB_vect, ISR_NAKED)
{
- /* reschedule current task if it've used its time slice */
- TAILQ_REMOVE(kern.cur->rq, kern.cur, r_link);
- /* lower priority */
- if (kern.cur->prio < Low)
- kern.cur->prio++;
- kern.cur->rq = &kern.rq[kern.cur->prio];
- TAILQ_INSERT_TAIL(kern.cur->rq, kern.cur, r_link);
+ struct queue *rq;
- swtch();
+ pusha();
+
+ if (kern.cur == TAILQ_FIRST(kern.cur->rq)) {
+ /* reschedule current task if it've used its time slice */
+ TAILQ_REMOVE(kern.cur->rq, kern.cur, r_link);
+ /* lower priority */
+ if (kern.cur->prio < Low)
+ kern.cur->prio++;
+ kern.cur->rq = &kern.rq[kern.cur->prio];
+ TAILQ_INSERT_TAIL(kern.cur->rq, kern.cur, r_link);
+ }
+
+ /* pick hightes rq, cannot fail */
+ for (rq = kern.rq; TAILQ_EMPTY(rq); rq++)
+ ;
+
+ /* switch context */
+ kern.cur->sp = SP;
+ kern.cur = TAILQ_FIRST(rq);
+ SP = kern.cur->sp;
+
+ /* set task slice timeout */
+ OCR1B = TCNT1 + SLICE;
+
+ popa();
+
+ reti();
}
void