aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2011-12-23 11:44:26 +0000
committerDimitri Sokolyuk <demon@dim13.org>2011-12-23 11:44:26 +0000
commita8eedf7b32b38fa1ab2c7ce8e7c6ec95be479e82 (patch)
tree5298ce6588ee903accc18c8f4a69d115f5c17071
parentaeec53f9a3f6a431676489df5e60f3b1f16efb9a (diff)
add task priorities
-rw-r--r--kernel/dmx.c10
-rw-r--r--kernel/kernel.c69
-rw-r--r--kernel/kernel.h2
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);