Lazuli
scheduler.c
Go to the documentation of this file.
1 /*
2  * SPDX-License-Identifier: GPL-3.0-only
3  * This file is part of Lazuli.
4  */
5 
14 #include <stdint.h>
15 
16 #include <Lazuli/common.h>
17 #include <Lazuli/config.h>
18 #include <Lazuli/lazuli.h>
19 #include <Lazuli/list.h>
20 #include <Lazuli/mutex.h>
21 
23 #include <Lazuli/sys/arch/arch.h>
24 #include <Lazuli/sys/clock_24.h>
25 #include <Lazuli/sys/compiler.h>
26 #include <Lazuli/sys/kernel.h>
27 #include <Lazuli/sys/memory.h>
28 #include <Lazuli/sys/scheduler.h>
29 
33 static Task * currentTask;
34 
40 static NOINIT Lz_LinkedList readyTasks[__LZ_SCHEDULING_POLICY_ENUM_END];
41 
50 
59 
64 
69 
74 
80 static NOINIT Task *idleTask;
81 
86  NULL ,
88  PRIORITY_RT ,
89  0 ,
90  0 ,
91  0
92 };
93 
99 static void
100 IdleTask(void)
101 {
102  for (;;) {
104  Arch_CpuSleep();
105  }
106  }
107 }
108 
115 static void
117 {
118  TaskContextLayout * const contextLayout
120  - sizeof(TaskContextLayout) + 1);
121 
122  contextLayout->pc = ReverseBytesOfFunctionPointer(task->entryPoint);
123  contextLayout->terminationCallback =
125 
126  task->stackPointer = ALLOW_ARITHM((void*)contextLayout) - 1;
127 }
128 
139 static bool
140 PeriodComparer(const Task * const task1, const Task * const task2)
141 {
142  return task1->period > task2->period;
143 }
144 
155 static bool
156 PriorityComparer(const Task * const task1, const Task * const task2)
157 {
158  return task1->priority > task2->priority;
159 }
160 
174 static void
176  Task * const taskToInsert,
177  bool (*compareByProperty)(const Task * const ,
178  const Task * const))
179 {
180  Task *task;
181 
182  /*
183  * This is commented on purpose.
184  * TODO: Find a neat way to perform the equivalent. This function is static
185  * so we master the parameters that are passed to that function.
186  * Static checking could do the job.
187  *
188  * if (NULL == list || NULL == taskToInsert || NULL == compareByProperty) {
189  * return;
190  * }
191  */
192 
193  List_ForEach (list, Task, task, stateQueue) {
194  if (compareByProperty(task, taskToInsert)) {
195  List_InsertBefore(list,
196  &task->stateQueue,
197  &taskToInsert->stateQueue);
198 
199  return;
200  }
201  }
202 
203  List_Append(list, &taskToInsert->stateQueue);
204 }
205 
216 static Task*
218 {
219  /*
220  * We can choose an uint8_t here as Lz_SchedulingPolicy has very few possible
221  * values.
222  */
223  uint8_t i;
224 
225  for (i = 0; i < ELEMENTS_COUNT(readyTasks); ++i) {
226  const Lz_LinkedListElement * const linkedListElement
227  = List_PickFirst(&readyTasks[i]);
228 
229  if (NULL != linkedListElement) {
230  return CONTAINER_OF(linkedListElement, stateQueue, Task);
231  }
232  }
233 
234  return idleTask;
235 }
236 
242 static void
244 {
245  Task *loopTask;
246  Lz_LinkedListElement *iterator;
247 
248  /* Here we update the time until activation of all cyclic RT tasks */
249  List_ForEach(&readyTasks[CYCLIC_RT], Task, loopTask, stateQueue) {
250  loopTask->timeUntilActivation--;
251 
252  if (0 == loopTask->timeUntilActivation) {
253  if (loopTask->timeUntilCompletion > 0) {
254  /* TODO: Missed deadline */
255  } else {
256  loopTask->timeUntilActivation = loopTask->period;
257  }
258  }
259  }
260 
261  /* After updating, we check if a cyclic RT task is ready to run */
262  List_RemovableForEach(&waitingActivationTasks,
263  Task,
264  loopTask,
265  stateQueue,
266  iterator) {
267  loopTask->timeUntilActivation--;
268 
269  if (0 == loopTask->timeUntilActivation) {
270  iterator = List_Remove(&waitingActivationTasks, &loopTask->stateQueue);
271  InsertTaskByPriority(&readyTasks[CYCLIC_RT], loopTask, PeriodComparer);
272 
273  loopTask->timeUntilActivation = loopTask->period;
274  loopTask->timeUntilCompletion = loopTask->completion;
275  }
276  }
277 }
278 
284 static void
286 {
287  Task *task;
288  Lz_LinkedListElement *iterator;
289 
290  List_RemovableForEach(&waitingTimerTasks, Task, task, stateQueue, iterator) {
291  --task->timeUntilTimerExpiration;
292 
293  if (0 == task->timeUntilTimerExpiration) {
294  iterator = List_Remove(&waitingTimerTasks, &task->stateQueue);
296  }
297  }
298 }
299 
303 static void
305 {
306  --currentTask->timeUntilCompletion;
307 
308  if (WAIT_ACTIVATION == currentTask->taskToSchedulerMessage ||
309  0 == currentTask->timeUntilCompletion) {
310  List_Append(&waitingActivationTasks, &currentTask->stateQueue);
311 
312  return;
313  }
314 
316 }
317 
321 static void
323 {
324  bool setCurrentTaskReady = false;
325 
326  if (WAIT_INTERRUPT == currentTask->taskToSchedulerMessage) {
327  uint8_t interruptCode =
328  *((uint8_t*)currentTask->taskToSchedulerMessageParameter);
329 
330  /*
331  * If the requested interrupt code is not an acceptable value, we abort the
332  * task.
333  */
335  (interruptCode > INT_LAST_ENTRY)) {
336  List_Append(&abortedTasks, &currentTask->stateQueue);
337 
338  return;
339  }
340 
341  List_Prepend(&waitingInterruptsTasks[interruptCode],
342  &currentTask->stateQueue);
343  } else if (WAIT_SOFTWARE_TIMER == currentTask->taskToSchedulerMessage) {
344  currentTask->timeUntilTimerExpiration =
346  if (0 == currentTask->timeUntilTimerExpiration) {
347  setCurrentTaskReady = true;
348  } else {
349  List_Append(&waitingTimerTasks, &currentTask->stateQueue);
350  }
351  } else if (LZ_CONFIG_MODULE_MUTEX_USED &&
352  (WAIT_MUTEX == currentTask->taskToSchedulerMessage)) {
353  Lz_Mutex * const mutex = currentTask->taskToSchedulerMessageParameter;
354  List_Prepend(&mutex->waitingTasks,
355  &currentTask->stateQueue);
356  } else {
357  setCurrentTaskReady = true;
358  }
359 
360  if (setCurrentTaskReady) {
362  currentTask,
364  }
365 }
366 
378 static void
379 Schedule(void)
380 {
381  /*
382  * We call this function before adding new tasks waiting for a software timer
383  * in order to avoid decrementing the expiration counter immediately after
384  * adding the task to the corresponding waiting list.
385  */
387 
388  if (currentTask != idleTask) {
389  if (TERMINATE_TASK == currentTask->taskToSchedulerMessage) {
390  List_Append(&terminatedTasks, &currentTask->stateQueue);
391  } else {
392  void (* const jumpToManager[__LZ_SCHEDULING_POLICY_ENUM_END])(void) =
393  {
396  };
397 
398  jumpToManager[currentTask->schedulingPolicy]();
399  }
400  }
401 
403 
404  currentTask->taskToSchedulerMessage = NO_MESSAGE;
405 
406  currentTask = PickTaskToRun();
407 }
408 
420 static Task *
421 CallbackRegisterUserTask(const Lz_TaskConfiguration * const taskConfiguration)
422 {
423  Task *newTask;
424  /*
425  * Jump table to the appropriate comparer, depending of the desired
426  * scheduling policy.
427  */
428  bool (* const comparers[__LZ_SCHEDULING_POLICY_ENUM_END])
429  (const Task * const,
430  const Task * const) = {
433  };
434 
435  if (taskConfiguration->schedulingPolicy >= __LZ_SCHEDULING_POLICY_ENUM_END) {
436  return NULL;
437  }
438 
439  if (CYCLIC_RT == taskConfiguration->schedulingPolicy &&
440  (0 == taskConfiguration->period || 0 == taskConfiguration->completion)) {
441  return NULL;
442  }
443 
444  newTask = KIncrementalMalloc(sizeof(Task));
445  if (NULL == newTask) {
446  return NULL;
447  }
448 
449  newTask->priority = taskConfiguration->priority;
450  newTask->period = taskConfiguration->period;
451  newTask->completion = taskConfiguration->completion;
452 
453  newTask->timeUntilActivation = newTask->period;
454  newTask->timeUntilCompletion = newTask->completion;
455 
457 
459 
460  InsertTaskByPriority(&readyTasks[taskConfiguration->schedulingPolicy],
461  newTask,
462  comparers[taskConfiguration->schedulingPolicy]);
463 
464  return newTask;
465 }
466 
473 static Task *
475 {
476  idleTask = KIncrementalMalloc(sizeof(Task));
477  if (NULL == idleTask) {
478  return NULL;
479  }
480 
482 
483  return idleTask;
484 }
485 
502 static bool
503 RegisterTask(void (* const taskEntryPoint)(void),
504  Lz_TaskConfiguration * taskConfiguration,
505  const bool isIdleTask)
506 {
507  Lz_TaskConfiguration defaultConfiguration;
508  Task *newTask;
509  void *taskStack;
510  size_t desiredStackSize;
511 
512  if (NULL == taskConfiguration) {
514  &defaultConfiguration,
515  sizeof(Lz_TaskConfiguration));
516  taskConfiguration = &defaultConfiguration;
517  } else if (taskConfiguration->stackSize < LZ_CONFIG_DEFAULT_TASK_STACK_SIZE) {
518  taskConfiguration->stackSize = LZ_CONFIG_DEFAULT_TASK_STACK_SIZE;
519  }
520 
521  if (isIdleTask) {
522  newTask = CallbackRegisterIdleTask();
523  } else {
524  newTask = CallbackRegisterUserTask(taskConfiguration);
525  }
526 
527  if (NULL == newTask) {
528  return false;
529  }
530 
531  desiredStackSize = taskConfiguration->stackSize
532  /* We add enough space to contain the context of a task on the stack */
533  + sizeof(TaskContextLayout)
534  /* Plus 1 call to save_context_on_stack (in startup.S) */
535  + sizeof(void *);
536 
537  taskStack = KIncrementalMalloc(desiredStackSize);
538  if (NULL == taskStack) {
539  return false;
540  }
541 
542  newTask->schedulingPolicy = taskConfiguration->schedulingPolicy;
543  newTask->name = taskConfiguration->name;
544  newTask->entryPoint = taskEntryPoint;
545  newTask->stackSize = desiredStackSize;
546  newTask->stackOrigin = ALLOW_ARITHM(taskStack) + desiredStackSize - 1;
547  newTask->stackPointer = newTask->stackOrigin;
548  newTask->timeUntilTimerExpiration = 0;
549 
550  PrepareTaskContext(newTask);
551 
552  return true;
553 }
554 
562 static bool
564 {
565  Lz_TaskConfiguration taskConfiguration;
566 
567  Lz_TaskConfiguration_Init(&taskConfiguration);
568 
569  taskConfiguration.stackSize = LZ_CONFIG_IDLE_TASK_STACK_SIZE;
570 
572  taskConfiguration.name = LZ_CONFIG_IDLE_TASK_NAME;
573  }
574 
575  return RegisterTask(IdleTask, &taskConfiguration, true);
576 }
577 
594 void
595 (*ReverseBytesOfFunctionPointer(void (* const pointer)(void)))(void)
596 {
597  const uint8_t maxIndex = sizeof(pointer) - 1;
598  const uint8_t * const oldPointerPointer = (const uint8_t * const)&pointer;
599  void (*newPointer)(void);
600  uint8_t * const newPointerPointer = (uint8_t * const)&newPointer;
601  uint8_t i;
602 
603  for (i = 0; i <= maxIndex; ++i) {
604  newPointerPointer[maxIndex - i] = oldPointerPointer[i];
605  }
606 
607  return newPointer;
608 }
609 
612 void
614 {
615  size_t i;
616  const Lz_LinkedList linkedListInit = LINKED_LIST_INIT;
617 
619 
620  for (i = 0; i < ELEMENTS_COUNT(readyTasks); ++i) {
621  Memory_Copy(&linkedListInit, &readyTasks[i], sizeof(linkedListInit));
622  }
623 
624  for (i = 0; i < ELEMENTS_COUNT(waitingInterruptsTasks); ++i) {
625  Memory_Copy(&linkedListInit,
627  sizeof(linkedListInit));
628  }
629 }
630 
631 void
632 Scheduler_AbortTask(void * const sp)
633 {
634  currentTask->stackPointer = sp;
635 
636  List_Append(&abortedTasks, &currentTask->stateQueue);
637 
639 
640  for(;;);
641 
642  /*
643  * TODO: we have a problem here.
644  * Here, CPU is now idle.
645  * But Schedule() doesn't run the elected task.
646  *
647  * I think one good solution is to enter idle, and wait for the next clock
648  * tick.
649  */
650 }
651 
652 /*
653  * This function is executed on the current task's stack. So go easy with stack
654  * usage.
655  */
656 void
657 Scheduler_HandleInterrupt(const uint8_t interruptCode)
658 {
659  Task *loopTask;
660  Lz_LinkedListElement *iterator;
661 
663  if (interruptCode > INT_LAST_ENTRY) {
664  Kernel_Panic();
665  }
666  }
667 
669  Task,
670  loopTask,
671  stateQueue,
672  iterator) {
673  iterator = List_Remove(&waitingInterruptsTasks[interruptCode],
674  &loopTask->stateQueue);
676  }
677 }
678 
679 void
681 {
682  currentTask->stackPointer = sp;
683 
686  }
687 
688  Schedule();
689 
691 }
692 
693 void
695 {
696  Task *loopTask;
697  Lz_LinkedListElement *iterator;
698 
699  /* TODO: Ugly */
701  UNUSED(mutex);
702  UNUSED(loopTask);
703  UNUSED(iterator);
704 
705  return;
706  }
707 
709  Task,
710  loopTask,
711  stateQueue,
712  iterator) {
713  iterator = List_Remove(&mutex->waitingTasks,
714  &loopTask->stateQueue);
716  }
717 }
718 
719 Task*
721 {
722  return currentTask;
723 }
724 
725 void
727 {
728  /*
729  * We use this do-while loop because the task can be woken up by any interrupt
730  * source. In the case of standard interrupts (i.e. not a clock tick)
731  * the task needs to sleep again after the interruption has been managed.
732  * In other words, currentTask->taskToSchedulerMessage will be equal to
733  * NO_MESSAGE only if the task's time slice has finished.
734  */
735  do {
736  Arch_CpuSleep();
737  } while (NO_MESSAGE != currentTask->taskToSchedulerMessage);
738 }
739 
745 void
747 {
748  if (NULL == taskConfiguration) {
749  return;
750  }
751 
753  taskConfiguration,
754  sizeof(Lz_TaskConfiguration));
755 }
756 
757 bool
758 Lz_RegisterTask(void (* const taskEntryPoint)(void),
759  Lz_TaskConfiguration * taskConfiguration)
760 {
761  return RegisterTask(taskEntryPoint, taskConfiguration, false);
762 }
763 
764 void
765 Lz_Run(void)
766 {
767  if (!RegisterIdleTask()) {
768  Kernel_Panic();
769  }
770 
771  currentTask = PickTaskToRun();
772 
774 
776 }
777 
778 const char *
780 {
781  return currentTask->name;
782 }
783 
784 void
786 {
788 
790 }
791 
792 void
794 {
795  /* TODO: Check if the calling task's scheduling policy is PRIORITY_RT */
796 
797  currentTask->taskToSchedulerMessageParameter = &interruptCode;
798  currentTask->taskToSchedulerMessage = WAIT_INTERRUPT;
799 
801 }
802 
803 void
805 {
806  /* TODO: Check if the calling task's scheduling policy is PRIORITY_RT */
807 
808  currentTask->taskToSchedulerMessageParameter = &units;
810 
812 }
813 
814 void
816 {
817  currentTask->taskToSchedulerMessage = TERMINATE_TASK;
818 
820 }
821 
void Scheduler_Init(void)
Initialize the scheduler prior to running it.
Definition: scheduler.c:613
#define INT_TOTAL
Total interrupt codes used.
Definition: interrupts.h:158
Task * Scheduler_GetCurrentTask(void)
Get a pointer to the current running task.
Definition: scheduler.c:720
static void ManagePriorityRealTimeTask(void)
Manage priority real-time tasks.
Definition: scheduler.c:322
char const * name
A pointer to an allocated const string containing the name to give to the task.
Definition: lazuli.h:94
Cyclic real-time scheduling.
Definition: lazuli.h:58
bool Lz_RegisterTask(void(*const taskEntryPoint)(void), Lz_TaskConfiguration *taskConfiguration)
Register a new task.
Definition: scheduler.c:758
size_t stackSize
The stack size of the task.
Definition: task.h:109
Memory management API.
#define INT_LAST_ENTRY
Alias for the last code used.
Definition: interrupts.h:153
#define WAIT_INTERRUPT
Set the task to wait for an interrupt.
Definition: task.h:52
void Lz_Task_Terminate(void)
Terminate the calling task.
Definition: scheduler.c:815
#define ALLOW_ARITHM(X)
Allow arithmetic on a void pointer.
Definition: common.h:116
volatile FuncVoidVoid pc
Program counter for the task.
Definition: task.h:304
static void IdleTask(void)
The scheduler idle task.
Definition: scheduler.c:100
static Lz_LinkedList readyTasks[__LZ_SCHEDULING_POLICY_ENUM_END]
The queues of ready tasks for each scheduling policy.
Definition: scheduler.c:40
#define TERMINATE_TASK
Terminate the task.
Definition: task.h:57
void Scheduler_HandleClockTick(void *const sp)
This function is called when a clock tick occured, catch by the interrupt handler.
Definition: scheduler.c:680
Lz_LinkedListElement stateQueue
The scheduling queue on which the task is stored.
Definition: task.h:124
void * stackPointer
The saved stack pointer of the task.
Definition: task.h:114
const bool LZ_CONFIG_IDLE_TASK_HAS_NAME
Configure if the idle task must have a name.
Kernel symbols definition.
#define CONTAINER_OF(P, M, T)
Get a pointer to the structure T containing the member M pointed by P.
Definition: common.h:263
static Lz_LinkedList terminatedTasks
The queue of terminated tasks.
Definition: scheduler.c:68
lz_u_resolution_unit_t period
The period (T) of the task.
Definition: lazuli.h:117
static const Lz_TaskConfiguration DefaultTaskConfiguration
Contains default values for Lz_TaskConfiguration.
Definition: scheduler.c:85
void Arch_EnableInterrupts(void)
Enable all interrupts.
const char * name
The name of the task.
Definition: task.h:82
void List_Prepend(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const item)
Insert an Lz_LinkedListElement as the first element of an existing Lz_LinkedList. ...
Definition: list.c:44
const bool LZ_CONFIG_MODULE_MUTEX_USED
Use module "mutex": Mutexes implementation.
void Scheduler_SleepUntilEndOfTimeSlice(void)
Put the current task to sleep until the end of its time slice.
Definition: scheduler.c:726
static bool RegisterIdleTask(void)
Register the idle task.
Definition: scheduler.c:563
void Lz_WaitTimer(lz_u_resolution_unit_t units)
Set the calling task to wait for the specified number of time resolution units (time slices)...
Definition: scheduler.c:804
const char * Lz_Task_GetName(void)
Get the name of the calling task.
Definition: scheduler.c:779
#define UNUSED(X)
Tell the compiler that the variable X is left unsed.
Definition: common.h:51
void(* entryPoint)(void)
Entry point of execution of the task.
Definition: task.h:89
void Arch_RestoreContextAndReturnFromInterrupt(void *stackPointer)
Restore the context of a previously saved task, and run it by returning from interrupt.
Include appropriate config file.
const bool LZ_CONFIG_MODULE_CLOCK_24_USED
Use module "clock_24": Implement a 24-Hour clock in the kernel.
lz_task_priority_t priority
The task priority.
Definition: task.h:154
lz_u_resolution_unit_t completion
The completion time (C) of the task (worst case execution time), expressed as an integer number of ti...
Definition: task.h:137
lz_u_resolution_unit_t timeUntilCompletion
The number of time units until the task will complete its execution.
Definition: task.h:143
lz_u_resolution_unit_t completion
The completion time (C) of the task (worst case execution time).
Definition: lazuli.h:125
void Arch_CpuSleep(void)
Put the CPU to sleep according to the sleep settings.
Definition: arch.c:60
#define WAIT_MUTEX
Wait for a mutex to be unlocked.
Definition: task.h:63
#define ELEMENTS_COUNT(X)
Get the number of elements in a statically initialized array.
Definition: common.h:278
static Task * currentTask
A pointer to the current running task.
Definition: scheduler.c:33
The public API of the Lazuli kernel.
static void InsertTaskByPriority(Lz_LinkedList *const list, Task *const taskToInsert, bool(*compareByProperty)(const Task *const, const Task *const))
Insert a task in a list, keeping priorities ordered.
Definition: scheduler.c:175
Lazuli scheduler interface.
const bool LZ_CONFIG_CHECK_INTERRUPT_CODE_OVER_LAST_ENTRY
When 1, check if the interrupt code sent by the ASM interrupt handler to the base scheduler interrupt...
Lz_LinkedListElement * List_Remove(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const itemToRemove)
Remove an element from an Lz_LinkedList.
Definition: list.c:195
size_t stackSize
The size of the stack needed by the task.
Definition: lazuli.h:99
volatile lz_task_to_scheduler_message_t taskToSchedulerMessage
The message the task has to pass to the scheduler for the next scheduling operation (i...
Definition: task.h:174
const size_t LZ_CONFIG_DEFAULT_TASK_STACK_SIZE
Default stack size in bytes for a new task.
Macro aliases on compiler facilities.
static void PrepareTaskContext(Task *const task)
Prepare the first context of the task so it will be ready when switching context for the first time (...
Definition: scheduler.c:116
static Task * idleTask
The idle task.
Definition: scheduler.c:80
uint16_t lz_u_resolution_unit_t
Represents the type used for the system clock resolution unit, as an unsigned integer.
Definition: lazuli.h:36
#define WAIT_SOFTWARE_TIMER
Set the task to wait for the specified number of time resolution units, using the software timer...
Definition: task.h:71
void * KIncrementalMalloc(const size_t size)
Allocate memory for kernel objects using incremental method.
Definition: memory.c:67
enum Lz_SchedulingPolicy schedulingPolicy
The scheduling policy of the task.
Definition: lazuli.h:104
Lz_LinkedList waitingTasks
The list of tasks waiting for that mutex.
Definition: mutex.h:30
void Lz_Task_WaitActivation(void)
Set the calling task to wait for its next activation.
Definition: scheduler.c:785
24-Hour clock kernel interface.
lz_u_resolution_unit_t timeUntilTimerExpiration
The number of time units until the software timer expires for the task.
Definition: task.h:159
void Scheduler_AbortTask(void *const sp)
Call the appropriate scheduler to abort the curent running task.
Definition: scheduler.c:632
Doubly linked lists interface.
static Task * PickTaskToRun(void)
Pick the task ready to run with the highest priority.
Definition: scheduler.c:217
void * stackOrigin
The bottom of the allocated stack for the task.
Definition: task.h:102
void List_Append(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const item)
Insert an Lz_LinkedListElement as the last element of an existing Lz_LinkedList.
Definition: list.c:20
void Kernel_Panic(void)
Kernel panic.
Definition: kernel.c:77
static void UpdateCyclicRealTimeTasks(void)
Update all registered cyclic RT tasks.
Definition: scheduler.c:243
void Arch_LoadFromProgmem(const void *source, void *destination, const size_t size)
Copy bytes from program memory to RAM.
static void Schedule(void)
Elect the new current task.
Definition: scheduler.c:379
void Memory_Copy(const void *source, void *destination, const size_t size)
Copy bytes from one location to another in main memory.
Definition: memory.c:73
Interrupt codes of ATmega328P.
uint8_t bool
Boolean type.
Definition: common.h:78
Represents the main container for doubly linked elements.
Definition: list.h:36
unsigned char uint8_t
Represents a unsigned integer type with width of exactly 8 bits.
Definition: stdint.h:89
Represents the configuration of a task.
Definition: lazuli.h:88
static void ManageCyclicRealTimeTask(void)
Manage cyclic real-time tasks.
Definition: scheduler.c:304
Mutexes interface.
enum Lz_SchedulingPolicy schedulingPolicy
The scheduling policy.
Definition: task.h:119
#define NULL
NULL pointer.
Definition: common.h:68
static Lz_LinkedList waitingActivationTasks
The queue of tasks waiting activation.
Definition: scheduler.c:49
static bool PeriodComparer(const Task *const task1, const Task *const task2)
Compare the "period" property of 2 tasks.
Definition: scheduler.c:140
Priority time sliced real-time scheduling.
Definition: lazuli.h:65
static Task * CallbackRegisterUserTask(const Lz_TaskConfiguration *const taskConfiguration)
Callback of SchedulerOperations.registerTask() for registering a user task.
Definition: scheduler.c:421
#define WAIT_ACTIVATION
Set the task to wait for its next activation.
Definition: task.h:46
void Lz_Run(void)
Run the scheduler.
Definition: scheduler.c:765
void Scheduler_HandleInterrupt(const uint8_t interruptCode)
This function is called by arch-specific interrupt handling routine.
Definition: scheduler.c:657
volatile FuncVoidVoid terminationCallback
Callback to the scheduler to manage task termination.
Definition: task.h:312
void Arch_InitSystemTimer(void)
Initialize the system timer.
lz_u_resolution_unit_t timeUntilActivation
The number of time units until the task will be activated.
Definition: task.h:149
void List_InsertBefore(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const listItem, Lz_LinkedListElement *const itemToInsert)
Insert an element before another in a Lz_LinkedList.
Definition: list.c:171
lz_task_priority_t priority
The priority of task.
Definition: lazuli.h:110
Basic type definitions and useful macros.
Architecture Abstraction API.
static bool RegisterTask(void(*const taskEntryPoint)(void), Lz_TaskConfiguration *taskConfiguration, const bool isIdleTask)
Register a new task.
Definition: scheduler.c:503
static void UpdateTasksWaitingSoftwareTimer(void)
Update all tasks waiting for the expiration of a software timer.
Definition: scheduler.c:285
void Clock24_Increment(void)
Increment the 24-Hour clock, taking into the account the resolution of the system clock...
Definition: clock_24.c:97
const bool LZ_CONFIG_ON_IDLE_SLEEP
When 1, put the CPU to sleep when it&#39;s idle.
#define NO_MESSAGE
No message has to be passed to the scheduler.
Definition: task.h:40
static Lz_LinkedList abortedTasks
The queue of aborted tasks.
Definition: scheduler.c:73
Represents a mutex.
Definition: mutex.h:28
Represents an element of a doubly linked list.
Definition: list.h:25
static Task * CallbackRegisterIdleTask(void)
Callback of SchedulerOperations.registerTask() for registering the scheduler idle task...
Definition: scheduler.c:474
void Scheduler_WakeupTasksWaitingMutex(Lz_Mutex *const mutex)
Wake up all tasks waiting for a mutex.
Definition: scheduler.c:694
const size_t LZ_CONFIG_IDLE_TASK_STACK_SIZE
The stack size in bytes of the scheduler idle task.
Represents a task.
Definition: task.h:76
static Lz_LinkedList waitingInterruptsTasks[INT_TOTAL]
The table of waiting queues for interrupts.
Definition: scheduler.c:58
void(*)(void) ReverseBytesOfFunctionPointer(void(*const pointer)(void))
Reverse the bytes of a function pointer.
Definition: scheduler.h:35
void Lz_TaskConfiguration_Init(Lz_TaskConfiguration *const taskConfiguration)
Initialize an Lz_TaskConfiguration with default values for all parameters.
Definition: scheduler.c:746
Lz_LinkedListElement * List_PickFirst(Lz_LinkedList *const linkedList)
Return the first element of an existing linked list.
Definition: list.c:96
void Arch_StartSystemTimer(void)
Start the system timer.
void * taskToSchedulerMessageParameter
A parameter that can accompany a taskToSchedulerMessage.
Definition: task.h:181
#define List_RemovableForEach(LINKEDLIST, TYPE, ITEM, MEMBER, ITERATOR)
Run through an Lz_LinkedList like a for loop, with the ability of removing elements from the list whi...
Definition: list.h:222
#define LINKED_LIST_INIT
Define the initialization value for the type Lz_LinkedList.
Definition: list.h:47
#define List_ForEach(LINKEDLIST, TYPE, ITEM, MEMBER)
Run through an Lz_LinkedList like a for loop.
Definition: list.h:178
const char *const LZ_CONFIG_IDLE_TASK_NAME
The name of the idle task.
void Lz_Task_WaitInterrupt(uint8_t interruptCode)
Wait for a specific interrupt to occur.
Definition: scheduler.c:793
lz_u_resolution_unit_t period
The period (T) of the task, expressed as an integer number of time units.
Definition: task.h:130
void List_InitLinkedListElement(Lz_LinkedListElement *const item)
Initialize an Lz_LinkedListElement.
Definition: list.c:264
static bool PriorityComparer(const Task *const task1, const Task *const task2)
Compare the "priority" property of 2 tasks.
Definition: scheduler.c:156
Represents the layout of the stack when saving the context of a task.
Definition: task.h:203
static Lz_LinkedList waitingTimerTasks
The queue of tasks waiting for their software timer to reach expiration.
Definition: scheduler.c:63