Page 50 - Designing Autonomous Mobile Robots : Inside the Mindo f an Intellegent Machine
P. 50
The Basics of Real-time Software (For Mere Mortals)
threads. The problem comes when one thread is using a subroutine and the kernel
switches the context to another thread which then calls the same routine. Since the
function had not completed its work for the first thread before being called by the
second, it is said to have been reentered. A function or subroutine that can allow this
without errors is said to be reentrant.
If a routine uses any dedicated variables in fixed memory locations, the value of
these will be destroyed by a reentrant call, and when the routine returns to finish
the first call it will produce erroneous results. Therefore, for a routine to be reen-
trant, it must use only registers which are preserved on its stack, or stack allocated
memory for its working storage.
When at all possible, all functions and subroutines should be written to be reentrant.
Reentrant routines should also be clearly labeled as being so, and conversely non-reentrant
routines should be clearly marked as well.
If a subroutine is not reentrant, and it is subject to being called from two or more
different threads or interrupt routines, then the only solution may be to mask inter-
rupts during the subroutine. Generally this is a messy solution that can bring with it
other problems. For example, if a very large block of code is being executed with
interrupts blocked while fast interrupts are occurring, there is the danger that one or
more interrupts may not get serviced. This condition is called overrunning the
interrupts.
Interrupt masking and interrupt priority
There are other considerations when programming real-time systems. For example,
consider an interrupt from a wheel encoder that is used to make dead-reckoning
calculations. At least two things can go wrong. The first danger has to do with
interrupt priority.
The encoder procedure will be accumulating position estimates based on previous
position estimates. For this reason it cannot be reentrant by definition, as it needs
the results of all previous executions to be complete before it can add the new
increments to their totals. Therefore this routine must mask its own interrupt (or
simply not reenable it) until it is done with its calculations.
Such an encoder will produce interrupts that can occur at a relatively high rate, but
that take only a few microseconds to service. Since the shortest time period between
33

