From a99c5b516dd6d065a803e63747592b12f2ee9597 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 4 Mar 2012 17:58:19 +0000 Subject: distribute --- kernel/kernel.c | 149 +++++++++++++++++++++++++------------------------------- 1 file 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; } -- cgit v1.2.3