From a8eedf7b32b38fa1ab2c7ce8e7c6ec95be479e82 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 23 Dec 2011 11:44:26 +0000 Subject: add task priorities --- kernel/dmx.c | 10 ++++++--- kernel/kernel.c | 69 +++++++++++++++++++++++++++++++++++++++------------------ kernel/kernel.h | 2 -- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/kernel/dmx.c b/kernel/dmx.c index 51a723a..3d9a51e 100644 --- a/kernel/dmx.c +++ b/kernel/dmx.c @@ -43,12 +43,16 @@ main() init(STACK); init_uart(); +#define LOW 0 +#define MID 0 +#define HIGH 0 + #if 1 exec(heartbeat, STACK, 0, LOW); #endif #if 1 - exec(rgb, STACK + 16, &rgbargs, LOW); + exec(rgb, STACK + 16, &rgbargs, MID); exec(pwm, STACK, &pwmargs[0], HIGH); exec(pwm, STACK, &pwmargs[1], HIGH); exec(pwm, STACK, &pwmargs[2], HIGH); @@ -61,11 +65,11 @@ main() #endif #if 0 - exec(cmd, STACK, &rgbargs, LOW); + exec(cmd, STACK, &rgbargs, 0); #endif #if 0 - exec(ppm, STACK, &ppmarg, LOW); + exec(ppm, STACK, &ppmarg, 0); #endif for (;;) diff --git a/kernel/kernel.c b/kernel/kernel.c index d950124..cab3853 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -27,7 +27,8 @@ #include "stack.h" #include "queue.h" -#define DEBUG 0 +#define DEBUG 1 +#define NPRIO 4 enum State { TERMINATED, RUNQ, TIMEQ, WAITQ }; @@ -48,8 +49,9 @@ struct task { }; struct kernel { - SIMPLEQ_HEAD(, task) runq; + SIMPLEQ_HEAD(, task) runq[NPRIO]; struct task *last; /* last allocated task */ + struct task *current; struct task task[TASKS + 1]; uint32_t lasthit; uint16_t cycles; @@ -68,6 +70,7 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED) int32_t dist; uint32_t now; uint16_t nexthit; + uint8_t prio; /* save context */ PUSH_ALL(); @@ -79,15 +82,34 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED) #endif /* save stack pointer */ - tp = SIMPLEQ_FIRST(&kernel.runq); + tp = kernel.current; tp->sp = SP; + +#if 0 + /* involuntary switch, reduce prio */ + switch (tp->state) { + case RUNQ: /* involuntay, reduce prio */ + if (tp->prio > 0) + --(tp->prio); + break; + case TIMEQ: /* voluntary, rise prio */ + if (tp->prio < (NPRIO - 1)) + ++(tp->prio); + break; + default: + break; + } +#endif + tp->state = TIMEQ; tp->time += DISTANCE(kernel.lasthit, now); + /* drop current task from run-queue */ - SIMPLEQ_REMOVE_HEAD(&kernel.runq, link); + SIMPLEQ_REMOVE_HEAD(&kernel.runq[tp->prio], link); kernel.lasthit = now; nexthit = 0xffff; + prio = 0; /* walk through tasks and assemble run-queue */ for (tp = &kernel.task[1]; tp <= kernel.last; tp++) { @@ -96,20 +118,20 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED) dist = DISTANCE(now, tp->release); if (dist <= 0) { tp->state = RUNQ; - if (tp->prio == HIGH) - SIMPLEQ_INSERT_HEAD(&kernel.runq, tp, link); - else - SIMPLEQ_INSERT_TAIL(&kernel.runq, tp, link); + if (tp->prio > prio) + prio = tp->prio; + SIMPLEQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link); } else if (dist < nexthit) nexthit = dist; } - /* idle if empty */ - if (SIMPLEQ_EMPTY(&kernel.runq)) - SIMPLEQ_INSERT_HEAD(&kernel.runq, &kernel.task[0], link); + /* idle if all queues empty */ + if (!prio && SIMPLEQ_EMPTY(kernel.runq)) + SIMPLEQ_INSERT_HEAD(kernel.runq, kernel.task, link); /* restore stack pointer */ - SP = SIMPLEQ_FIRST(&kernel.runq)->sp; + kernel.current = SIMPLEQ_FIRST(&kernel.runq[prio]); + SP = kernel.current->sp; OCR1A = (uint16_t)(now + nexthit); @@ -121,6 +143,8 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED) void init(uint8_t stack) { + uint8_t prio; + cli(); /* Set up timer 1 */ @@ -134,17 +158,18 @@ init(uint8_t stack) DDRB |= _BV(PB1); /* DEBUG */ #endif - SIMPLEQ_INIT(&kernel.runq); + for (prio = 0; prio < NPRIO; prio++) + SIMPLEQ_INIT(&kernel.runq[prio]); kernel.lasthit = 0; kernel.cycles = 0; kernel.freemem = (void *)(RAMEND - stack); + kernel.task->release = 0; + kernel.task->prio = 0; + kernel.task->state = RUNQ; kernel.last = kernel.task; - kernel.last->release = 0; - kernel.last->prio = 0; - kernel.last->state = RUNQ; - - SIMPLEQ_INSERT_HEAD(&kernel.runq, kernel.last, link); + kernel.current = kernel.task; + SIMPLEQ_INSERT_HEAD(kernel.runq, kernel.task, link); sei(); } @@ -176,6 +201,8 @@ exec(void (*fun)(void *), uint8_t stack, void *args, uint8_t prio) t = ++kernel.last; t->release = NOW(kernel.cycles, TCNT1); + if (prio >= NPRIO) + prio = NPRIO - 1; t->prio = prio; t->state = TIMEQ; @@ -241,7 +268,7 @@ sleep(uint32_t ticks) cli(); - tp = SIMPLEQ_FIRST(&kernel.runq); + tp = kernel.current; tp->release += ticks; tp->time = 0; tp->state = TIMEQ; @@ -260,12 +287,12 @@ suspend(void) { cli(); - SIMPLEQ_FIRST(&kernel.runq)->state = TERMINATED; + kernel.current = TERMINATED; SCHEDULE(); } uint8_t running(void) { - return SIMPLEQ_FIRST(&kernel.runq) - &kernel.task[0]; + return kernel.current - kernel.task; } diff --git a/kernel/kernel.h b/kernel/kernel.h index 84c0f39..3e58917 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -89,8 +89,6 @@ #define SEC1(T) ((uint32_t)(T) * ((F_CPU / 10) / PRESCALE)) #define SEC0(T) ((uint32_t)(T) * ((F_CPU / 1) / PRESCALE)) -enum Prio { LOW, HIGH }; - /* __BEGIN_DECLS */ void init(uint8_t stack); -- cgit v1.2.3