aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2012-03-04 17:58:19 +0000
committerDimitri Sokolyuk <demon@dim13.org>2012-03-04 17:58:19 +0000
commita99c5b516dd6d065a803e63747592b12f2ee9597 (patch)
tree840617cf7438106afae83cfab0708b5ebc0a2312
parent9619334634b1921a4f3af220adbd7feea85e2c02 (diff)
distribute
-rw-r--r--kernel/kernel.c149
1 files changed, 67 insertions, 82 deletions
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 8ef32b9..ecb9e59 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -41,27 +41,20 @@ enum State { TERMINATED, RUNQ, TIMEQ, WAITQ, SIGNAL };
struct task {
uint32_t release;
uint16_t sp; /* stack pointer */
- uint8_t state;
uint8_t chan; /* wait channel */
- TAILQ_ENTRY(task) link;
+ TAILQ_ENTRY(task) r_link, t_link, w_link;
};
struct kernel {
TAILQ_HEAD(queue, task) runq, timeq, waitq;
- struct task task[1 + TASKS];
+ struct task idle[1 + TASKS];
struct task *nextfree;
+ struct task *current;
uint16_t cycles;
uint8_t *freemem;
uint8_t semaphore;
} kernel;
-void
-setrq(struct task *tp)
-{
- tp->state = RUNQ;
- TAILQ_INSERT_TAIL(&kernel.runq, tp, link);
-}
-
ISR(TIMER1_OVF_vect)
{
++kernel.cycles;
@@ -69,7 +62,7 @@ ISR(TIMER1_OVF_vect)
ISR(TIMER1_COMPA_vect, ISR_NAKED)
{
- struct task *tp, *tmp, *cur;
+ struct task *tp, *tmp;
uint32_t now;
uint16_t nexthit;
int32_t dist;
@@ -81,70 +74,24 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
PORTB ^= _BV(PB1); /* DEBUG */
#endif
- cur = TAILQ_FIRST(&kernel.runq);
- TAILQ_REMOVE(&kernel.runq, cur, link);
+ if (kernel.current == TAILQ_FIRST(&kernel.runq)) {
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
+ if (kernel.current != kernel.idle)
+ TAILQ_INSERT_TAIL(&kernel.timeq, kernel.current, t_link);
+ }
/* release waiting tasks */
- TAILQ_FOREACH_SAFE(tp, &kernel.timeq, link, tmp) {
+ TAILQ_FOREACH_SAFE(tp, &kernel.timeq, t_link, tmp) {
if (DISTANCE(now, tp->release) <= 0) {
- TAILQ_REMOVE(&kernel.timeq, tp, link);
- setrq(tp);
+ TAILQ_REMOVE(&kernel.timeq, tp, t_link);
+ TAILQ_INSERT_TAIL(&kernel.runq, tp, r_link);
} else
break;
}
- switch (cur->state) {
- case RUNQ:
- /* readd current task at the end of run queue */
- if (cur != &kernel.task[0])
- setrq(cur);
-
- break;
- case TIMEQ:
- /* find right position on time queue */
- TAILQ_FOREACH(tp, &kernel.timeq, link)
- if (DISTANCE(cur->release, tp->release) > 0)
- break;
-
- if (tp)
- TAILQ_INSERT_BEFORE(tp, cur, link);
- else
- TAILQ_INSERT_TAIL(&kernel.timeq, cur, link);
-
- break;
- case WAITQ:
- if (kernel.semaphore & _BV(cur->chan)) {
- /* semaphore busy, go into wait queue */
- TAILQ_INSERT_TAIL(&kernel.waitq, cur, link);
- } else {
- /* occupy semaphore */
- kernel.semaphore |= _BV(cur->chan);
- /* go into the end of run queue again */
- setrq(cur);
- }
-
- break;
- case SIGNAL:
- /* release waiting tasks from wait queue */
- TAILQ_FOREACH_SAFE(tp, &kernel.waitq, link, tmp) {
- if (tp->chan == cur->chan) {
- TAILQ_REMOVE(&kernel.waitq, tp, link);
- setrq(tp);
- }
- }
-
- /* clear semaphore, and go back to run queue */
- kernel.semaphore &= ~_BV(cur->chan);
- setrq(cur);
-
- break;
- default:
- break;
- }
-
/* idle if nothing to run */
if (TAILQ_EMPTY(&kernel.runq))
- setrq(&kernel.task[0]);
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.idle, r_link);
nexthit = UINT16_MAX;
@@ -157,8 +104,9 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
OCR1A = (uint16_t)(now + nexthit);
/* switch context */
- cur->sp = SP;
- SP = TAILQ_FIRST(&kernel.runq)->sp;
+ kernel.current->sp = SP;
+ kernel.current = TAILQ_FIRST(&kernel.runq);
+ SP = kernel.current->sp;
POP_ALL();
reti();
@@ -187,11 +135,11 @@ init(uint8_t stack)
TAILQ_INIT(&kernel.waitq);
kernel.cycles = 0;
- kernel.nextfree = &kernel.task[1];
+ kernel.nextfree = kernel.idle + 1;
kernel.freemem = (void *)(RAMEND - stack);
- kernel.task->state = RUNQ;
- kernel.task->release = 0;
- TAILQ_INSERT_TAIL(&kernel.runq, &kernel.task[0], link);
+ kernel.idle->release = 0;
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.idle, r_link);
+ kernel.current = TAILQ_FIRST(&kernel.runq);
sei();
}
@@ -221,11 +169,10 @@ exec(void (*fun)(void *), void *args, uint8_t stack)
memset(sp, 0, 6); /* r26-r31 */
tp = kernel.nextfree++;
- tp->release = NOW(kernel.cycles, TCNT1);
+ tp->release = 0;
tp->chan = 0;
tp->sp = (uint16_t)sp; /* SP */
- tp->state = TIMEQ;
- TAILQ_INSERT_TAIL(&kernel.timeq, tp, link);
+ TAILQ_INSERT_TAIL(&kernel.runq, tp, r_link);
SCHEDULE();
}
@@ -235,8 +182,17 @@ wait(uint8_t chan)
{
cli();
- TAILQ_FIRST(&kernel.runq)->chan = chan;
- TAILQ_FIRST(&kernel.runq)->state = WAITQ;
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
+ kernel.current->chan = chan;
+
+ if (kernel.semaphore & _BV(kernel.current->chan)) {
+ /* semaphore busy, go into wait queue */
+ TAILQ_INSERT_TAIL(&kernel.waitq, kernel.current, w_link);
+ } else {
+ /* occupy semaphore */
+ kernel.semaphore |= _BV(kernel.current->chan);
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.current, r_link);
+ }
SCHEDULE();
}
@@ -244,9 +200,23 @@ wait(uint8_t chan)
void
signal(void)
{
+ struct task *tp, *tmp;
+
cli();
- TAILQ_FIRST(&kernel.runq)->state = SIGNAL;
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
+
+ /* release waiting tasks from wait queue */
+ TAILQ_FOREACH_SAFE(tp, &kernel.waitq, w_link, tmp) {
+ if (tp->chan == kernel.current->chan) {
+ TAILQ_REMOVE(&kernel.waitq, tp, w_link);
+ TAILQ_INSERT_TAIL(&kernel.runq, tp, r_link);
+ }
+ }
+
+ /* clear semaphore, and go back to run queue */
+ kernel.semaphore &= ~_BV(kernel.current->chan);
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.current, r_link);
SCHEDULE();
}
@@ -254,10 +224,22 @@ signal(void)
void
sleep(uint32_t sec, uint32_t usec)
{
+ struct task *tp;
+
cli();
- TAILQ_FIRST(&kernel.runq)->release += SEC(sec) + USEC(usec);
- TAILQ_FIRST(&kernel.runq)->state = TIMEQ;
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
+ kernel.current->release += SEC(sec) + USEC(usec);
+
+ /* find right position on time queue */
+ TAILQ_FOREACH(tp, &kernel.timeq, t_link)
+ if (DISTANCE(kernel.current->release, tp->release) > 0)
+ break;
+
+ if (tp)
+ TAILQ_INSERT_BEFORE(tp, kernel.current, t_link);
+ else
+ TAILQ_INSERT_TAIL(&kernel.timeq, kernel.current, t_link);
SCHEDULE();
}
@@ -267,6 +249,9 @@ yield(void)
{
cli();
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
+ TAILQ_INSERT_TAIL(&kernel.timeq, kernel.current, t_link);
+
SCHEDULE();
}
@@ -275,7 +260,7 @@ suspend(void)
{
cli();
- TAILQ_FIRST(&kernel.runq)->state = TERMINATED;
+ TAILQ_REMOVE(&kernel.runq, kernel.current, r_link);
SCHEDULE();
}
@@ -289,5 +274,5 @@ now(void)
uint8_t
running(void)
{
- return TAILQ_FIRST(&kernel.runq) - kernel.task;
+ return kernel.current - kernel.idle;
}