Schedulers – Comtrol eCos User Manual

Page 28

Advertising
background image

Kernel Overview

loosely defined because of the many configuration options. For example

cyg_mutex_lock

will always attempt to

lock a mutex, but various configuration options determine the behaviour when the mutex is already locked and
there is a possibility of priority inversion.

The optional nature of the kernel package presents some complications for other code, especially device drivers.
Wherever possible a device driver should work whether or not the kernel is present. However there are some
parts of the system, especially those related to interrupt handling, which should be implemented differently
in multi-threaded environments containing the eCos kernel and in single-threaded environments without the
kernel. To cope with both scenarios the common HAL package provides a driver API, with functions such as

cyg_drv_interrupt_attach

. When the kernel package is present these driver API functions map directly on to

the equivalent kernel functions such as

cyg_interrupt_attach

, using macros to avoid any overheads. When the

kernel is absent the common HAL package implements the driver API directly, but this implementation is simpler
than the one in the kernel because it can assume a single-threaded environment.

Schedulers

When a system involves multiple threads, a scheduler is needed to determine which thread should currently be
running. The eCos kernel can be configured with one of two schedulers, the bitmap scheduler and the multi-level
queue (MLQ) scheduler. The bitmap scheduler is somewhat more efficient, but has a number of limitations. Most
systems will instead use the MLQ scheduler. Other schedulers may be added in the future, either as extensions to
the kernel package or in separate packages.

Both the bitmap and the MLQ scheduler use a simple numerical priority to determine which thread should be
running. The number of priority levels is configurable via the option

CYGNUM_KERNEL_SCHED_PRIORITIES

, but

a typical system will have up to 32 priority levels. Therefore thread priorities will be in the range 0 to 31, with 0
being the highest priority and 31 the lowest. Usually only the system’s idle thread will run at the lowest priority.
Thread priorities are absolute, so the kernel will only run a lower-priority thread if all higher-priority threads are
currently blocked.

The bitmap scheduler only allows one thread per priority level, so if the system is configured with 32 priority levels
then it is limited to only 32 threads — still enough for many applications. A simple bitmap can be used to keep
track of which threads are currently runnable. Bitmaps can also be used to keep track of threads waiting on a mutex
or other synchronization primitive. Identifying the highest-priority runnable or waiting thread involves a simple
operation on the bitmap, and an array index operation can then be used to get hold of the thread data structure
itself. This makes the bitmap scheduler fast and totally deterministic.

The MLQ scheduler allows multiple threads to run at the same priority. This means that there is no limit on the
number of threads in the system, other than the amount of memory available. However operations such as finding
the highest priority runnable thread are a little bit more expensive than for the bitmap scheduler.

Optionally the MLQ scheduler supports timeslicing, where the scheduler automatically switches from one runnable
thread to another when some number of clock ticks have occurred. Timeslicing only comes into play when there
are two runnable threads at the same priority and no higher priority runnable threads. If timeslicing is disabled
then a thread will not be preempted by another thread of the same priority, and will continue running until either it
explicitly yields the processor or until it blocks by, for example, waiting on a synchronization primitive. The con-
figuration options

CYGSEM_KERNEL_SCHED_TIMESLICE

and

CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS

control

timeslicing. The bitmap scheduler does not provide timeslicing support. It only allows one thread per priority level,
so it is not possible to preempt the current thread in favour of another one with the same priority.

Another

important

configuration

option

that

affects

the

MLQ

scheduler

is

CY-

GIMP_KERNEL_SCHED_SORTED_QUEUES

. This determines what happens when a thread blocks, for example by

28

Advertising