The CTL enables your application to have multiple tasks. You will typically use a task when you have some algorithmic or protocol processing that suspend it's execution whilst other activities occur. For example you may have a protocol processing task and a user interface task.

#### Tasks

A task (sometimes called a thread) is a CPU execution context which is typically a subset of the CPU register state. When a task switch occurs the CPU execution context is saved on to the stack of the current task, a new task is selected to run and its saved CPU execution context is restored. The process of selecting a new task to run is called task switching or (re)scheduling.

Task switching can be co-operative or pre-emptive. Co-operative task switching occurs when a task calls a tasking library function that may cause another task to run. Pre-emptive task switching occurs when an interrupt service routine calls a function in the library that suspends the interrupted task and a suspended task becomes the active (currently executing) task. Note that interrupt service routines are not tasks and cannot be context switched.

A task has a priority associated with it, the lowest priority is 0 the highest is 255. A task is either executing (the current task) or it is queued in the task list. The task list is kept in priority order with the highest priority task at the head of the list. The current task will always have a priority that is greater than or equal to the first runnable task in the task list.

In general a task switch occurs when a task in the task list becomes runnable and has a priority that is higher than the current task. However when a co-operative task switch occurs and the next task ready to run is of the same priority as the current task then a task switch will occur. This is sometimes referred to as round robin scheduling.

There is one executing task and there must always be a task ready to execute i.e. the task list must have a runnable task queued on it. Typically there will always be an idle task that loops and perhaps puts the CPU into a power save mode. A task on the task list is either runnable or waiting for something (e.g. timeout).

When a task switch occurs global interrupts will be enabled. So you can safely call the tasking library functions with interrupts disabled.

#### Task synchronization and resource allocation

The CrossWorks tasking library provides several mechanisms to synchronize execution of tasks and to serialise resource allocation.

- Event Sets — An event set is a word sized variable which tasks can wait for specific bits (events) to be set to 1. You can wait for any specified events in an event set or for all of the specified events. You can also specify that the events the task are waiting on are automatically cleared (set to 0) when the task has completed its wait.
- Counting Semaphores — A counting semaphore is a word size variable which tasks can wait for to be non-zero. Counting semaphores are useful when serialising access to fixed sized buffers i.e. the count value can represent the number of free or used elements in the buffer.
- Message Queues — A message queue is a structure that enables tasks to post and receive data. Message queues are used to provide a buffered communication mechanism between tasks.
- Interrupt enable/disable — The tasking library provides functions that enable and disable the global interrupt enables state of the processor. These functions can be used to provide a time critical mutual exclusion facility.

Note that all waits on task synchronization objects are priority based i.e. the highest priority task waiting will be scheduled first.

#### Timer support

If your application can provide a periodic timer interrupt (for example one that keeps a watch dog alive) then you can use the timer wait facility of the library. This is a simple software counter that is incremented by your timer interrupt. You can use this to specify a wakeup time and to prevent your program waiting forever for something to happen.

#### Interrupt Service Routine support

On systems that have programmable interrupt controllers the CTL provides functions that enable you to install interrupt service routines as C functions and associate the required hardware priority to their execution. On systems that have fixed interrupt schemes functions are provided that enable you to create interrupt service routines that co-operate with the CTL.

Tasks can synchronize with interrupt service routines using either event sets, semaphores or message queues. Interrupt service routines are allowed to set (and clear) events in an event set, to signal a semphore and to do a non blocking post to a message queue. Interrupt service routines cannot wait for events, wait for a semaphore or use blocking message queue functions.

#### Memory Block Allocation support

The CTL provides a simple memory block allocator that can be used in situations where the standard C malloc and free functions are either too slow or may block the calling task.

#### C Library support

The CTL provides a task specific errno as well as exclusion mechanisms to enable usage of malloc/free functions in a multi-tasking envrionment.