12
Information Processing Letters 22 (1986) 61-72 North-Holland 18 January 1986 EDISON-80, A LANGUAGE FOR MODULAR PROGRAMMING OF PARALLEL PROCESSES Ke-Chang DAI * Jiao-Tung University, Shanghai, China Communicated by M. Paul Received 7 September 1984 Revised 10 April 1985 EDISON-80, a superset of the programming language EDISON, was implemented on an Intel development system. It aims at providing software designers with a programming environment, which combines the benefits of abstraction of high-level languages with those of machine-orientation and is powerful enough to support the development of nontrivial system software with a spectrum of facilities, including parallel processing. Modifications (e.g., the separate compilation facility) are introduced into EDISON-80 to make it more powerful than the original. In spite of being an interpreted language, the resulting EDISON-80 object code is down-loadable and compatible with the existing compiled languages on the system, so that they can be linked together and run on user systems. Experiences of implementation will be reported. Keywords: Programming language, modular programming, separate compilation, conc~wrent statement, conditional critical region, down-loadability I. Introduction Due to the drastic decrease in hardware costs, great attention has been paid in the last two decades to the cost and quality of software. To produce quality software more efficiently and to maintain them easily, a programming environment is needed which will offer software designers a variety of tools (including languages) to support programming at all levels--from simple drivers for peripherals to high-level managers. Hardly any single language can meet this goal, unless the hardware on which the language runs is intentionally tailored to the language, as for exam- ple the 'Lilith' computer to 'MODULA-2'. Even in this case it is still too early to say if it is the most reasonable solution to software development. Here, we must take into account the fact that no lan- * Present address: GMD FIRST Technical University Berlin ZAZ-11, Hardenbergstrasse 29c, 1000 Berlin 12, German Democratic Republic. guage can be implemented equally efficiently on all machines. To make full use of the merits of high-level languages, whose machine-independent notation made it possible for a single programmer to write in one year a nontrivial program like a compiler or an operating system that is both understandable and reliable, and yet retain the efficiency of ma- chine-oriented languages at the same time, it is desirable to implement high-level languages that allow the user to write parts of a program in other languages. Modern languages, like ADA, are in fact proposed to include such facilities at implementa- tion. This work is an attempt to implement a pro- gramming language as a base for building up an environment to support programming nontrivial tasks for microcomputer systems. The Intel devel- opment system is used as a vehicle. It is, in fact, also a partial aspect of a fairly general problem, namely the optimal organization of language tools on small--possibly distributed--systems. 0020-0190/86/$3.50 © 1986, Elsevier Science Publishers B.V. (North-Holland) 61

Edison-80, a language for modular programming of parallel processes

Embed Size (px)

Citation preview

Page 1: Edison-80, a language for modular programming of parallel processes

Information Processing Letters 22 (1986) 61-72 North-Holland

18 January 1986

EDISON-80, A LANGUAGE FOR MODULAR P R O G R A M M I N G OF PARALLEL P R O C E S S E S

Ke-Chang DAI *

Jiao-Tung University, Shanghai, China

Communicated by M. Paul Received 7 September 1984 Revised 10 April 1985

EDISON-80, a superset of the programming language EDISON, was implemented on an Intel development system. It aims at providing software designers with a programming environment, which combines the benefits of abstraction of high-level languages with those of machine-orientation and is powerful enough to support the development of nontrivial system software with a spectrum of facilities, including parallel processing. Modifications (e.g., the separate compilation facility) are introduced into EDISON-80 to make it more powerful than the original. In spite of being an interpreted language, the resulting EDISON-80 object code is down-loadable and compatible with the existing compiled languages on the system, so that they can be linked together and run on user systems. Experiences of implementation will be reported.

Keywords: Programming language, modular programming, separate compilation, conc~wrent statement, conditional critical region, down-loadability

I. I n t r o d u c t i o n

Due to the drastic decrease in hardware costs, great attention has been paid in the last two decades to the cost and quality of software. To produce quality software more efficiently and to maintain them easily, a programming environment is needed which will offer software designers a variety of tools (including languages) to support programming at all levels- - f rom simple drivers for peripherals to high-level managers.

Hardly any single language can meet this goal, unless the hardware on which the language runs is intentionally tailored to the language, as for exam- ple the 'Lilith' computer to 'MODULA-2'. Even in this case it is still too early to say if it is the most reasonable solution to software development. Here, we must take into account the fact that no lan-

* Present address: G M D FIRST Technical University Berlin ZAZ-11, Hardenbergstrasse 29c, 1000 Berlin 12, German Democratic Republic.

guage can be implemented equally efficiently on all machines.

To make full use of the merits of high-level languages, whose machine-independent notation made it possible for a single programmer to write in one year a nontrivial program like a compiler or an operating system that is both understandable and reliable, and yet retain the efficiency of ma- chine-oriented languages at the same time, it is desirable to implement high-level languages that allow the user to write parts of a program in other languages. Modern languages, like ADA, are in fact proposed to include such facilities at implementa- tion.

This work is an attempt to implement a pro- gramming language as a base for building up an environment to support programming nontrivial tasks for microcomputer systems. The Intel devel- opment system is used as a vehicle. It is, in fact, also a partial aspect of a fairly general problem, namely the optimal organization of language tools on smal l - -possibly distr ibuted--systems.

0020-0190/86/$3.50 © 1986, Elsevier Science Publishers B.V. (North-Holland) 61

Page 2: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

2 Choice of the language

A jumbo language like ADA is clearly not a realistic basis for a programming environment on a small system with 8-bit microprocessors. Its complexity requires for its compilation, and often at runtime, a large memory or frequent access to secondary storages. Besides, many of its elements are unnecessary for development systems. A sim- ple and powerful language is a suitable solution. The reason for emphasizing simplicity is that pro- grammers can tackle more complex jobs and com- plete them more reliably and efficiently only if they fully understand their tools. To support well- structured programming at an abstract level, in- cluding the support of parallel programming, the language is expected to contain adequate linguistic constructs to depict them. These linguistic con- structs or elements should be flexible and easy to assemble, so that their combination offers the pro- grammers the possibility to unfold their creative ability rather than to restrict their inventiveness.

The programming languages CONCURRENT PAS- CAL and MODULA support both modularity and concurrency and have indeed had a dramatic im- pact on developing both simple and correct oper- ating systems and real-time systems for minicom- puters. However, these languages are based on somewhat complicated concepts, and provide users with a number of specialized mechanisms to cover the programming needs. It is evident that both have the shortcoming that important decisions which have great influence on the system perfor- mances are not made by software designers but by the language implementor.

After a careful study of several modern lan- guages, EDISON was chosen. The reasons are the following.

(1) Four user-definable type declarations are provided by EDISON. These type declarations im- prove readability and also help to avoid certain programming errors by allowing profound type checking at compile time.

(2) With the help of the structure 'module' , abstract data types are easy to construct. In EDI- SON there is no special mechanism such as moni- tor. A monitor is constructed by using a program- ming style that combines the simpler concepts of

modules, variables, procedures, and WHEN state- ment (see below). The user is not compelled to use the monitor concept; he can construct simpler mechanisms, such as semaphores if it suits his purpose better.

(3) The incorporation of the COBEGIN state- ment permits the programmer to define processes which can be executed simultaneously. An elegant mechanism called conditional critical region (pro- posed in 1972 by C.A.R. Hoare) is used for pro- cess scheduling. In EDISON it appears in a simple form in the WHEN statement; it reads:

when B do statement list end

The execution of all WHEN statements takes place strictly one at a time. The implementation of con- currency will be discussed in greater detail in Section 5.4.

(4) Type relaxation provides an escape from the limitations of the language. It enables other- wise unallowed operations on variables of differ- ent types, as long as they have the same size in memory. It makes the language fairly flexible and is especially useful for writing I / O routines.

(5) The introduction of 'constructor' makes it easy to build up structured variables of arbitrary type, even if they are of complicated types. Assign- ment of one structured variable to another varia- ble of the same type is allowed in this language.

In conclusion, EDISON possesses many im- portant merits of modern languages. It is power- ful, flexible, and above all it is simple to under- stand and compact to implement on a small sys- tem with 64k bytes memory.

3. Extending EDISON to EDISON-80

Although EDISON is a good language, it still needs improvements to serve our purpose.

3.1. Separate compilation and change of the definition of 'program'

The separate compilation facility is of growing importance for software designers today, and has therefore been included in almost all modern pi'o- gramming languages. The main reasons are as follows.

62

Page 3: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

(a) Error-free parts of the program need not be continually recompiled.

(b) With well-defined interfaces a program can be divided into smaller modules, which can more easily be programmed, compiled, debugged and tested separately, and then linked to become an executable program. This modular programming technique has become a convention nowadays and is absolutely necessary for nontrivial projects.

(c) Program modules can easily be put into a program library, so that they can be placed at the disposal of other users a n d / o r be used by other programs.

(d) The end product (executable program) does not have to be comprised of modules which are translated from source programs of the same lan- guage. As long as the object modules to be linked are compatible with each other, one can choose the most appropriate language to program individual modules.

For systems with limited main memory the following factor plays an important role.

(e) Large programs, which are built up in mod- ules, can be compiled on small systems without table-overflow or excess of other limits at compila- tion-time. The resulting programs can then run on small systems with the help of overlay techniques or virtual memory.

Unfortunately, EDISON has no proper separate compilat ion ability, for only library procedures may be compiled separately. A program is defined in EDISON as a single complete procedure with preceding optional constant and type declarations (so-called initial declarations). Fig. 1 shows the structure of a typical EDISON program.

As a means for abstraction in a programming language, a procedure is comprised of four ele- ments: its name, the parameter specification, a body and an environment. However, in EDISON,

the outermost procedure (the program procedure)

const nl = char(10); l inelength = 132 array line [1 :linelength] (char) proc backup(proc writetext(text: line))

begin

end "backup"

Fig. ]. Example of an EDISON program.

has no explicit environment, for the initial declara- tions only serve to inform the compiler of the attributes of the possible parameters in the outer- most procedure head. These declarations create no objects like variables or procedures, which can be referenced, updated or called in the 'program' procedure. The only way to make use of other programs is to call them as library procedures as a whole. The calling program may pass its local objects (variables and procedures) as arguments to the called program so that these may be accessed to within the called program. But there is no possibility for the calling program to make access to local objects in the called program. The lack of facilities to form an adequate environment for the 'program' procedure restricts the possibility to im- port object from other compilation units. In fact, all EDISON PROGRAMS (including the compiler) are treated as library procedures, which are called by the operating system and loaded dynamically to the memory at run time. This results in a long 'prefix' (parameter list) containing all the operat- ing system objects, which are used in the program. The compiler, for example, inherits a prefix of three variables and thirty-three procedures from the operating system. This produces, in turn, ob- ject codes of the kind 'parameter procedure calls', which is inefficient to interpret [4].

Like conventional procedures, a 'program' pro- cedure also delimits scope. Instances of local ob- jects exist only for the period when the procedure is executed by procedure call, and disappear when the procedure terminates. This dynamic nature of the local objects thus prevents them from being exported to the surrounding environment.

In short, the definition of a program as a com- plete procedure restricts EDISON programs in mak- ing access to individual objects declared in other programs, which is essential for modular program- ming.

In contrast to a procedure, a module constitutes a wall around its local objects whose transparency is strictly under the control of the programmer. Objects local to a module are said to be at the same scope level as the module. They can be considered as being local to the immediate sur- rounding environment but residing within a more restricted scope. They exist as long as their im-

63

Page 4: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS

Table 1 Main differences between EDISON and EDISON-80

18 January 1986

Features Languages

EDISON

Separate compilation Not implemented facility

Access to external variables Not implemented

Source inclusion facility Not implemented (INCLUDE)

Compiler,options for Simple controlling listing form & output files

Operations on arrays of =, < > characters (string)

Input forms of numerals Octal, decimal

EDISON-80

Implemented

Implemented

Implemented

13 controls implemented

(e.g., no-object, pagewidth etc.)

the latter two make the search in a binary tree much easier

Octal, decimal, binary, hexadecimal

Interrupt Not allowed Allowed

mediate surrounding environment exists and is therefore exportable. By extending the 'module ' concept in EDISON to include ' p rogram module ' , their local objects can simply be exported to their invisible environment under the programmer 's

control. In EDISON-80 a program is therefore composed

of one or more compila t ion units, called program modules ( thereafter simply modules). Fig. 2 shows the structure of the above EDISON program rewrit- ten in EDISON-80.

In order to construct an executable program, one of the modules must be a main module. Only

module backup const nl = char(10); linelength = 132 array line [1 :linelength] (char) • proc backup (proc writetext(text: line))

begin

end begin

skip end backup

Fig. 2. Example of an EDISON-80 program (a submodule).

this module may contain executable s ta tements at the module level. All other modules are submod- ules, which contain declarat ions only. The initiali- zation of objects in the submodule can be fullfilled by an exportable procedure on the module level.

A reserved word MAIN is in t roduced into EDI- SON-80 to distinguish the main module from its submodules . A special byte in the 'mo du le end record' of the object file will be set to one for the main module. This byte will be checked at l ink-time to see if one and only one of the input modules in the link-list is a main module.

3.2. Another meaning for "lib" and " * " (export symbol)

A library procedure declarat ion has in EDISON the following form:

Library procedure declaration: ' l ib' procedure heading '[ ' library key '] '

This definition implies that a library procedure, which has the form of a separate program, can have no direct access either to global variables or to global procedures. To enable the sharing of

64

Page 5: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

objects between program modules, it must be changed correspondingly.

In EDISON-80, "lib" was extended to include all the facilities of the 'external' at tr ibute in PLM-80. This means that not only procedures may have the import-prefix "lib", but also variables. The export symbol " ' * " at the module level means PUBLIC. "lib" declarations are only allowed at the module level. This restriction is reasonable because the importation to internal modules is controlled by the scope rules. " l ib" and " *" are mutually exclu- sive in EDISON-80.

As the tasks of searching program libraries for modules, exportable procedures or variables are taken over by the existing linker for this imple-

Command ~ I

q

1_.. Table Routine

1- I TABLE id$ptr L

symbols

COMMAND ANALYSE

lJ ANALYSER

1.1 E-CODE

GENERATOR

U

Error Routines ~I

next symbols

E-code listing

E-code

E-code

object code

Fig. 3. Structure of the EDISON-80 compiler.

mentation, the 'library key' has actually lost its meaning. They are nevertheless retained here to inform the compiler if the procedure being im- ported is written in EDISON-80.

By means of the above and some other mea- sures (e.g., adhering to parameter passing conven- tions), the existing library procedures or system utilities can be called from EDISON-80 program.

3. 3. Some other extensions

Further extensions are made in EDISON-80 to make the compiler more comfortable for users. Table 1 lists the differences between EDISON and EDISON-80. Some of them will be discussed in more detail later.

ERROR error message

~ Error Routines

SCANNER L next$ch F i

source line

l SOURCE " ~ HANDLER

L ~ w I E-CODE

error listing

program listing

- h I LISTING|

zE-CODE in Intel relocatable object format

65

Page 6: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

4. EDISON-80 compiler

4.1. Structure of the EDISON compiler

The EDISON-80 compiler for boots t rapping is written in PLM-80 and is programmed in modules. It consists of a main module " R o o T " and three overlays. The "ROOT" controls the execution of the compilation. Fig. 3 shows the structure of the EDISON-80 compiler.

Wheo compilat ion begins, the " R o o T " loads the first overlay to analyse the rest of the com- mand invoking the compilation and sets the con- trol parameters (object, pagewidth etc.) accord- ingly if the comm and is correct. It then loads the second overlay to do lexical, syntactic, and semantic analyses.

A listing file is meanwhile generated to provide the users with compilation informat ion and an intermediate code with unresolved labels is output to a temporary file. To check the intermediate code, the control word EDICODE can be used to create a file of E-CODE listing which has the same name as the source file but with the extension name E. This is done by pass 1 of the compiler. If there is no error in the source program and object code generation is not suppressed by the command control word NOOBJECT, the third overlay is loaded and pass 2 begins. It scans the intermediate code once, replaces labels with corresponding informa- tion and produces a relocatable object code file in Intel convention with necessary informat ion for LINKER and LOCATER.

Table 2 Sizes of the individual modules in pass one

Module name Code Data Max. stack

ROOT 145 3100 8 SOURCEHANDLER 5579 450 18 DECLANALYSE 6068 121 53 STATANALYSE 9186 53 128 TABLE 3871 7833 19 SCANNER 2054 735 10 EGENERATOR 4495 911 16 ENDP 619 47 8

Sum 32017 13250 128

Table 2 shows the size of the individual mod- ules of pass 1, the biggest pass of the compiler. Together with some system and PLM-80 library subroutines it occupies almost the whole user memory area of 48k bytes of the system.

4.2. E-CODE

In order to make EDISON-80 more portable, an intermediate code 'E-CODE' is used, which can either be directly interpreted or translated in a later pass to machine code. In this implementation the interpreted approach is chosen because the semantic gap between the language and the system hardware is so wide that it is hardly possible to produce optimized machine code, which can be run efficiently on Intel development systems. Using the interpreting method it is easy to 'optimize' the interpreter (called KERNEL by Hansen) by hand.

The E-CODE here is quite similar to the EDISON-CODE of Hansen [4]; it is, however, altered in two points:

(i) Hansen implemented EDISON on a PDP-11 machine, which has a special instruction JMP@ (R) + to support the so-called ' threaded code' [1]. The operation codes are in fact addresses of the entry of interpreter routines, and therefore consist of two bytes. As we have no such instruction on Intel 8080, a shorter form of operation codes with one byte was chosen.

(ii) While implementing EDISON-80 we have al- ways borne in mind the criteria that this language must be able to make use of procedures or varia- bles declared in other modules, even if they are programmed in other languages. Some additional E-CODES are implemented to serve this purpose.

- GVAR(ADDR): for addressing variables on module level.

- E X V R ( E X N U M ) : for addressing external variables.

- GCAL(ADDR): for calling procedures de- clared on module level.

- ECLI(EXNUM): for calling lib procedures programmed in EDISON-80. The function of this instruction is like global call. The exter- nal number will be replaced with a relative address at linktime.

- ECL2(EXNUM): for calling non-EDISON-80

66

Page 7: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

lib procedures. Such lib procedures are located in a code segment in the form of machine code. In order to call these procedures, all the parameters must be transferred from the activation record to the 'machine stack' or to certain registers according to Intel conven- tions before control transfer; and after return from the called procedure the activation re- cord must be deleted. PBED: for ending public procedures (see Sec- tion 5.5 for an explanation).

segment, stack segment, and memory segment (see Fig. 4). - All codes of the user programs are loaded in the

code segment. - All variables, which are declared on module

level or which are local variables of nonreen- trant procedures in PLM-80, are located in the data segment.

- The stack segment is used mainly by ASM-80 or PLM-80. EDISON-80 uses this segment only for

5. Execution of an EDISON-80 program

The EDISON-80 program runs with the help of an interpre'ter, called KERNEL. In order to enable the mutual call of procedures of different sources, some measures are necessary.

5.1. Preparation for the execution

The KERNEL is programmed as a normal sub- module and is put in the program library EDISON.LIB. Except for some routines in assembly language, most procedures are first written in PLM-80 and then wholly rewritten in assembly language ASM-80.

Before a program runs, it must first be linked with the LINK command:

LINK (OBJECT FILE LIST), EDISON LIB, SYSTEM.LIB & TO PROGRAM NAME

Here, the object files to be linked may be relocata- ble object files translated from any languages on the system.

The EDISON-80 compiler has a reserved lib pro- cedure named KMAIN which is the main procedure of the KERNEL. It results in the fact that every EDISON-80 object file now contains the external name KMAIN in its external name record. The module KERNEL in the EDISON.LIB, which con- tains the public procedure K_MAIN, is therefore included automatically in the output file of the LINKER. This is then located by the LOCATER.

5.2. Runtime memory organization

0000H

0017H

0018H

003FH 0040H

2FFFH

3000H

387FH

3880H

F6BFH

F6COH

F800H

FFFFH

ISIS INTERRUPT 0,1,2

USER INTERRUPTS 3-7

ISIS RESIDENT AREA

BUFFER AREA

CODE SEGMENT (object code and KERNEL)

STACK SEGMENT

DATA SEGMENT

MEMORY SEGMENT (variable stack for

EDISON-80 modules)

WORKING AREA FOR MONITOR

MONITOR

The user memory on the development system is divided into four segments: code segment, data Fig. 4. Runtime memory organization.

67

Page 8: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

passing parameters while calling non-EDISON-80 procedures. The memory segment means originally the memory part, which is not used by the program. (Its starting address is calculated by LOCATE.) However, it plays an important role in EDISON- 80 because it is used as stack for activation records and intermediate results.

5. 3. Downloadability of the resulted program

It is of great importance for a development system to download the developed programs to user systems so that they can run on them. To reach this goal it is reasonable to make the KERNEL behave like ordinary submodules and be allowed to reside in any place in the code segment.

At the beginning of the program execution, however, control must be passed to the KERNEL, SO that the E-CODE can be interpreted. This is realized by attaching a PREFIX of machine code to main modules (see Fig. 5). The relative address of START is put into the 'module end record' of the object file.

The target of this PREFIX branch is the main procedure KMAXN of the KERNEL (see Fig. 6).

5. 4. Execution of concurrent processes

Initially, an EDISON-80 program is executed as a single process. When the execution reaches a concurrent statement, several processes are created dynamically, and to every process a separate varia- ble stack is allocated.

It can be explained better with the help of a program paragraph and its corresponding E-CODE list (see Fig. 7). This program is adopted from Hansen [3].

A GOTO instruction stands at the beginning of a

E X T R N

START: LXI

LXI

JMP HAUPT: .

KMAIN, FIRST SP, STACK; set stack pointer B, HAUPT; pass parameter KMAIN; jump to KERNEL

E - C O D E i n s t r u c t i o n s

Fig. 5. Prefix of main modules.

concurrent statement, which causes the execution of a CoB~ (COBEGIN) instruction. This instruction possesses several operands, which represent the number of processes to be executed concurrently, the line number of the statement (for errror mes- sage), and a list of process parameters, which are in turn composed of a process constant and the entry of the process. In our case, two processes will be created, with process constants 1, 2 and entry-addresses 02D6H, 02E7H respectively.

The COBG divides the free space of the variable stack evenly among processes (compare Fig. 4). The variable stack is now tree structured, every process has its private variable stack and the previ- ous stack part serves as the stack root. Initial administration information for each process (such as the base address of the most recent activation record of a process, the stack pointer, the stack maximum and program counter value, etc.) is reg- istered in its corresponding process descriptors and these are aligned in a queue. In the case of a multiprocessor system, the processes can now be distributed to or attracted by individual processors according to some strategy for execution. On a single processor system, as in our case, they may run quasi-parallel. This means that one of the processes will be chosen to run according to some rule (in this implementation we simply chose the first process in the list). The process runs until it reaches its end (an ALSO instruction) or a WAIT instruction. The process will then be preempted and another process be resumed. So the processes run until all processes terminate, the execution now continues sequentially again in the context of the root stack.

At the start of every process, a PRX instruction is executed, which checks if the usable stack is big enough to accomodate all the temporary variables of the process. The memory size needed is in- cluded as the first operand in the instruction. If it fails, an error message will be output to CRT, otherwise the process body will be executed.

The last instruction executed by a process is the ALSO instruction, which does one of two things:

- If some other processes are not yet terminated, the descriptor of the given process is removed from the queue (deleted), and another process resumed.

68

Page 9: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETi'ERS 18 January 1986

KMAIN: PROCEDURE(FIRST$E$CODE); DECLARE FIRST$E$CODE ADDRESS; IF FIRST THEN / . FIRST is a global variable showing . /

CALL INITIALIZE$KERNEL,/* if KMAIN be called the first time * / PC = FIRST$E$CODE; DO WHILE MORE$E$CODE;

CALL EXECUTE; END; MORE$EDISON = 0FFH;

END KMAIN;

Fig. 6. Main procedure of KERNEL.

- I f all o ther processes have terminated, the execution continues with the initial process and context.

The WHEN statement in EDISON is an elegant mechanism for process scheduling.

Fig. 8 shows a typical WHEN statement and its E-CODE list.

The execution of a WHEN statement begins with evaluating one or a list of scheduling condit ions (in our case, a single function). If none of the

condit ions yields true, the WAIT instruction is executed, otherwise the WHEN statement termi- nates. The function of WAIT is tO preempt the current process and resume another process. It also enables the return to the start of the WHEN statement when the preempted process is resumed. If several processes need to evaluate scheduling condit ions simultaneously, they will be able to do so one at a time in some fair order (e.g., cyclically). If no other process exists, the scheduling condi-

92 2 93 3 94 2 95 3 96 3 97 3 98 2 99 1

BEGIN COBEGIN 1 DO TYPIST(WORDS); STOP ALSO 2 DO CLOCK(SECONDS) END; IF SECONDS > 0 DO

WRITE(NL); WRITEINT(60* WORDS DIV SECONDS); WRITETEXT(LINE ('WORDS PER MINUTE', NL, '$'))

END END TYPING

(a) Source program of COBEGIN statement.

Addr. 02D3 02D6 02DB 02DE 02E1 02E4 02E7 02EC 02EF 02F2 02F5

Op-code Mnemonics Operands 12 GOTO 02F5 28 PRX 000C LINE: 93 47 GVAR 0019 44 GCAL 01A0 44 GCAL 02B2 01 ALSO 02FF 28 PRX 000C LINE: 94 47 GVAR 001 B 44 GCAL 0223 01 ALSO 02FF 05 COBG 02 01 02D6 LINE:94

02 02E7

(b) E-CODE of the above COBEGIN statement.

Fig. 7. Example of a typical COBEGIN statement and its corresponding E-CODE.

69

Page 10: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

tions will be evaluated repeatedly until it yields true.

Apparent ly, this WHEN sta tement uses a polling approach. The preference for this approach is based on the assumption that with multiprocessor systems composed of inexpensive microprocessors, the overhead for evaluating scheduling conditions is tolerable. The EDISON system even goes so far as to exclude the use of the existing hardware inter- rupt mechanism completely. The reasons are partly due to the following: - E D I S O N has no way to set in terrupt vectors. - EDISON has no facility to link library programs

to the main program statically and all the varia- bles are allocated dynamical ly in the variable stack. Therefore, the existing EDISON system of Hansen does not permit concurrent processes to call l ibrary procedures, otherwise the program stack will change during the execution of a

concurrent statement, which often leads to un- predictable results. If interrupt routines are pro- g rammed in the form of l ibrary programs, the result may also be unpredictable.

However, the interrupt is a fine hardware mecha- nism with many applications. For example, it is of ten used to realize emergency exits and is espe- cially useful for real-time systems. Since EDISON-80 allows procedures to be writ ten in foreign lan- guages and global variables are located in the data segment, interrupts are allowed in EDISON-80. But, for the moment , an interrupt is not supported as a process, and is therefore said to be supported only partially.

Furthermore, programming interrupt routines as processes are also realizable if an addit ional i tem is added to process descriptors to show if the process is an interrupt routine, and corresponding changes are made in the interpretat ion of WAIT and ALSO.

48 3 PROC READ 49 4 BEGIN 50 5 WHEN SENSE(STATUS, READY) DO 51 5 OBTAIN(BUFFER, CH:INT) 52 4 END; 53 4 CH := CHAR(INT(CH) MOD 128); 54 4 IF C H = CR DO CH := NL END; 55 4 WRITE(CH) 56 3 END

(a) Source program of a WHEN statement.

Addr. Op-code Mnemonics Operands 0146 12 GOTO 019D 0149 27 PROC 0000 000A 0152 2F WHEN 0153 2B VSPC 0002 0156 06 CNST FF70 0159 06 CNST 0080 015C 53 EFK1 0004 0000 0161 0A DO 0172 0164 06 CNST FF72 0167 34 GVAL 0005 016A 46 ECL2 0004 0000 016F 0B ELSE 0175 0172 2E WAIT 0153 0175 OF ENDW

0010 LINE :49

(b) E-CODE of the above W'HEN statement.

Fig. 8. Example of a typical WHEN statement and its corresponding E-CODE.

70

Page 11: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

In EDISON-80 all the E-CODE interpretation routines, which concern concurrent operations, were built into a separate module, so that they could easily be extended or rewritten in order to implement different versions with various schedul- ing strategies to suit individual purposes. Here, we again see the merits of modular programming.

5.5. Access to and from foreign modules

As just mentioned, all the variables on the module level are statically located in the data segment. Access to them from different modules causes no extra problems.

Calls of foreign procedures from EDISON-80 are realized with the help of the E-CODE ECL2.

It is difficult, however, to call EDISON-80 proce- dures from foreign modules, because the control cannot be passed directly to E-CODE procedures.

The KERNEL must therefore be able to fulfill the following tasks: - Before interpreting the actual E-CODE of the

procedure, the KERNEL must first create an activation record for the procedure in the varia- ble stack (in memory segment), transfer param- eters from the stack segment to the activation record and put the dynamic link to a LINK STACK, which is declared as a global array-vari- able in KERNEL. All this is done by the sub- routine EDISONSENTRY. After that, the control will be transferred to KMAIN with the entry of the procedure as parameter.

- At the end of the procedure, that is, when executing the E-CODE PBED, the dynamic link of the actual activation record will be com- pared with the top of DNK$STACK. In case of equality, the LINK$STACK will be decremented DNK$STACK$INX -- 1) and the boolean variable MORE$EDISON be set to FALSE. The control will then be transferred from KMAIN to the calling program (compare Fig. 6).

To call EDISON-80 procedures in programs whose main module is not programmed in EDISON-80, the following conventions must be observed (in PLM-80 or ASM-80 modules): - At the beginning of the main module, the exter-

nal procedure INITIALSEDISON should be called to initialize the KERNEL.

- All EDISON-80 procedures to be called should be declared as external variables instead of ex- ternal procedures in the calling modules, so that they may be used as argument in a procedure call.

- A 'replacement procedure' should be declared for each procedure to be called. These replace- ment procedures have two more parameters than the original ones. It can be schematically de- scribed as follows:

EDIPROCI: PROCEDURE(PAR1, PAR2 ..... PARA- METER$COUNT, PROCEDURE$NAME) EXTERNAL; DECLARE(PAR1, PAR2 . . . . . PARA- METER$COUNT, PROCEDURES NAME) ADDRESS;

END EDIPROC1 ;

In another separate module all these procedures will be declared public as follows (without parameters):

EDIPROCI: PROCEDURE PUBLIC; GOTO EDISON$ENTRY;

END EDIPROC1 ;

Instead of direct calls of the external EDISON-80 procedures, the corresponding replacement pro- cedures will be called in the program. Beside the original parameters, two more parameters will be used to stand for the count of the original parameters and the entry address of the EDI- SON-80 procedures.

6. C o n c l u s i o n s

Reasonable programming environments are ex- pected to offer the software designers a variety o f programming languages to meet different require- ments. The cooperation of languages at different levels (from machine-oriented language to high- level languages with complex abstractions) often leads to programs whch have both the merits of abstraction and that of machine-orientation. EDI- SON-80 was implemented on the Intel MDS with this intention in mind.

Although an interpretation approach was cho- sen to execute the EDISON-80 programs, it is suc- cessful in making EDISON-80 fully compatible with

7]

Page 12: Edison-80, a language for modular programming of parallel processes

Volume 22, Number 2 INFORMATION PROCESSING LETTERS 18 January 1986

other MDS-languages. All the languages in the system appear equal to the users. The user can call any existing procedures (native or foreign) from EDISON-80 without any problem, as long as he sets the 'library key' properly.

The programming environment is un i form and transparent to him. Only if EDISON-80 procedures are called from foreign modules - - in rare cases-- must he observe some conventions.

The extension of the 'module ' concept to 'pro- gram module ' plays an important role in effecting all these improvements.

It is no less important to ment ion that the KERNEL is not only downloadable, but also con- tains no system-dependent standard procedures, a feature not realizable for the original EDISON [4, p. 178]. In other words, for single processor systems, the KERNEL is only processor-dependent and not system-dependent.

As mentioned before, the current version of the EDISON-80 compiler is written in P L / M and is used as a boots trapping compiler. Since a compati- ble P L / M exists for the Intel 8086, this compiler can be directly realized for the 8086. By rewriting (translating) this compiler in EDISON-80 and using techniques similar to those used for PASCAL [5], EDISON-80 is also easily portable to other processors.

'Standard procedures' , which already exist on user systems, can be declared (if necessary, in rewritten form) as lib procedures in EDISON-80. These make EDISON-80 more flexible and portable than EDISON.

Acknowledgment

I would like to express my most grateful thanks to Prof. Dr. W. Thomassen for the generous sup- port and advice he gave in the course of this project, and to Prof. Dr. D. Maass both for his encouragement and the valuable suggestions which have contributed greatly to this work. I am also indebted to Prof. Dr. K. Hager for his constant help.

References

[1] J.R. Bell, Threaded code, Comm. ACM 16 (6) (1973) 370-372.

[2] P. Brinch Hansen, The Architecture of Concurrent Pro- grams (Prentice-Hall, Englewood Cliffs, N J, 1977).

[3] P. Brinch Hansen, Edison programs, Software-Practice and Experience 11 (4) (1981) 397-414.

[4] P. Brinch Hansen, Programming a Personal Computer (Prentice-Hall, Englewood Cliffs, N J, 1983).

[5] C. Ghezzi and M. Jazayeri, Programming Language Con- cepts (Wiley, New York, 1982).

[6] C.A.R. Hoare, Monitors: An operating system structuring concept, Comm. ACM 14 (10) (1974) 549-557.

[7] ISIS-II User's Guide, lntel Corporation, Santa Clara, CA, 1981.

[8] MCS 80/85 Relocatable Object Module Formats, lntel Corporation, Santa Clara, CA, 1981.

[9] N. Wirth, The personal computer Lilith, lnstitut fi~r Infor- matik, ETH Ziarich, 1981.

[10] N. Wirth, Programming in MODULA-2 (Springer, Berlin, 1983).

72