====== OSA : Events and priority ======
===== Task states =====
To synchronize tasks, the system uses events. For example, we have two active tasks (created by service ##[[en:osa:ref:allservices:OS_Task_Create|OS_Task_Create]]##): one of them measures temperature, and the other displays the measured value on a screen. The second task cannot display data if there is no measured value. While the first task makes measurements, the second task waits. After the temperature is measured (in other words, the event has taken place), the second task becomes ready to run. And then the second task can be executed.
Thus all tasks can have one of five states:
{|class = "fpl"
|-
|**not active**
|task was not created or was deleted
|-
|**waiting**
|task is waiting for some event
|-
|**ready**
|the expected event occurred but the task did not get control yet
|-
|**running**
|task is executing
|-
|**paused**
|task is paused. It is still active but can't get control.
|}
In order for a task to get control, two conditions must be met:
- the event expected by the task occurs (task becomes **ready**);
- the task's priority must be higher than the priorities of other ready tasks.
===== Events =====
Events in OSA:
- semaphore ([[en:osa:ref:services:binary_semaphores|binary]] or [[en:osa:ref:services:counting_semaphores|counting]]);
- [[en:osa:ref:services:messages|message]] (pointer to a message body or a simple byte message);
- [[en:osa:ref:services:flags|flags combination]];
- [[en:osa:ref:services:timers|timeout]];
- any boolean expression.
Each of the first four types is described in its own section. The fifth type is optional and allows a task to wait for some non-system event, e.g.:
OS_Wait(TMR1IF); // Wait for TMR1 overflow
or
OS_Wait_TO(ReadADC(0) > 128); // Wait for input voltage to be greater than Vdd/2
These two services are described in the section [[en:osa:ref:services:system_services|system services]].
===== Priority =====
All task have a priority from 0 (highest) to 7 (lowest).
There are three priority modes (levels):
* **disabled priorities** - all assigned priorities are ignored. This is the fastest and compact mode. But it does not allow to assign higher priority for more important tasks.
* **normal priorities** - each task have it's own priority. If there are several **ready** tasks, then the task with the highest priority will get control. If several **ready** tasks have the same priority, then they will be run in round-robin mode. This mode has two disadvantages:
- when there is an always ready task with high priority, no low priority tasks will get control;
- when two or more tasks have the same priority and they wait for the same event, only one of them allways will get the control;
* **extended priorities** NEW - all tasks get control according to their priority. For example, if there are two always ready tasks with priorities 3 and 4, then one of them will get 55-60% of control (with priority 4) and other - 40-45%. The advantage of this mode is that all tasks guarantly will get the control. But in this mode system requires 2 addition bytes of RAM per each task.
Read [[en:osa:ref:appendix:speed|SPeed characteristics]] to learn more about speed of scheduler in different modes.
The priority mode is defined once on the compilation stage by setting constant ##[[en:osa:ref:appendix:configuration|OS_PRIORITY_LEVEL]]## in ##[[en:osa:ref:appendix:configuration|osacfg.h]]##:
#define OS_PRIORITY_LEVEL OS_PRIORITY_DISABLE // For disable priorities
#define OS_PRIORITY_LEVEL OS_PRIORITY_NORMAL // For normal priorities
#define OS_PRIORITY_LEVEL OS_PRIORITY_EXTENDED // For extended priorities
By default ##[[en:osa:ref:appendix:configuration|OS_PRIORITY_NORMAL]]## is set.
~~UP~~
===== Priority competition =====
There are times whan several tasks are waiting for the same event. For example they can wait for some internal resource (UART, ADC, SPI) or some external resource (EEPROM, LCD etc). How will the system behave in this case? After the event occurs, all tasks that waited for this event will become **ready**. The kernel will find the task with the highest priority and run it. If, after this task executes, the event is cleared (for example, all tasks waited for a semaphore, and the executed task reset it) all tasks become **waiting** again.
When working under extended priority mode, the tasks who was ready but did not get the control (because of more priority task has reset the event) will rise it's priority. This will give to it more chance to get the control next time event occured.
~~UP~~