scheduler.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <stddef.h>
  2. #include <stdint.h>
  3. #include "task.h"
  4. #include "kernel.h"
  5. #include "scheduler.h"
  6. #include "zv_time.h"
  7. static bool __zv_scheduler_event_ready(
  8. zv_kernel_t *,
  9. zv_task_t *target
  10. ) {
  11. zv_event_t *event = &target->event;
  12. if (event->type == ZV_EVENT_OBJECT || event->type == ZV_EVENT_DATA) {
  13. return true;
  14. }
  15. if (event->type == ZV_EVENT_TIMER) {
  16. zv_time_t current_time = zv_platform_get_time();
  17. if (event->content.time <= current_time) {
  18. return true;
  19. }
  20. }
  21. return false;
  22. }
  23. static void __zv_scheduler_update_single_task(
  24. zv_kernel_t *self,
  25. zv_task_t *target
  26. ) {
  27. if (__zv_scheduler_event_ready(self, target)) {
  28. target->state = ZV_TASK_READY;
  29. }
  30. if (target->state == ZV_TASK_READY) {
  31. ++target->age;
  32. }
  33. }
  34. void __zv_scheduler_update_tasks(zv_kernel_t *self) {
  35. for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
  36. __zv_scheduler_update_single_task(self, self->tasks + count);
  37. }
  38. }
  39. static zv_task_t * __zv_scheduler_basic(zv_kernel_t *self) {
  40. for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
  41. zv_task_t *current = self->tasks + count;
  42. if (current->state == ZV_TASK_READY) {
  43. return current;
  44. }
  45. }
  46. return NULL;
  47. }
  48. static zv_task_t * __zv_scheduler_priority_strict(zv_kernel_t *self) {
  49. zv_task_t *found = NULL;
  50. for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
  51. zv_task_t *current = self->tasks + count;
  52. if (current->state != ZV_TASK_READY) {
  53. continue;
  54. }
  55. if (found == NULL) {
  56. found = current;
  57. continue;
  58. }
  59. if (found->priority < current->priority) {
  60. found = current;
  61. continue;
  62. }
  63. }
  64. return found;
  65. }
  66. static zv_task_t * __zv_scheduler_priority_aging(zv_kernel_t *self) {
  67. zv_task_t *found = NULL;
  68. zv_priority_t found_priority;
  69. for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
  70. zv_task_t *current = self->tasks + count;
  71. if (current->state != ZV_TASK_READY) {
  72. continue;
  73. }
  74. if (found == NULL) {
  75. found = current;
  76. found_priority = found->priority + found->age;
  77. continue;
  78. }
  79. if (found_priority < (current->priority + current->age)) {
  80. found = current;
  81. found_priority = found->priority + found->age;
  82. continue;
  83. }
  84. }
  85. return found;
  86. }
  87. zv_task_t * __zv_scheduler_find_task(zv_kernel_t *self) {
  88. switch (self->scheduler) {
  89. case ZV_SCHEDULER_BASIC:
  90. return __zv_scheduler_basic(self);
  91. case ZV_SCHEDULER_PRIORITY_STRICT:
  92. return __zv_scheduler_priority_strict(self);
  93. case ZV_SCHEDULER_PRIORITY_AGING:
  94. return __zv_scheduler_priority_aging(self);
  95. default:
  96. return NULL;
  97. }
  98. }
  99. void __zv_scheduler_run_task(zv_kernel_t *self, zv_task_t *target) {
  100. target->state = ZV_TASK_RUNNING;
  101. zv_event_t event_copy = target->event;
  102. target->event.type = ZV_EVENT_EMPTY;
  103. target->event.content.unumber = 0;
  104. zv_state_t result = target->worker(
  105. self,
  106. &event_copy,
  107. __zv_kernel_get_tid(self, target),
  108. target->param
  109. );
  110. if (result == ZV_TASK_READY || result == ZV_TASK_RUNNING) {
  111. result = ZV_TASK_READY;
  112. }
  113. target->state = result;
  114. target->age = 0x00;
  115. }