void _arch_irq_task_switch(void * _cpu_state) { if(run_queue) { spinlock_lock(&run_queue->spinlock); get_system_time(&run_queue->sched_time); struct kthread * c = run_queue_current(); struct kthread * n = run_queue_next(); spinlock_unlock(&run_queue->spinlock); _BUG_ON(!n); _BUG_ON(!c); if(stack_check(&(c->stack))<0) _BUG(); // TASK WE JUST PUT TO SLEEP BLEW ITS STACK! _switch(c,n,_cpu_state); // schedule next switch. _sched_next_task(NULL); } }
/** * @brief Best effort (BE) scheduler (callback). * * @return Best effort task id. * * The algorithm is Round Robin. * - Take a task from the run queue, copy its entry and put it back at the tail of the run queue. * - If the task is in the blocked state (it may be simply blocked or waiting in a semaphore), it is * put back at the tail of the run queue and the next task is picked up. * - So, if all tasks are blocked, at least the idle task can execute (it is never * blocked, at least it is what we hope!). * - Tasks in the blocked state are never removed from the run queue (they are * ignored), although they may be in another queue waiting for a resource. */ int32_t sched_rr(void) { if (hf_queue_count(krnl_run_queue) == 0) panic(PANIC_NO_TASKS_RUN); do { run_queue_next(); } while (krnl_task->state == TASK_BLOCKED); krnl_task->bgjobs++; return krnl_task->id; }
/** * @brief Best effort (BE) scheduler (callback). * * @return Best effort task id. * * The algorithm is priority based Round Robin. * - Take the first task and put it at the end of the run queue (to advance the queue and avoid deadlocks) * - Perform a run in the queue, searching for the task with the highest priority (non blocked, lowest remaining priority) * - While we are at it, check if there is a critical task. If so, schedule it, and get out. * - Perform another run in the queue, updating the remaining priorities of all tasks by subtracting the priority * of the task with the lowest remaining priority (task with the highest priority) from the remaining priority of * all other tasks. */ int32_t sched_priorityrr(void) { int32_t i, k; uint8_t highestp = 255; struct tcb_entry *krnl_task2 = NULL; k = hf_queue_count(krnl_run_queue); if (k == 0) panic(PANIC_NO_TASKS_RUN); /* advance the queue to prevent deadlocks */ run_queue_next(); /* search for the highest priority task */ for (i = 0; i < k; i++){ run_queue_next(); /* critical event, bypass the queue */ if (krnl_task->critical && krnl_task->state != TASK_BLOCKED){ krnl_task->critical = 0; goto done; } if (highestp > krnl_task->priority_rem && krnl_task->state != TASK_BLOCKED){ highestp = krnl_task->priority_rem; krnl_task2 = krnl_task; } } /* update priorities of all tasks */ for (i = 0; i < k; i++){ run_queue_next(); if (krnl_task != krnl_task2) krnl_task->priority_rem -= krnl_task2->priority_rem; } krnl_task = krnl_task2; krnl_task->priority_rem = krnl_task->priority; done: krnl_task->bgjobs++; return krnl_task->id; }
/** * @brief Best effort (BE) scheduler (callback). * * @return Best effort task id. * * The algorithm is Lottery Scheduling. * - Take a task from the run queue, copy its entry and put it back at the tail of the run queue. * - If the task is in the blocked state (it may be simply blocked or waiting in a semaphore) or * its not the ticket, it is put back at the tail of the run queue and the next task is picked up. */ int32_t sched_lottery(void) { int32_t r, i = 0; r = random() % krnl_tasks; if (hf_queue_count(krnl_run_queue) == 0) panic(PANIC_NO_TASKS_RUN); do { run_queue_next(); } while ((krnl_task->state == TASK_BLOCKED) || ((i++ % krnl_tasks) != r)); krnl_task->bgjobs++; return krnl_task->id; }