The ModulaTor logo 7KB

The ModulaTor

Oberon-2 and Modula-2 Technical Publication

Erlangen's First Independent Modula_2 Journal! Nr. 7/Aug-1992


Test Program for ISO Modula-2's Processes & Semaphores

by Elmar Baumgart, ModulaWare

Here are the "final" definitions modules Processes and Semaphores of the ISO Modula-2 Standard Library (some updates/minor renamings by Pat Terry, Jul-92; revised and early 1993). No guarantee is given that these definitions exactly match those of the soon-to-be-released Standard.


___________________________________________________________________

DEFINITION MODULE Processes;

  (* This module allows concurrent algorithms to be expressed using processes. A process is
     a unit of a program that has the potential to run in parallel with other processes.
  *)

IMPORT SYSTEM;

TYPE
  ProcessId;                      (* Used to identify processes *)
  Parameter     = SYSTEM.ADDRESS; (* Used to pass data between processes *)
  Body          = PROC;           (* Used as the type of a process body *)
  Urgency       = INTEGER;        (* Used by the internal scheduler *)
  Sources       = CARDINAL;       (* Used to identify event sources *)
  ProcessesExceptions =           (* Exceptions raised by this module *)
    (passiveProgram, processError);

(* The following procedures create processes and switch control between them. *)

PROCEDURE Create (procBody: Body; extraSpace: CARDINAL; procUrg: Urgency;
                  procParams: Parameter; VAR procId: ProcessId);
  (* Creates a new process with procBody as its body, and with urgency and parameters
     given by procUrg and procParams.  At least as much workspace (in units of
     SYSTEM.LOC) as is specified by extraSpace is allocated to the process.
     An identity for the new process is returned in procId.
     The process is created in the passive state; it will not run until activated.
  *)

PROCEDURE Start (procBody: Body; extraSpace: CARDINAL; procUrg: Urgency;
                 procParams: Parameter; VAR procId: ProcessId);
  (* Creates a new process, with parameters as for Create.
     The process is created in the ready state; it is eligible to run immediately.
  *)

PROCEDURE StopMe ();
  (* Terminates the calling process.
     The process must not be associated with a source of events.
  *)

PROCEDURE SuspendMe ();
  (* Causes the calling process to enter the passive state.  The procedure only returns
     when the calling process is again activated by another process.
  *)

PROCEDURE Activate (procId: ProcessId);
  (* Causes the process identified by procId to enter the ready state, and thus to become
     eligible to run again.
  *)

PROCEDURE SuspendMeAndActivate (procId: ProcessId);
  (* Executes an atomic sequence of SuspendMe() and Activate(procId). *)

PROCEDURE Switch (procId: ProcessId; VAR info: Parameter);
  (* Causes the calling process to enter the passive state; the process identified by procId
     becomes the currently executing process.
     info is used to pass parameter information from the calling to the activated process.
     On return, info will contain information from the process that chooses to switch back to
     this one (or will be NIL if Activate or SuspendMeAndActivate are used instead of
     Switch).
  *)

PROCEDURE Wait ();
  (* Causes the calling process to enter the waiting state.  The procedure will return when
     the calling process is activated by another process, or when one of its associated
     eventSources has generated an event.
  *)

(* The following procedures allow the association of processes with sources of external
   events.
*)

PROCEDURE Attach (eventSource: Sources);
  (* Associates the specified eventSource with the calling process. *)

PROCEDURE Detach (eventSource: Sources);
  (* Dissociates the specified eventSource from the program. *)

PROCEDURE IsAttached (eventSource: Sources): BOOLEAN;
  (* Returns TRUE if and only if the specified eventSource is currently associated with
     one of the processes of the program.
  *)

PROCEDURE Handler (eventSource: Sources): ProcessId;
  (* Returns the identity of the process, if any, that is associated with the specified
     eventSource.
  *)

(* The following procedures allow processes to obtain their identity, parameters, and
   urgency.
*)

PROCEDURE Me (): ProcessId;
  (* Returns the identity of the calling process (as assigned when the process was first
     created).
  *)

PROCEDURE MyParam (): Parameter;
  (* Returns the value specified as procParams when the calling process was created. *)

PROCEDURE UrgencyOf (procId: ProcessId): Urgency;
  (* Returns the urgency established when the process identified by procId was first
     created.
  *)

(* The following procedure provides facilities for exception handlers. *)

PROCEDURE ProcessesException (): ProcessesExceptions;
  (* If the current coroutine is in the exceptional execution state because of the raising
     of a language exception, returns the corresponding enumeration value, and
     otherwise raises an exception.
  *)

PROCEDURE IsProcessesException (): BOOLEAN;
  (* Returns TRUE if the current coroutine is in the exceptional execution state
     because of the raising of an exception in a routine from this module; otherwise
     returns FALSE.
  *)

END Processes.

___________________________________________________________________

DEFINITION MODULE Semaphores;

  (* Provides mutual exclusion facilities for use by processes. *)

TYPE
  SEMAPHORE;

PROCEDURE Create (VAR s: SEMAPHORE; initialCount: CARDINAL );
  (* Creates and returns s as the identity of a new semaphore that has its associated count
     initialized to initialCount, and has no processes yet waiting on it.
  *)

PROCEDURE Destroy (VAR s: SEMAPHORE);
  (* Recovers the resources used to implement the semaphore s, provided that no process is
     waiting for s to become free.
  *)

PROCEDURE Claim (s: SEMAPHORE);
  (* If the count associated with the semaphore s is non-zero, decrements this count and
     allows the calling process to continue; otherwise suspends the calling process until
     s is released.
  *)

PROCEDURE Release (s: SEMAPHORE);
  (* If there are any processes waiting on the semaphore s, allows one of them
     to enter the ready state; otherwise increments the count associated with s.
  *)

PROCEDURE CondClaim (s: SEMAPHORE): BOOLEAN;
  (* Returns TRUE if the call Claim(s) would cause the calling process to be suspended;
     in this case the count associated with s is not changed. Otherwise returns TRUE and
     the associated count is decremented.
  *)

END Semaphores.

Use_Processes is an amazingly short test program. It uses ISO M2's Std I/O-Lib modules SWholeIO and STextIO to write to the terminal. Use_Processes displays the processes' number (id) on console (see listing below) and is short enough to be able to describe itself. An attempt to provide a detailed description would result in a text that is longer than the program itself :-) Just find out how it works!


MODULE Use_Processes; (* Test program for ISO 10154 Modula-2 Standard Library [Extension] of MaX|MVR V4 Modula-2 Compiler for AXP|VAX/OpenVMS Distribution Kit Copyright (1994-1996) Guenter Dotzel, ModulaWare, http://www.modulaware.com/ This software source code constitutes intellectual property rights of Guenter Dotzel, ModulaWare and is furnished under a Non-Disclosure Agreement and may only be used, processed and stored according to the terms and conditions of this agreement. All rights reserved. Modula-2 example & test program for modules Processes and Semaphores. This program displays the processes' number (id) trace on console. Use_Processes is short enough to describe itself; a description of it's functionality would be longer than the source code. Written by Elmar Baumgart/May-1992. *) FROM STextIO IMPORT WriteLn, WriteString, WriteChar; FROM SWholeIO IMPORT WriteCard; FROM Processes IMPORT Start, StopMe, SuspendMe, ProcessId, Parameter, MyParam; FROM Semaphores IMPORT SEMAPHORE, Create, Claim, Release; FROM SYSTEM IMPORT ADR; (* CAST removed by GD/28-Jul-1992 *) CONST WSP = 100000;(*required on AXP; VAX needs 20000; *) Tasks = 25; OutputPerLine = 10; Iterations = 30; VAR G: INTEGER; gSEMA: SEMAPHORE; Params: ARRAY[1..Tasks] OF INTEGER; PROCEDURE P; VAR i: INTEGER; p: POINTER TO INTEGER; BEGIN p:= MyParam(); FOR i:= 1 TO Iterations DO Act(p^); END; Died(p^); END P; PROCEDURE Act(x: INTEGER); BEGIN WriteCard(x, 6); WriteChar(' '); ConditionalWriteLn; END Act; PROCEDURE Died(x: INTEGER); BEGIN WriteCard(x, 6); WriteChar('#'); ConditionalWriteLn; END Died; PROCEDURE ConditionalWriteLn; BEGIN Claim(gSEMA); INC(G); IF (G REM OutputPerLine) = 0 THEN WriteLn; END; Release(gSEMA); END ConditionalWriteLn; PROCEDURE StartProcess(x, prio: INTEGER); VAR id: ProcessId; BEGIN WriteCard(x, 6); WriteChar('+'); ConditionalWriteLn; Start(P, WSP, prio, ADR(Params[x]), id); END StartProcess; VAR i: INTEGER; BEGIN G:= 0; Create(gSEMA, 1); FOR i:= 1 TO Tasks DO Params[i]:= i; StartProcess(i, 0); END; WriteString(" #Mn#"); ConditionalWriteLn; SuspendMe(); END Use_Processes. _____________________________________________________________________ 1+ 1 2+ 1 1 2 3+ 1 2 1 2 3 4+ 1 2 3 1 2 3 4 5+ 1 2 3 4 1 2 3 4 5 6+ 1 2 3 4 5 1 2 3 4 5 6 7+ 1 2 3 4 5 6 1 2 3 4 5 6 7 8+ 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 9+ 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 10+ 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10 11+ 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 12+ 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 12 13+ 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14+ 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1# 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17+ 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18+ 2# 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19+ 3# 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20+ 4# 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21+ 5# 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22+ 6# 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23+ 7# 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24+ 8# 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25+ 9# 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #Mn# 10# 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 12 13 14 15 16 17 18 19 20 21 22 23 24 25 11# 12 13 14 15 16 17 18 19 20 21 22 23 24 25 13 14 15 16 17 18 19 20 21 22 23 24 25 12# 13 14 15 16 17 18 19 20 21 22 23 24 25 14 15 16 17 18 19 20 21 22 23 24 25 13# 14 15 16 17 18 19 20 21 22 23 24 25 15 16 17 18 19 20 21 22 23 24 25 14# 15 16 17 18 19 20 21 22 23 24 25 16 17 18 19 20 21 22 23 24 25 15# 16 17 18 19 20 21 22 23 24 25 17 18 19 20 21 22 23 24 25 16# 17 18 19 20 21 22 23 24 25 18 19 20 21 22 23 24 25 17# 18 19 20 21 22 23 24 25 19 20 21 22 23 24 25 18# 19 20 21 22 23 24 25 20 21 22 23 24 25 19# 20 21 22 23 24 25 21 22 23 24 25 20# 21 22 23 24 25 22 23 24 25 21# 22 23 24 25 23 24 25 22# 23 24 25 24 25 23# 24 25 25 24# 25 25# EXCEPTION encountered m2-iso-lib-err: passiveProgram %MTK-F-PROCABORT, process 00036718, routine 00065A21 aborted. %MODULA-F-HLTSTMT, HALT statement encountered %TRACE-F-TRACEBACK, symbolic stack dump follows module name routine name line rel PC abs PC EXCEPTIONS RAISEGENERALEXCEPTION 31 00000121 00064B76 PROCESS_SCHEDUL NEXTREADY 266 0000007E 0006590E PROCESS_SCHEDUL STOPTASK 313 000000E8 00065B09 FOREIGN_PROCESS NEWPROCESS 000000B1 000630B1 _____________________________________________________________________________
Module Use_Processes terminates intentionally with an exception. The program was tested under VAX/VMS using ModulaWare's Modula-2 compiler MVR V3.18 and ModulaWare's implementation of the ISO M2 Std Lib, available since Apr-1992.

An Oberon-2 Multi-Programming Excursion

One of the nice features of VMS is that languages can be mixed in applications. So if one provides Oberon-2 symbol files for the modules Processes and Semaphores, module Use_Processes could also be written in Oberon-2 using ModulaWare's new Oberon-2 Compiler H2O V1.0 on VAX/VMS. Here are the [dummy] interface modules Processes and Semaphores (comments cut out, to keep the paper short) and the example and example and test program UseProcesses - all written in Oberon-2. Note, that in contrast to ISO M2, there are no underscores allowed in Oberon-2 identifiers. ISO M2 even allows "_" to be the first character of an identifier; good that the ISO M2 Std Lib doesn't make use of underscores at all.



MODULE Processes; IMPORT CTR; TYPE ProcessId* = POINTER TO ProcessIdDesc; ProcessIdDesc*= RECORD END; (* hidden type *) Parameter* = CTR.ADDRESS; Body* = PROCEDURE; Urgency* = CTR.INTEGER; Sources* = CTR.CARDINAL; ProcessesExceptions* = CTR.ENUM8; CONST passiveProgram*=0; processError*=1; PROCEDURE Create*(procBody: Body; extraSpace: CTR.CARDINAL; procUrg: Urgency; procParams: Parameter; VAR procId: ProcessId); END Create; PROCEDURE Start*(procBody: Body; extraSpace: CTR.CARDINAL; procUrg: Urgency; procParams: Parameter; VAR procId: ProcessId); END Start; PROCEDURE StopMe*(); END StopMe; PROCEDURE SuspendMe*(); END SuspendMe; PROCEDURE Activate*(procId: ProcessId); END Activate; PROCEDURE SuspendMeAndActivate*(procId: ProcessId); END SuspendMeAndActivate; PROCEDURE Switch*(procId: ProcessId; VAR info: Parameter ); END Switch; PROCEDURE Wait*(); END Wait; PROCEDURE Attach*(eventSource: Sources); END Attach; PROCEDURE Detach*(eventSource: Sources); END Detach; PROCEDURE IsAttached*(eventSource: Sources): BOOLEAN; END IsAttached; PROCEDURE Handler*(eventSource: Sources): ProcessId; END Handler; PROCEDURE Me*(): ProcessId; END Me; PROCEDURE MyParam*(): Parameter; END MyParam; PROCEDURE UrgencyOf*(procId: ProcessId): Urgency; END UrgencyOf; PROCEDURE ProcessesException*(): ProcessesExceptions; END ProcessesException; PROCEDURE IsProcessesException*(): BOOLEAN; END IsProcessesException; END Processes. ___________________________________________________________________ MODULE Semaphores; IMPORT CTR; TYPE SEMAPHORE* = POINTER TO SemaphoreDesc; SemaphoreDesc*=RECORD END; PROCEDURE Create*(VAR s: SEMAPHORE; initialCount: CTR.CARDINAL); END Create; PROCEDURE Destroy*(VAR s: SEMAPHORE); END Destroy; PROCEDURE Claim*(s: SEMAPHORE); END Claim; PROCEDURE Release*(s: SEMAPHORE); END Release; PROCEDURE CondClaim*(s: SEMAPHORE): BOOLEAN; END CondClaim; END Semaphores. ___________________________________________________________________ MODULE UseProcesses; (* Oberon-2 Example & test program for ISO Modula-2 Standard library module Processes and Semaphores. This program displays the processes' number (id) trace on console. Copyright (1994-1996) Guenter Dotzel, ModulaWare, http://www.modulaware.com/ This software source code constitutes intellectual property rights of Guenter Dotzel, ModulaWare and is furnished under a Non-Disclosure Agreement and may only be used, processed and stored according to the terms and conditions of this agreement. All rights reserved. Converted from Modula-2 to Oberon-2 from [m2lib]Use_Processes.Mod by GD/28-Jul-1992, 12-Aug-1992 *) IMPORT STextIO, SWholeIO, Processes, Semaphores, S:=SYSTEM; CONST WSP = 20000; Tasks = 25; OutputPerLine = 10; Iterations = 30; TYPE INTEGER=LONGINT; VAR G: INTEGER; gSEMA: Semaphores.SEMAPHORE; Params: ARRAY Tasks+1 OF INTEGER; VAR i: INTEGER; PROCEDURE ConditionalWriteLn; BEGIN Semaphores.Claim(gSEMA); INC(G); IF (G MOD OutputPerLine) = 0 THEN STextIO.WriteLn; END; Semaphores.Release(gSEMA); END ConditionalWriteLn; PROCEDURE Act(x: INTEGER); BEGIN SWholeIO.WriteCard(x, 6); STextIO.WriteChar(' '); ConditionalWriteLn; END Act; PROCEDURE Died(x: INTEGER); BEGIN SWholeIO.WriteCard(x, 6); STextIO.WriteChar('#'); ConditionalWriteLn; END Died; PROCEDURE P; TYPE IntPtr = POINTER TO RECORD p: INTEGER END; VAR p: IntPtr; i: INTEGER; BEGIN p:= S.VAL(IntPtr, Processes.MyParam()); FOR i:= 1 TO Iterations DO Act(p^.p); END; Died(p^.p); END P; PROCEDURE StartProcess(x, prio: INTEGER); VAR id: Processes.ProcessId; BEGIN SWholeIO.WriteCard(x, 6); STextIO.WriteChar('+'); ConditionalWriteLn; Processes.Start(P, WSP, prio, S.ADR(Params[x]), id); END StartProcess; BEGIN G:= 0; Semaphores.Create(gSEMA, 1); FOR i:= 1 TO Tasks DO Params[i]:= i; StartProcess(i, 0); END; STextIO.WriteString(" #Mn#"); ConditionalWriteLn; Processes.SuspendMe(); END UseProcesses.

UseProcesses is the world's first concurrent Oberon-2 program - at least on VAX/VMS systems. When linking UseProcesses, ModulaWare's ISO Modula-2 Standard Library implementation modules is used. The link command is

$ link useprocesses

When run, UseProcesses executes exactly like it's Modula-2 companion Use_Processes.

END Oberon-2 Excursion

Yet Another Process Abstraction

On-top of module Processes and Semaphores we can now define another abstraction layer called CoProcesses, according to Per Brinch Hansen's Parallel Pascal language construct COBEGIN and COEND (see also Roger Henry's MODUS article, Issue 8, May-1988). The example and test module for CoProcesses is called Use_CoProcesses which has the same functionality as Use_Processes above. The output generated is slighty different compared to that of Use_Processes. See listing below. This is due to the fact that the parent process is on hold as long as his childrens are running. The full source code of CoProcesses' implementation module is also provided below.



DEFINITION MODULE CoProcesses;

FROM Processes IMPORT Body, Parameter, Urgency;

TYPE CB;

PROCEDURE CoBEGIN(VAR Block: CB);

PROCEDURE CoStart(
  c:          CB;
  UserProc:   Body;
  Space:      CARDINAL;
  UserParam:  Parameter;
  Importance: Urgency
);

PROCEDURE CoEND(VAR Block: CB);

END CoProcesses.
___________________________________________________________________

MODULE Use_CoProcesses;
(*
  Test program for
  ISO 10154 Modula-2 Standard Library [Extension] of

  MaX|MVR V4 Modula-2 Compiler for AXP|VAX/OpenVMS
  Distribution Kit

Copyright (1994) Guenter Dotzel, ModulaWare
http://www.modulaware.com

This software source code constitutes intellectual property 
rights of Guenter Dotzel, ModulaWare and is furnished under a 
Non-Disclosure Agreement and may only be used, processed
and stored according to the terms and conditions of this agreement.

All rights reserved.

   Example & test program for modules Processes and Semaphores 
   using Per Brinch Hansen's CoBEGIN, CoEND
   parallel process abstraction provided by the example layer CoProcesses.

   This program displays the processes' number (id) trace on console.
   Use_CoProcesses is short enough to describe itself;
   a description of it's functionality would be longer than the source
   code.

   Written by Elmar Baumgart/May-1992. 
*)
FROM STextIO IMPORT WriteLn, WriteString, WriteChar;
FROM SWholeIO IMPORT WriteInt;

FROM Processes IMPORT MyParam;
FROM CoProcesses IMPORT CoBEGIN, CoEND, CoStart, CB;

FROM Semaphores IMPORT SEMAPHORE, Create, Claim, Release;
FROM SYSTEM IMPORT ADR;

CONST 
  WSP = 20000*5; 
  Tasks =  25;

  OutputPerLine = 10;
  Iterations = 30;

VAR
  G: INTEGER; gSEMA: SEMAPHORE;
  Params: ARRAY[1..Tasks] OF INTEGER;
  Block: CB;

PROCEDURE P;
VAR i: INTEGER; p: POINTER TO INTEGER;
BEGIN
  p:= MyParam();
  FOR i:= 1 TO Iterations DO 
    Act(p^); 
  END; 
  Died(p^);
END P;

PROCEDURE Act(x: INTEGER);
BEGIN
  WriteInt(x, 6); WriteChar(' ');
  ConditionalWriteLn;
END Act;

PROCEDURE Died(x: INTEGER);
BEGIN
  WriteInt(x, 6); WriteChar('#');
  ConditionalWriteLn;
END Died;

PROCEDURE ConditionalWriteLn;
BEGIN
  Claim(gSEMA);
    INC(G);
    IF (G REM OutputPerLine) = 0 THEN WriteLn; END;
  Release(gSEMA);
END ConditionalWriteLn;

VAR i: INTEGER;
BEGIN
  G:= 0; 
  Create(gSEMA, 1);

  CoBEGIN(Block);
    FOR i:= 1 TO Tasks DO 
      Params[i]:= i;
      CoStart(Block, P, WSP, ADR(Params[i]), 0);
    END;
  CoEND(Block);

  WriteString("   #Mn#");
  (*Conditional*)WriteLn;
END Use_CoProcesses.
_____________________________________________________________________

     1      1      2      1      2      3      1      2      3      4 
     1      2      3      4      5      1      2      3      4      5 
     6      1      2      3      4      5      6      7      1      2 
     3      4      5      6      7      8      1      2      3      4 
     5      6      7      8      9      1      2      3      4      5 
     6      7      8      9     10      1      2      3      4      5 
     6      7      8      9     10     11      1      2      3      4 
     5      6      7      8      9     10     11     12      1      2 
     3      4      5      6      7      8      9     10     11     12 
    13      1      2      3      4      5      6      7      8      9 
    10     11     12     13     14      1      2      3      4      5 
     6      7      8      9     10     11     12     13     14     15 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16      1      2      3      4 
     5      6      7      8      9     10     11     12     13     14 
    15     16     17      1      2      3      4      5      6      7 
     8      9     10     11     12     13     14     15     16     17 
    18      1      2      3      4      5      6      7      8      9 
    10     11     12     13     14     15     16     17     18     19 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21      1      2      3      4      5      6      7      8      9 
    10     11     12     13     14     15     16     17     18     19 
    20     21     22      1      2      3      4      5      6      7 
     8      9     10     11     12     13     14     15     16     17 
    18     19     20     21     22     23      1      2      3      4 
     5      6      7      8      9     10     11     12     13     14 
    15     16     17     18     19     20     21     22     23     24 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      1      2      3      4      5 
     6      7      8      9     10     11     12     13     14     15 
    16     17     18     19     20     21     22     23     24     25 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      1      2      3      4      5 
     6      7      8      9     10     11     12     13     14     15 
    16     17     18     19     20     21     22     23     24     25 
     1      2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      1      2      3      4      5 
     6      7      8      9     10     11     12     13     14     15 
    16     17     18     19     20     21     22     23     24     25 
     1#     2      3      4      5      6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      2#     3      4      5      6 
     7      8      9     10     11     12     13     14     15     16 
    17     18     19     20     21     22     23     24     25      3#
     4      5      6      7      8      9     10     11     12     13 
    14     15     16     17     18     19     20     21     22     23 
    24     25      4#     5      6      7      8      9     10     11 
    12     13     14     15     16     17     18     19     20     21 
    22     23     24     25      5#     6      7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      6#     7      8      9     10 
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25      7#     8      9     10     11 
    12     13     14     15     16     17     18     19     20     21 
    22     23     24     25      8#     9     10     11     12     13 
    14     15     16     17     18     19     20     21     22     23 
    24     25      9#    10     11     12     13     14     15     16 
    17     18     19     20     21     22     23     24     25     10#
    11     12     13     14     15     16     17     18     19     20 
    21     22     23     24     25     11#    12     13     14     15 
    16     17     18     19     20     21     22     23     24     25 
    12#    13     14     15     16     17     18     19     20     21 
    22     23     24     25     13#    14     15     16     17     18 
    19     20     21     22     23     24     25     14#    15     16 
    17     18     19     20     21     22     23     24     25     15#
    16     17     18     19     20     21     22     23     24     25 
    16#    17     18     19     20     21     22     23     24     25 
    17#    18     19     20     21     22     23     24     25     18#
    19     20     21     22     23     24     25     19#    20     21 
    22     23     24     25     20#    21     22     23     24     25 
    21#    22     23     24     25     22#    23     24     25     23#
    24     25     24#    25     25#   #Mn#
_______________________________________________________________________

IMPLEMENTATION MODULE CoProcesses;
(*
Copyright (1994-1996) Guenter Dotzel, ModulaWare
http://www.modulaware.com/

This software source code constitutes intellectual property 
rights of Guenter Dotzel, ModulaWare and is furnished under a 
Non-Disclosure Agreement and may only be used, processed
and stored according to the terms and conditions of this agreement.

All rights reserved.
*)
FROM Semaphores IMPORT SEMAPHORE, Create, Destroy, Claim, Release;
FROM Processes IMPORT ProcessId, Body, Parameter, Urgency, Start;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;
FROM SYSTEM IMPORT TSIZE;

TYPE 
  CoBlock = RECORD
    ChildPen   : SEMAPHORE;
    ChildMinder: SEMAPHORE;
    Children   : CARDINAL;
  END;

  CB = POINTER TO CoBlock;

VAR
  Parenthood: SEMAPHORE;
  Childhood:  SEMAPHORE;
  Proc:       Body;
  CurrentCb:  CB;

CONST
  CoOpTariff = 1024;

PROCEDURE CoBEGIN(VAR c: CB);
BEGIN
  ALLOCATE(c, TSIZE(CoBlock));
  Create(c^.ChildPen, 0);
  Create(c^.ChildMinder, 0); (* initially claimed *)
  c^.Children:= 0;  
END CoBEGIN;

PROCEDURE CoStart(
  c:          CB;
  UserProc:   Body;
  Space:      CARDINAL;
  UserParam:  Parameter;
  Importance: Urgency
);
VAR id: ProcessId;
BEGIN
  Claim(Parenthood);
  Proc:= UserProc;
  CurrentCb:= c;
  INC(c^.Children);
  Start(Wrapping, Space + CoOpTariff, Importance, UserParam, id);  
END CoStart;

PROCEDURE CoEND(VAR c: CB);
VAR i: CARDINAL;
BEGIN
  IF c^.Children > 0 THEN
    FOR i:= 1 TO c^.Children DO Release(c^.ChildPen);
    END;
    Claim(c^.ChildMinder);
  END;
  Destroy(c^.ChildPen);
  Destroy(c^.ChildMinder);
  DEALLOCATE(c, TSIZE(CoBlock));
END CoEND;

PROCEDURE Wrapping;
VAR 
  UserProc: Body;
  c: CB;
BEGIN
  UserProc:= Proc;
  c:= CurrentCb;
  Release(Parenthood);
  Claim(c^.ChildPen);
  UserProc;
  Claim(Childhood);
  DEC(c^.Children);
  IF c^.Children = 0 THEN
    Release(c^.ChildMinder);
  END;
  Release(Childhood);
END Wrapping;

BEGIN
  Create(Parenthood, 1);
  Create(Childhood, 1);
END CoProcesses.
___________________________________________________________________
All M2/O2 modules above are now part of the ModulaWare's MVR respectively H2O distribution kit. See directories [m2lib] resp. [oli].

H2O

ModulaWare's Oberon-2 Compiler for VAX/VMS by Günter Dotzel, ModulaWare.

Erlangen, Aug-10, 1992

H2O is a new ModulaWare product which belongs to the Moderon-, Obula, Obulon-family of programming languages :-) designed at ETH-Zuerich.

ModulaWare GmbH proudly announces the first version V1.0 of the Oberon-2 Compiler H2O for DEC VAX/VMS. The main features of Oberon-2 are strong type checking, modules with type checked interfaces and separate compilation, type extension (object-orientedness), type-bound procedures (methods), read-only export of variables, support for run-time type tests, compatibility between all numeric types (mixed expressions), and string operations.

H2O is a native-code Oberon-2 compiler for DEC VAX/VMS. The front-end is ETH-Zuerich's portable Oberon-2 compiler OP2 written in an almost Oberon- compatible subset of Modula-2. The back-end of H2O is based upon the proven VAX code-generator of ModulaWare's Modula-2 compiler MVR also written in a subset of Modula-2.

H2O produces standard VAX/VMS object code files with standard call- interface and VMS-debugger information. As with Modula-2, debugger mode/language is set to Pascal. There is no dedicated Oberon-2 [I/O]-library in H2O. However, since H2O generated code can be called from any other language and vice versa under VMS, it is possible to use the ISO Modula-2 Standard Library in Oberon-2. See below. H2O's compilation qualifiers include

/noLog show compilation progress, names of imported modules and file names,

/noQuery explicitly asks for name of symbolic files,

/noSym[=filespec] allow generation of a new symbolic file (only if the export changed) and optionally accepts another file name. The default extension is .SYN,

/noCheck generate run-time tests for array indices, case-statement index, and type-checked pointers,

/noDebug generate VMS-debugger symbolic data into object file,

/noOmit_module_name omit the "ModuleName." prefix for exported procedures (external references),

/noForeign_code generate code which is AST-save,

/noModule_name_separator[="x"] use "x" instead of "." in ModuleName.ProcedureName for external references of exported procedures.

/noMachine_code generate symbolic assembly listing of the code generated in addition to source code listing (use with /Listing)

/noCross_reference generate cross reference listing in addition to the source code listing (not yet implemented),

/noListing[=filespec] generate source code listing into an optionally specified filespec,

/noObject[=filespec] generate object file into optionally specified filespec,

/noTransfer_vectors generate transfer vectors for VMS' shareable images.

In the first version of H2O it is only possible to import Oberon-2 modules in Modula-2 via dummy definition modules/symbol files or via so-called foreign definition modules, because MVR can't process H2O's symbol-files and vice versa. Note, Oberon-2's symbol files are produced from marked identifiers in the [implementation-]module; there is no direct equivalent of Modula-2's definition module in Oberon-2.

How can you use Modula-2 and other separate library modules in Oberon-2?

Most Modula-2 definition modules are easily converted to Oberon-2 symbol files by deleting the keyword DEFINITION, adding an asterisk "*" after each identifier, converting enumeration types to constants, adding END procname after each PROCEDURE procname( ... ): ... declaration and finally compiling this new module using H2O which generates an Oberon-2 symbol file. Such modules can be imported in Oberon-2 modules. At link time, the object code of the corresponding Modula-2 implementation module from LNK$LIBRARY (e.g.: from MOD$SYSTEM:Modula.OLB) is used.

This allows to import the ISO Modula-2 Standard I/O-, string conversions-, mathematical-, string handling-, system clock-, and last but not least the concurrent processes- Library in Oberon-2 programs.

Interface conversion from Modula-2 to Oberon-2 4

An example serves to illustrate the conversion of a Modula-2 definition module to an Oberon-2 dummy (means no implementation) interface module. First an M2 definition module x.def then the corresponding O2 dummy interface module called x.mod is shown. x.mod must be compiled with the O2 compiler to produce an O2 symbol file x.syn):


 DEFINITION MODULE x;
   CONST y=123; 
   TYPE e=(a,b,c); 
   PROCEDURE z(x: INTEGER): REAL; 
 END x.

 MODULE x;
   CONST y*=123;
   TYPE e*=SHORTINT; (* enumeration type *)
   CONST a*=0; b*=1; c*=2;
   PROCEDURE z*(x: LONGINT): REAL; 
   END z;
 END x.
Example import of module x into the O-2 module usex:

  MODULE usex;
    IMPORT M2lib:=x;
    VAR r: LONGREAL;
  BEGIN
    r:=M2lib.z(M2lib.y)
  END usex.
Example command sequence to compile, link and execute usex:

  $copy [m2lib]x.def x.mod
  $edit x.mod          ! manual conversions from M2 def. to O2 mod.
  $h2o  x.mod/sym/noobj! invoke the VAX/VMS Oberon-2 compiler;
                       ! generates file x.syn
  $h2o usex            ! compiles usex.mod, imports x.syn and 
                       ! generates [usex.syn,] usex.obj
  $link usex,[m2lib]x  ! link usex.obj to module [m2lib]x.obj
  $run usex            ! execute usex.exe

Oberon-2 foreign language support

H2O supports the interface definition of so-called foreign definition modules that have no corresponding Modula-2 or Oberon-2 implementation module. M2/O2 entities have at link time the following syntax (object file references)

ModuleName "NameSeparatorChar" EntityName

where entity is either a procedure, or variable or additionally in O2, the type descriptor section name. Constants, strings and types are completely handled by the M2/O2 compilers.

The NameSeparatorChar can be freely choosen with the

/[No]Module_Name_Separator[="x"] compilation qualifier.

The import of a module forces the compiler to produce a call to the module body, i.e. the initialization procedure with the name of the module. For foreign interface module references, only the object file references contain the EntityName.

VMS's parameter passing mechanisms %IMMED, %REF and %STDESCR (immediate value, per reference and per string descriptor) are supported. Syntactically we decided not to introduce additional keywords as in Modula-2 (MVR). Instead we did only one change in the front-end of the Oberon-2 compiler:

H2O's parameter passing specifications for foreign interfaces:

Allow "$" in the module name. If it contains a "$", then the entity names are also allowed to contain dollar signs. Names of procedure parameters are don't care names at link time (even at compile time), so a parameter name suffix of either "$I", "$R", or "$S" could serve to indicate its parameter passing mechanism. By default all parameters, even value parameters are passed by reference as in Modula-2 (MVR). Note, that the module name of foreign modules is nowhere used at link time, hence it can be cheated with a "$"

So for example, the M2 definition


%FOREIGN DEFINITION MODULE StrHanProcs;

PROCEDURE STR$InsertStringAtPos (
  VAR %STDESCR str:       ARRAY OF CHAR; 
               pos:       INTEGER;
          %REF ins:       ARRAY OF CHAR;
        %IMMED insLength: INTEGER): INTEGER;

END StrHanProcs.
is defined in Oberon-2 (H2O) as follows:

MODULE StrHanProcs$;

TYPE INTEGER*=LONGINT;

PROCEDURE STR$InsertStringAtPos* (
  VAR str$S:       ARRAY OF CHAR; 
      pos:         INTEGER;
      ins$R:       ARRAY OF CHAR;
      insLength$I: INTEGER): INTEGER;

END StrHanProcs.
Parameters with the "$R" suffix make sense only in combination with open array parameters; in this case, the pushing of the array descriptors LEN(array) value is suppressed; only the address of the array is pushed.

$R mechanisms are heavily used for example in the OSF/Motif interface (DECW$MOTIF) which doesn't make use of string descriptors. That's all that's needed to create any interface to VMS callable routines. The compiler guarantees the correct passing mechanism while retaining the full type check.

When doing an interface conversion from M2 syntax to O2 syntax, the change of the parameter passing specification as illustrated in the StrHanProcs module above, could be securely done using an editor macro. An additional suffix "$O" indicates an optional parameter. NIL is used to indicate an omitted actual parameter.

The following modules of ISO Modula-2 Standard I/O Library are part of the H2O distribution kit:

Channels, reading program arguments and enumerations: StdChans, ProgramArgs, IOConsts

I/O-channel operations (reading, writing): TextIO, WholeIO, WholeLIO, RealIO, RealSIO, LongIO, LongGIO, LongTIO, RawIO, IOResult

Simple I/O operations with default channel: STextIO, SWholeIO, SWholeLIO, SRealIO, SRealSIO, SLongIO, SLongGIO, SLongTIO, SRawIO, SIOResult

Device modules (opening, closing, positioning): ChanConsts, StreamFile, SeqFile, RndFile, TermFile

Interfaces: IOChan, IOLink

Concurrent processing: Processes, Semaphores

String handling and number conversions: CharClass, Strings, ConvTypes, WholeConv, WholeLConv, RealConv, RealSConv, LongConv, LongGConv, LongTConv, WholeStr, WholeLStr, RealStr, RealSStr, LongStr, LongGStr, LongTStr, LongStr

System clock routines: SysClock

Mathematics: RealMath, RealSMath, LongMath, LongGMath, LongTMath, ComplexMath, ComplexSMath, LongComplexMath, LongComplexGMath, LongComplexTMath

Low level: LowReal, LowRealS, LowLongG, LowLongT

The ModulaTor Vol 2, Nr 8, Sep-92 (http://www.modulaware.com/mdlt26.htm) contains a complete collection of the ISO M2 Std Lib interface modules for Oberon-2, including source code of Oberon-2 example programs. This issue also contains a detailed description how programming language constructs, such as enumeration types, used in the ISO M2 definitions have been converted to Oberon-2 to be able to use the ISO M2 Std Lib in Oberon-2 just as in M2. H2O uses the same implementation modules as ModulaWare's Modula-2 compiler MVR under VMS.

This interoperability of the ISO M2 Lib with O2 was not a design goal of the ISO M2 committee. But the O2 programmers can take advantage of a formally specified (VDM-SL) library. For more information about VDM-SL see the article of Nico Plat and Peter Gorm Larsen, entitled An Overview of the ISO VDM-SL Standard, in ACM SigPlan, Vol 27, Nr 8, Aug-92, pp 76..82).


IMPRESSUM: The ModulaTor is an unrefereed journal. Technical papers are to be taken as working papers and personal rather than organizational statements. Items are printed at the discretion of the Editor based upon his judgement on the interest and relevancy to the readership. Letters, announcements, and other items of professional interest are selected on the same basis. Office of publication. The Editor of The ModulaTor is Günter Dotzel; he can be reached at mailto:[email deleted due to spam]


Home | Site_index | Legal | OpenVMS_compiler | Alpha_Oberon_System | ModulaTor | Bibliography | Oberon[-2]_links | Modula-2_links |

Amazon.com [3KB] [Any browser]

Books Music Video Enter keywords...


Amazon.com logo

Webdesign by www.otolo.com/webworx, 16-Dec-1998