#include #include #include "task.h" #include "kernel.h" #include "scheduler.h" #include "zv_time.h" static bool __zv_scheduler_event_ready( zv_kernel_t *, zv_task_t *target ) { zv_event_t *event = &target->event; if (event->type == ZV_EVENT_OBJECT || event->type == ZV_EVENT_DATA) { return true; } if (event->type == ZV_EVENT_TIMER) { zv_time_t current_time = zv_platform_get_time(); if (event->content.time <= current_time) { return true; } } return false; } static void __zv_scheduler_update_single_task( zv_kernel_t *self, zv_task_t *target ) { if (__zv_scheduler_event_ready(self, target)) { target->state = ZV_TASK_READY; } if (target->state == ZV_TASK_READY) { ++target->age; } } void __zv_scheduler_update_tasks(zv_kernel_t *self) { for (zv_tid_t count = 0; count < self->tasks_count; ++count) { __zv_scheduler_update_single_task(self, self->tasks + count); } } static zv_task_t * __zv_scheduler_basic(zv_kernel_t *self) { for (zv_tid_t count = 0; count < self->tasks_count; ++count) { zv_task_t *current = self->tasks + count; if (current->state == ZV_TASK_READY) { return current; } } return NULL; } static zv_task_t * __zv_scheduler_priority_strict(zv_kernel_t *self) { zv_task_t *found = NULL; for (zv_tid_t count = 0; count < self->tasks_count; ++count) { zv_task_t *current = self->tasks + count; if (current->state != ZV_TASK_READY) { continue; } if (found == NULL) { found = current; continue; } if (found->priority < current->priority) { found = current; continue; } } return found; } static zv_task_t * __zv_scheduler_priority_aging(zv_kernel_t *self) { zv_task_t *found = NULL; zv_priority_t found_priority; for (zv_tid_t count = 0; count < self->tasks_count; ++count) { zv_task_t *current = self->tasks + count; if (current->state != ZV_TASK_READY) { continue; } if (found == NULL) { found = current; found_priority = found->priority + found->age; continue; } if (found_priority < (current->priority + current->age)) { found = current; found_priority = found->priority + found->age; continue; } } return found; } zv_task_t * __zv_scheduler_find_task(zv_kernel_t *self) { switch (self->scheduler) { case ZV_SCHEDULER_BASIC: return __zv_scheduler_basic(self); case ZV_SCHEDULER_PRIORITY_STRICT: return __zv_scheduler_priority_strict(self); case ZV_SCHEDULER_PRIORITY_AGING: return __zv_scheduler_priority_aging(self); default: return NULL; } } void __zv_scheduler_run_task(zv_kernel_t *self, zv_task_t *target) { target->state = ZV_TASK_RUNNING; zv_event_t event_copy = target->event; target->event.type = ZV_EVENT_EMPTY; target->event.content.unumber = 0; zv_state_t result = target->worker( self, &event_copy, __zv_kernel_get_tid(self, target), target->param ); if (result == ZV_TASK_READY || result == ZV_TASK_RUNNING) { result = ZV_TASK_READY; } target->state = result; target->age = 0x00; }