A Small Cooperative Multitasking Kernel

Dependencies:   mbed

kernel.c

Committer:
Ivop
Date:
2011-07-24
Revision:
0:73b89fc74e9f

File content as of revision 0:73b89fc74e9f:

/* Opus Una - A Small Cooperative Multitasking Kernel in C
 *
 * Copyright (C) 2011 by Ivo van Poorten <ivop@euronet.nl>
 * This file is licensed under the terms of the GNU Lesser
 * General Public License, version 3.
 */

#include "kernel.h"
#include "timer.h"

void *ou_state;
unsigned ou_wait, ou_current_task, ou_ticks;

void ou_update_tasks(void) {
    unsigned i;
    for (i=0; i<ou_ntasks; i++)
        if (ou_tasks[i].wait)
            ou_tasks[i].wait--;
}

void ou_scheduler(void) {
    unsigned i, priority, delayed;

    for(;;) {
        ou_current_task = priority = -1U;
        delayed = 0;
        for (i=0; i<ou_ntasks; i++) {
            if (ou_tasks[i].wait)                continue;      // task is still waiting
            if (ou_tasks[i].suspended)           continue;      // task is suspended
            if (ou_tasks[i].priority > priority) continue;      // task has lower priority

            if (ou_tasks[i].priority < priority)
                goto found_better_candidate;        // higher priority
            if (ou_tasks[i].delayed > delayed)
                goto found_better_candidate;        // equal priority, but waited longer

            ou_tasks[i].delayed++;                  // equal priority, but waited shorter
            continue;

found_better_candidate:
            if (ou_current_task != -1U)
                ou_tasks[ou_current_task].delayed++; // previous candidate is worse
            priority        = ou_tasks[i].priority;
            delayed         = ou_tasks[i].delayed;
            ou_current_task = i;
        }
        if (ou_current_task == -1U) {      // no runnable task, all are waiting or suspended
            ou_idle();
            continue;
        }

        ou_state = ou_tasks[ou_current_task].state;

        ou_tasks[ou_current_task].function();   // run!

        ou_tasks[ou_current_task].state = ou_state;     // returned values
        ou_tasks[ou_current_task].wait  = ou_wait;      // ...
    }
}