North-Holland Microprocessing and Microprogramming 12 (1983) 193-198
193
MIRTEX: A Real-Time, Multi-Tasking Executive for Microprocessors L.J.M. Nieuwenhuis Dr. Neher Laboratories of the Dutch PTT The Netherlands
MIRTEX is a real-time, multi-tasking executive for microprocessors. It was developed for real-time control systems by the Dr. Neher Laboratories of the Dutch PTT, Department INF-B. MIRTEX is smaller than 2 kbytes code and offers dynamic creation and termination of tasks running at different priority levels, task synchronization with semaphores and regions, interrupt driven I/0 synchronization and synchronized buffers for multiple reading and writing tasks.
I. MULTI-TASKING
2. THE MIRTEX CONCEPT
Multiprogramming is a programming technique based on dividing the program into sets of operations which may be executed in parallel. Such a set of operations is called a task. Each task may be executed in parallel with another task. The operations of one. task have to be carried out in a strict well-defined order. Multi~tasking does not put any restrictions on the execution time of an operation; the execution of an operation is completed in a final but undetermined period of time. Consequently, it cannot be predicted whether the operation of one task is completed before or after the operation of another task. Hence if one task stores data in a location which has to be used by another task, task synchronization is required to guarantee time-independent results.
MIRTEX is a concept of a real-time, multi-tasking executive for microprocessors based on [I] and [2]. It was developed in Pascal. A few comment lines where used to describe "hard" operations (i.e. stackpointer manipulations and interrupthandling). Error free compilation of the program guaranteed syntactical correct usage of datatypes and operations. The cross-reference list displayed the internal structure of the real-time multl-tasking executive. MIRTEX was coded in assembler for the Z80 and M6809 microprocessors. On the basis of the functional design in Pascal, the executive can easily be coded in less than 2 kbytes.
A multi-tasking executive is the software package providing a virtual machine which executes tasks in parallel. As the real machine only consists of one processor, the tasks executed by the virtual machine share the processor. The advantages of a real-time multi-tasking executive above a 'single-tasking' approach, are the structured solutions for real-time control systems. The usage of (nested) interrups offers a 'multi-tasking' solution with poor characteristics. Interrupts are handled with highest priority and have to be completed before the interrupted activities can continue. If a microprocessor system has to respond to several sequences of external events, many interrupt service routines are needed. Each responce to an external event has to be handled separately to guarantee efficient usage of the processor. A multi-tasking executive is a general purpose solution for these kinds of problems, offering structured programs and efficient processor usage. Each logical sequence of external events is a task and every task, not waiting for internal or external events, can be executed.
MIRTEX can be used in combination with almost every hardware configuration. Besides RAM and (E)PROM, a real-time clock is required to support the real-time functions of MIRTEX. To keep MIRTEX portable, a few bytes of code, handling the interrupt of the clock, have to be written by the user; the MIRTEX entry CLOCK provides all real-time functions of the executive. MIRTEX uses a heap to allocate memory pages for task stacks and buffer space. The heap location is a generation-dependent constant but will typically be at the top or bottom of the address space. The memory size required for the heap is determined by the page size and the maximum need at runtime. The page size is determined by the maximum stack depth and the buffer requirements. Stackdepth is regurlary checked by MIRTEX and an error trap will occur if stack overflow is detected. The address entered after a system reset is located in MIRTEX, After initialization of the executive, the userprogram is started at a generation-dependent start address. The code at this address may be any type of program; a 'single task' program can run without usage of MIRTEX. However, new tasks can be created by calling MIRTEX. After this call, the original and the new task are sharing the processor. The number of running tasks is only limited by the memory space available for the MIRTEX heap.
194
L.J.M. Nieuwenhuis / M I RTEX
Task synchronization is accomplished by SEMAPHORES and CRITICAL REGIONS [3]. Each SEMAPHORE and REGION requires a small control block in the user memory. The address of the control block is a unique identification for each synchronization primitive. The number of SEMAPHORES or CRITICAL REGIONS is not limited by MIRTEX. For synchronization with external events a special type of semaphore is used. For microprocessor systems with vectored interrupt facilities, MIRTEX provides an array of these semaphores using the vector value as an index.
TASK A
AI: LOAD A, COUNT A2: I N C A A3: LOAD COUNT, A
order: AI,BI,B2,B3,A2,A3 order: AI,A2,A3,B],B2,B3 Figure
For the exchange of data between tasks BUFFERS are available. The buffer management requires a small control block in the user memory space; the actual buffer space is allocated at the MIRTEX heap. Again the address of the BUFFER control block is the unique identification for each buffer. The buffer is a pipeline to smooth different production and consumption speeds. Synchronization as a consequence of reading and writing in a final length buffer by multiple tasks is provided by MIRTEX. 2.1 Task management Tasks are created by the MIRTEX call START. The address of the first instruction and a priority level accompany the call. The contents of the registers are passed to the new task. MIRTEX allocates a page from the heap and sets the stackpointer. The address of the entry EXIT is pushed on stack; a task terminates with a -instruction. An 'unstructured' termination by jumping to EXIT is also possible. The new task will be executed at one of seven priority levels. A task can read and modify its own priority by calling the entries GET PRIORITY and SET PRIORITY. The DELAY operation of MIRTEX delays a task for a requested number of time units. The time unit is determined by the frequency with which the entry CLOCK is called. 2.2 Task synchronization Task are synchronized by SEMAPHORES and CRITICAL REGIONS [3]. REGIONS are used to obtain temporary, exclusive control of common variables and I/O devices. SEMAPHORES enable exchange of timing signals between tasks. The execution order of operations of different tasks cannot be predicted. Consequently, it is unknown whether operations of different tasks are executed at the same time. To obtain predictable results, mutual exclusive control of variables and devices is necessary. An example of the need for mutual exclusion is given in figure I.
TASK B
;
BI: LOAD A, COUNT B2: I N C A B3: LOAD COUNT, A
result: COUNT:= COUNT + l result: COUNT:= COUNT + 2
Unprotected
common variables
Two tasks increment the variable COUNT. If the increment operation, consisting of 3 instructions, is executed at the same time (or interleaved), the result is unknown a priori. The increment operations are called critical operations; if the increment operations are mutually excluded, the correct result is obtained. Mutual exclusion is achieved by surrounding the critical operations by the ENTER REGION and LEAVE REGION operations. The increment operations of tasks A and B in the example are in the same CRITICAL REGION. The ENTER operation is a request to enter the CRITICAL REGION; this request is granted if there is no other task in that region. The request is also granted if the region is occupied by the requesting task itself; there is no reason to refuse a request which was granted earlier. After completion of the operation, the region is left by the LEAVE operation. Other tasks waiting for entrance, can be admitted. If the number of LEAVE-operations equals the number of ENTER-operations, the claim for the region is released. SEMAPHORES are used for the exchange of'timing signals. If, for example, task A loads data in a common variable, which task B needs to continue, a signal from task A to B is needed. SEMAPHORES are associated with a value and two operations P and V F3] (or WAIT and SIGNAL Ill). A P-operation decrements the semaphore value by l if the value > O. If the value = 0, the task will wait for value > 0. A V-operation always increments the semaphore value. Hence, a V-operation enables tasks, waiting for value > O, to continue. In the example, a semaphore with initial value = 0 can be used. Task A executes a V-operation after loading the data; task B executes a P-operation before reading the common variable. If task A executes the V before the P-operation of task B, the counter is incremented; task B immediately proceeds when the synchronization point is encountered. If, on the contrary, task B is faster, it will be blocked until the V-operation of task A has been completed. After the P- and V-operation have been completed the semaphore value always equals O. SEMAPHORES and CRITICAL REGIONS are initialized by two MIRTEX calls INIT SEMAPHORE and INIT REGION. The initial value of a semaphore is a parameter for the call.
L.J.M. Nieuwenhuis / M I R TEX
195
2.3 Buffers SEMAPHORES and REGIONS are very suitable to implement cyclic buffers enabling READ- and WRITEoperations by multiple tasks. A buffer is created and deleted by the calls BUFFER CREATE and BUFFER DELETE. Data is read and written by the calls BUFFER READ and BUFFER WRITE. A task requesting data from an empty buffer is blocked until data has been written by another task. A task delivering data for a full buffer, is blocked until buffer space is available by a READ OPERATION of another task. 2.4 I/O synchronization Semaphores are also used for synchronization of tasks and external events. MIRTEX handles interrupts by performing a V-operation for an interrupt semaphore. For microprocessor systems with vectored interrupt facilities, an array of interrupt semaphores is implemented. These semaphores are located on the MIRTEX heap and initialized during system reset. The corresponding P-operations are executed by calling the MIRTEX entry DOIO (as in MODULA [4]).
I ead ? tail Figure 2 A queue of records Each task in MIRTEX is associated with a task record. The address of the task record is a unique identification of a task. The lay-out of a task record is given in figure 3.
MIRTEX allows the usage of 'normal' interrupt service routines. An interrupt service routine is attached to a vector by calling the entry SET INTERRUPT. It is important to note that an interrupt service routine is not a task itself but a routine executed by the task which was interrupted. Deadlock may occur if the interrupt service routine includes P- or ENTER-operations. If, for instance, a P-operation leads to blockade of the interrupted task, deadlock is created if the interrupted task itself has to call for the V-operation,
stack
stackpointer time priority
3. THE INTERNAL STRUCTURE OF MIRTEX A multi-tasking executive is controlling the execution of multiple tasks of a program. The processor is allocated to tasks one after another. The executive selects tasks for processor allocation on the basis of assigned priorities and the state of a task. Each time a task is created, space from the heap is claimed. The executive has to keep an administration for every task in the system. The administration and memory management in MIRTEX is based on pointers and queues [5]. 3.] Queues of task records A set of records can be linked together if a pointer in the record is reserved to point to other records. A QUEUE CONTROL BLOCK consists of two pointers: a headpointer pointing to the first record in the queue and a tailpointer pointing to the last record in the queue (see figure 2). MIRTEX always attaches a record to the tailrecord of a queue; if a record has to be selected, the headrecord is always detached.
1
link Figure 3 A task record The task record contains all relevant information of a task. Like 'single task' programs, the stack contains the history of a task. When MIRTEX is called, the address of the next instruction is pushed on stack. MIRTEX pushes all registers on stack, saves the stackpointer in the stackpointer field of the task record. 3.2 The state of a task A task controlled by MIRTEX is in one of the following states: - READY - RUNNING - WAITING
L.J.M. Nieuwenhuis / M I RTEX
196
A task is RUNNING if the processor is allocated to the task. In a single processor system, only one task is RUNNING. A task is WAITING in one of the following cases: -
waiting waiting waiting waiting
for for for for
a V-operation of a semaphore a LEAVE-operation of a region an interrupt a period of time to elapse.
A task is ready if it is not WAITING or RUNNING. MIRTEX selects one of the READY tasks to become RUNNING; the processor will not be allocated to a WAITING task. The task records of none RUNNING tasks are linked in queues. MIRTEX uses 8 ready queues to administrate the READY tasks. Ready queues ] to 7 are the READY tasks with priority I to 7, and ready queue 0 consists of the task record of a NULL task. There is a queue with tasks waiting for an interrupt. Each vector has its own queue. Each task waiting for a period of time to elapse, is in the timer queue.
RUNNING. As a consequence of the queues, the scheduling algorithm can be very simple. The MIRTEX dispatcher searches for an non-empty ready queue starting with the queue of the highest priority. A task record is detached from the first non-empty ready queue. Because of the FIFO principle, the longest WAITING task from the set with currently highest priority is selected. A NULL task in the system guarantees that always one task will be found in the ready queues. The NULL task will become running if no user tasks are READY. It is noted that if all user tasks are WAITING for internal events (i.e. a V- or LEAVEoperation), deadlock occurs.
create
termnat
I•
The control blocks for semaphores, regions and buffers located in the memory space controlled by the user, include queue control blocks (see figure 4).
Figure 5
I States of a
task.
write pointer read pointer occupied
base pointer
counter queue control
write semaphore
queue control semaphore
region
I counter
I
read semaphore ufret
Figure 4 Control blocks for semaphores, regions and buffers.
The state transitions of tasks include the following 'low-level' operations. - CREATE A task record is reserved (on the heap) and initialized. The task record is attached to the ready queue. - CONTINUE
The queue control blocks point to task records waiting for V - o r ENTER-operations. The semaphore control block also includes the semaphore counter containing the current semaphore value. In the region control block, the counter contains the current number of ENTER operations, and the pointer OCCUPIED points to the task record of the task which is currently in the critical region. The buffer control block contains a READ and WRITE semaphore control block, to block a task if the buffer is empty or full. The base, read and write pointer, point to the base, the current read- and write-locations of the buffer page on the heap. 3.3 The scheduling algorithm
The context of the currently RUNNING task is saved. A READY task is selected, the context is loaded and the task continues. -PRE-EMPT The task record of the RUNNING task is attached to the ready queue. - WAlT The task record of the currently RUNNING task is attached to the queue of a semaphore, region, timer or interrupt. - SIGNAL The task record of a WAITING task is detached from the queue of a semaphore, region, timer or interrupt and attached to the ready queue. - TERMINATE
Each time MIRTEX is called, the state of some task may change. MIRTEX evaluates the change and, possibly, the processor is withdrawn from one task and allocated to another. Such a change of processor allocation is called a context switch or dispatch. The scheduling algorithm defines the strategy for selection of a READY task to become
The currently RUNNING task is terminated. The task record is disposed (on the heap). START and EXIT create and delete a task. If the priority of a newly created task is greater than the priority of the RUNNING task, the RUNNING task is pre-empted and the new task continued.
L.J.M. Nieuwenhuis / MIR TEX
197
If the priority of the RUNNING task is lowered by a call for SET PRIORITY, the RUNNING task is pre-empted and the task with highest priority continued. A call for DELAY puts the RUNNING task in the timer queue. The timer field in the task record is preset to the delay time of the DELAY call. Each call for the entry CLOCK will decrement the time field of all delayed tasks and, on zero, the WAITING task becomes READY. A call for CLOCK always pre-empts the RUNNING task. Hence, processor time is devided among tasks with currently highest priority.
One document figure 6):
The synchronization operations P and ENTER attach task records to the queues if the tasks have to wait. The operations V and LEAVE may change WAITING tasks into READY tasks. If the priority of these tasks is greater than the priority of the currently RUNNING task, the RUNNING task is pre-empted and the task, blocked by a semaphore or region, becomes RUNNING.
The machine classification is executed in parallel with step 3. The video take and the machine classification have to be completed before the document arrives in the code printer unit.
4. PRACTICAL EXPERIENCE 4.1 The ZSO version of MIRTEX The Z80 version of MIRTEX has been in use since the summer of 1982. The executive is the nucleus of a real-time program, controlling a transport unit for paper documents. The transport unit is part of the CODAL: a machine, developed by the Dutch PTT for verification of documents by automatic reading of handwritten figures. The documents are verified by comparing the machine classification with the classification coded in a standardized codeline on the document.
is processed as follows
]. feed the document (document feeder)
into the transporter
2. take a video image of the document scanner) 3. read the code of the document 4. print a code on the document
document
video scanner
code reader
(video
(code reader) (code printer)
5. put the document in the OK or NOT-OK pocket (pocket selector).
During runtime, the CODAL transporter contains up to 8 documents which are fed through the machine at a speed of 5 documents per second. Each document is in a different stage of processing. The microprocessor system consists of 16 kbytes ROM and 8 kbytes RAM, a real-time clock with a period of 7.8 msec., and 5 parallel I/0 devices. The program consists of approximately 20 tasks. 4.2 The M6809 version of MIRTEX The M6809 version of MIRTEX was introduced in the surmmer of ]983. The executive will be used with a single board computer system and user programs written in Pascal. No practical experience has been obtained with the combination of MIRTEX and Pascal.
The automatic classification is executed by a mini computersystem; the microprocessor system controls the units of the transporter and protects documents against jamming. The same microprocessor system controls a keyboard, textprinter, buttons and control panels.
feeder
(see
I;°'ne,
_1classif -I unit F i g u r e 6 The CODAL machine.
pocket
selector
ok not o k
L.J.M. Nieuwenhuis / MIRTEX
198
5. REFERENCES 1
Brinch Hansen, Per, Operating System Principles (Printice Hall, New Yersey,
2
Lister, A.M., Fundamentals of Operating Systems (The Macmillan Press, London, 1975)
3
Dijkstra, E.W., Hierarchical ordering of sequential processes (Acta Informatica, Springer Verlag, 1971)
4
Wirth, N., Modula: a language for modular multiprogramming (Software, Practice and Experience 7, 1977, 3-35)
5
Wirth, N., Algorithms and datastructures is programs (Printice Hall, New Yersey, 1976)
;973)
Bart Nieuwenhuis was born in Enschede, The Netherlands, in 1955. He received his M.Sc. in Electrical Engineering (Control Theory and Automation) from Twente University of Technology, in 1980. Since ]980, he is working at the Dr. Neher Laboratories, the research and development laboratories of the Dutch PTT. His main activities are the application of micro-electronics for process automation projects in behalf of the banking division of the Dutch PTT.