- 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]

It should be noted that synchronisation and mutual exclusion often get lumped together and confused. Mutual exclusion is about making sure thing don’t happen at the same time, whereas synchronisation is about making sure they do.

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).

We can now say that Task_{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).

However, we have yet another dichotomy; does Task_{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).

Finally, in the consuming model what happens if Task_{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.

So we can classify RTOS synchronisation into the following:

In the next posting I shall be looking at synchronisation involving more than two tasks and then following that one by examining some actual RTOSs and their support for synchronisation.

#### Latest posts by admin (see all)

- On BashLite and Shellshock - November 19, 2014
- Acorn Goes to Market with RISC Microprocessor - November 6, 2014
- Static and Dynamic Libraries on Linux - April 4, 2014

You neglected to mention the most intuitive way of synchronisation: messages. In the case of the asynchronous device driver, all the user has to do is send a request message to the driver and decide how long to wait for a reply (if at all).

No need to pick one behavioural model and hope it suits your needs, just specify the transactions directly.

"Bilateral synchronisation is the condition when whichever task arrives first it waits for the other one" ... "Surprisingly this is rarely supported by the majority of RTOSs."

Any reason why you can't do bilateral synchronisation with semaphores in the usual way? Namely, with two of them:

// Task 1:

signal(&task1;_ready);

wait(&task2;_ready);

// Task 2:

signal(&task2;_ready);

wait(&task1;_ready);

See 'the little book of semaphores' for details.

(it's free in pdf format from http://www.greenteapress.com/semaphores/).

Pingback: Cocoa edge case – dev blog by Krzysztof Profic | Concurrency and Threading on iOS #4 – Task synchronisation