Comtrol eCos User Manual

Page 31

Advertising
background image

Kernel Overview

shared with an ISR. For example if a thread needs to add another buffer to a linked list of free buffers and the ISR
may remove a buffer from this list at any time, the thread would need to disable interrupts for the few instructions
needed to manipulate the list. If the hardware raises an interrupt at this time, it remains pending until interrupts are
reenabled.

Analogous to interrupts being disabled or enabled, the kernel has a scheduler lock. The various kernel functions
such as

cyg_mutex_lock

and

cyg_semaphore_post

will claim the scheduler lock, manipulate the kernel data

structures, and then release the scheduler lock. If an interrupt results in a DSR being requested and the scheduler
is currently locked, the DSR remains pending. When the scheduler lock is released any pending DSRs will run.
These may post events to synchronization primitives, causing other higher priority threads to be woken up.

For an example, consider the following scenario. The system has a high priority thread A, responsible for processing
some data coming from an external device. This device will raise an interrupt when data is available. There are two
other threads B and C which spend their time performing calculations and occasionally writing results to a display
of some sort. This display is a shared resource so a mutex is used to control access.

At a particular moment in time thread A is likely to be blocked, waiting on a semaphore or another synchronization
primitive until data is available. Thread B might be running performing some calculations, and thread C is runnable
waiting for its next timeslice. Interrupts are enabled, and the scheduler is unlocked because none of the threads are
in the middle of a kernel operation. At this point the device raises an interrupt. The hardware transfers control
to a low-level interrupt handler provided by eCos which works out exactly which interrupt occurs, and then the
corresponding ISR is run. This ISR manipulates the hardware as appropriate, determines that there is now data
available, and wants to wake up thread A by posting to the semaphore. However ISR’s are not allowed to call

cyg_semaphore_post

directly, so instead the ISR requests that its associated DSR be run and returns. There are

no more interrupts to be processed, so the kernel next checks for DSR’s. One DSR is pending and the scheduler is
currently unlocked, so the DSR can run immediately and post the semaphore. This will have the effect of making
thread A runnable again, so the scheduler’s data structures are adjusted accordingly. When the DSR returns thread
B is no longer the highest priority runnable thread so it will be suspended, and instead thread A gains control over
the cpu.

In the above example no kernel data structures were being manipulated at the exact moment that the interrupt
happened. However that cannot be assumed. Suppose that thread B had finished its current set of calculations and
wanted to write the results to the display. It would claim the appropriate mutex and manipulate the display. Now
suppose that thread B was timesliced in favour of thread C, and that thread C also finished its calculations and
wanted to write the results to the display. It would call

cyg_mutex_lock

. This kernel call locks the scheduler,

examines the current state of the mutex, discovers that the mutex is already owned by another thread, suspends
the current thread, and switches control to another runnable thread. Another interrupt happens in the middle of
this

cyg_mutex_lock

call, causing the ISR to run immediately. The ISR decides that thread A should be woken

up so it requests that its DSR be run and returns back to the kernel. At this point there is a pending DSR, but the
scheduler is still locked by the call to

cyg_mutex_lock

so the DSR cannot run immediately. Instead the call to

cyg_mutex_lock

is allowed to continue, which at some point involves unlocking the scheduler. The pending DSR

can now run, safely post the semaphore, and thus wake up thread A.

If the ISR had called

cyg_semaphore_post

directly rather than leaving it to a DSR, it is likely that there would

have been some sort of corruption of a kernel data structure. For example the kernel might have completely lost
track of one of the threads, and that thread would never have run again. The two-level approach to interrupt han-
dling, ISR’s and DSR’s, prevents such problems with no need to disable interrupts.

31

Advertising