scheduler.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include <stdio.h>
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <zivuos.h>
  6. static void __zv_scheduler_update_task(zv_task_t *target) {
  7. if (__zv_event_is_working_timer(target->event)) {
  8. __zv_time_process_timer(&target->event);
  9. }
  10. if (__zv_event_is_set(target->event)) {
  11. target->state = ZV_TASK_READY;
  12. }
  13. if (target->state == ZV_TASK_READY) {
  14. ++target->age;
  15. }
  16. }
  17. static void __zv_scheduler_run_task(zv_kernel_t *self, zv_tid_t target_tid) {
  18. zv_task_t *target = __zv_kernel_get_task(self, target_tid);
  19. zv_event_t event_copy = target->event;
  20. __zv_task_mark_running(target);
  21. __zv_task_clear_age(target);
  22. __zv_event_clear(&target->event);
  23. zv_state_t exit_state = target->worker(
  24. self,
  25. &event_copy,
  26. target_tid,
  27. target->param
  28. );
  29. if (exit_state == ZV_TASK_RUNNING) {
  30. exit_state = ZV_TASK_READY;
  31. }
  32. if (exit_state == ZV_TASK_EMPTY || exit_state == ZV_TASK_KILLED) {
  33. zv_kernel_kill_process(self, target_tid);
  34. return;
  35. }
  36. target->state = exit_state;
  37. }
  38. static zv_tid_t __zv_scheduler_select_next_task(zv_kernel_t *self) {
  39. zv_tid_t selected = ZV_TID_NULL;
  40. zv_priority_t selected_priority = 0;
  41. for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
  42. zv_task_t *current = __zv_kernel_get_task(self, count);
  43. __zv_scheduler_update_task(current);
  44. if (!__zv_task_is_ready(current)) {
  45. continue;
  46. }
  47. zv_priority_t current_priority = __zv_task_calc_priority(current);
  48. if (selected == ZV_TID_NULL || current_priority > selected_priority) {
  49. selected = count;
  50. selected_priority = current_priority;
  51. }
  52. }
  53. return selected;
  54. }
  55. bool __zv_scheduler_single_loop(zv_kernel_t *self) {
  56. zv_tid_t next_task = __zv_scheduler_select_next_task(self);
  57. if (next_task == ZV_TID_NULL) {
  58. if (!self->idle_worker(self)) {
  59. return false;
  60. }
  61. return true;
  62. }
  63. __zv_scheduler_run_task(self, next_task);
  64. return true;
  65. }