## Task Synchronisation

October 15th, 2009- Asynchronous device driver where we are dealing with slow devices. We don’t necessarily want tasks blocked waiting on the device.
- At system start-up, many RTOSs start tasks as active (ready to run). We may have an ordering dependency for execution (e.g. initialisation of global resources) where all tasks must wait for a given condition (the concept of a barrier which can be very important in multi-processor systems).
- Having a managed task abort notification, rather than deleting tasks (which can lead to resource issues). Similar in concept to the UNIX/Linux kill signal. Also used to manage task pools.

**synchronisation**

*noun*

- the relation that exists when things occur
**at the same time**; “the drug produces an increased synchrony of the brain waves” [syn: synchronism] [ant: asynchronism] - an adjustment that causes something to occur or recur
**in unison**[syn: synchronization] - coordinating by causing to indicate
**the same time**; “the synchronization of their watches was an important preliminary” [syn: synchronization]

In regard to task synchronisation there four classes of interaction we need to address:

- one-to-one – only two task synchronising
- one-to-many
- many-to-one
- many-to-many

Initially we address the condition where only two tasks are synchronising.

_{1}and Task

_{2}) that need to synchronise their execution.

- Task
_{2}runs until it reaches the synchronisation point as defined by an RTOS synchronisation object (*SO*), at which point it waits for Task_{1} - Task
_{1}now runs and reaches the synchronisation point, signals Task_{2}via the*SO*. Both tasks are now ready to run. - The higher priority task now continues execution and the lower priority task is made ready (If the tasks are of equal priority typically Task
_{1}will continue as this avoids a context switch).

_{1}and Task

_{2}have synchronized their threads of execution.

_{1}arrives first? In terms of the dictionary definition of synchronisation, Task

_{1}should wait for Task

_{2}. Unfortunately, with most RTOSs this is not the case and Task

_{1}will continue execution without blocking. This means we need to further refine our definition of synchronisation to include the concepts of:

- Symmetric or Bilateral Synchronisation
- Asymmetric or Unilateral Synchronisation

*Rendezvous*(as support by the Ada programming language). Surprisingly this is rarely supported by the majority of RTOSs. One limitation of bilateral synchronisation is that it cannot be used for ISR-to-task synchronisation (as an ISRs must never block).

- if Task
_{2}arrives at the*SO*first it will wait for Task_{1}, and then synchronisation with Task_{1}when it arrives - if Task
_{1}arrives at the*SO*first it will not wait for Task_{2}, thus unilateral synchronisation.

_{2}now reaches the synchronisation point (assuming Task

_{1}has already passed the synchronisation point)? Does Task

_{2}block and wait for Task

_{1}, or does it see that Task

_{1}has already visited to

*SO*and continue? Or to put it another way, is the notification of synchronisation to the synch object from Task

_{1}persistent or non-persistent?

_{1}has already passed the synchronisation point is not remembered, therefore Task

_{2}blocks until Task

_{1}signals again . Due to how most RTOSs actually support unilateral synchronisation (discussed later), this, like bilateral synchronisation, is also an uncommon model. Interestingly, Win32 supports this model using a concept called a PulseEvent. If no tasks are waiting when the PulseEvent is called then the event is discarded.

_{1}has already signalled the

*SO*(passed the synchronisation point) is remembered. When Task

_{2}arrives at the synchronisation point is doesn’t block, but continues (this particular use case is actually asynchronous event notification).

_{2}

*consumes*the signal Task

_{1}has set (auto-reset) or does Task

_{1}

*clear*the signal (manual-reset) at some later time.

_{2}now arrives back at the

*SO*and waits, it will block until again signalled by Task

_{1}. In the manual-reset model, Task

_{2}will continue to pass the synchronisation point until Task

_{1}(or indeed Task

_{2}) explicitly clears the signal (normally with a separate API call).

_{1}signals the

*SO*more than once before Task

_{2}arrives at the synchronisation point, and therefore the original signal has not been consumed? One model is there is no effect, the signal remains set and is consumed when Task

_{2}arrives (binary model). The alternative is that a count is kept of the number of signals set by Task

_{1}. Each time Task

_{2}waits on the

*SO*this count is decremented, and Task

_{2}will only block if the count is zero.