
% SECTION
%
%    Coroutine supplement for release notes
%
%
%

\section{Coroutines and stack overflow testing}
This release of \gpm\ contains an implementation of coroutines for the 
first time. Since the module is new, full details are given here.

Programs which do not use the coroutines library, so-called 
{\em single-stack programs} have little need to perform stack overflow 
testing although testing is the default for \gpm. Typically, several hundred 
megabytes of virtual memory are
available for expansion of the stack segment of such programs, although 
it is usual for {\em UNIX\/}s process size limit to be exceeded well 
before this. Programs which use the coroutines library have a separate 
stack for each coroutine, suggesting the prudent use of stack overflow 
testing. The default stack for single stack programs in \gpm\ is 64k bytes,
and may be modified by the use of the environment variable {\em M2STACK}.

\subsection{The Coroutines library}

The coroutines library is an ordinary library in the sense that no 
knowledge of the library is required by the compiler. It is implemented 
in assembly language and uses the usual {\em FOREIGN} mechanism.
The library must be explicitly imported by user programs, in keeping with 
the proposals of {\em ISO WG-13}. However, this version implements the 
{\em old} coroutines model exactly as specified by Wirth. \gpm\ will 
provide the new coroutines model when acceptance of the change is 
confirmed. In the meanwhile, the old style library will not break 
existing programs.

\subsection*{Library definition}
%
%
\opencodebox{15.0cm}
\begin{verbatim}
(* ========================================================= *)
(* Preliminary library module for Gardens Point Modula       *)
(* ========================================================= *)

FOREIGN DEFINITION MODULE Coroutines;(* coroutines as in PIM *)

  IMPORT IMPLEMENTATION FROM "coroutines.o";
  FROM SYSTEM IMPORT ADDRESS;

  TYPE Coroutine = ADDRESS;  (* use of this type avoids SYSTEM import *)

  PROCEDURE NEWPROCESS (code  : PROC;           (* body of coroutine  *)
                        space : ADDRESS;        (* ptr to workspace   *)
                        size  : CARDINAL;       (* size of workspace  *)
                    VAR this  : Coroutine);     (* returned coroutine *)

  PROCEDURE TRANSFER (VAR thisCo : Coroutine;   (* current saved here *)
                      VAR destCo : Coroutine);  (* target to activate *)

END Coroutines.
\end{verbatim}
\closebox

For this preliminary release, the source code of the implementation is 
included in the distribution. The code is extremely dependent on the 
exact procedure calling conventions of the Modula and C compilers, and is 
tightly coupled to the facilities of the runtime system. Modification of 
this code, except as suggested by any future upgrade notices, is not 
recommended.

\subsection{Procedure NEWPROCESS}
The procedure {\em NEWPROCESS} initializes a new coroutine and computes 
various static attributes. In particular the call of the procedure 
specifies the code body which the coroutine will execute, and the size 
and address of the workspace which it will use.

\subsubsection{The first parameter}
The first actual parameter of the procedure call must designate a 
parameterless procedure value, that is a {\em PROC}. The actual
parameter must thus either be a procedure of this type, or a procedure 
variable of this type.\footnote{The use of parameters which are procedure 
variables is unusual. However, the creation of a pool of
coroutines whose bodies may be specfied at runtime is an interesting 
technique. It allows Modula to come close to providing for {\em 
dynamically} specified processes.}

\subsubsection{The second and third parameters}
The second actual parameter is of {\em Coroutine} or of
{\em SYSTEM.ADDRESS\/} type. It is a 
pointer to the workspace which the coroutine will use. The memory to 
which this value points must have been allocated prior to the call, 
either by a call to {\em Storage.ALLOCATE\/} or by using a statically 
declared array of suitable size. It is strongly recommended that space 
obtained from the storage allocator be used as workspace. In particular,
the workspace {\em must} be octo-byte aligned. Space obtained from 
{\em Storage.ALLOCATE} automatically fulfils this condition.
The third parameter simply states the workspace size.

\subsubsection{How much workspace is required?}
The workspace has two components. They are the coroutine state 
vector, and the normal coroutine private stack. The 
state vector is less than a hundred bytes in size.  

All of the remaining workspace is available as stack space for the 
coroutine. The procedure sets a stack overflow limit approximately 200 bytes 
from the end of the workspace. This safety zone provides space for cleanup 
procedures (which will execute in the context of the failed coroutine)
to run to completion successfully.

Programs which do not require any stack space at all will thus need 
workspace of approximately 400 bytes. 
For typical programs, a size of 
8000 bytes is probably more realistic minimum. 

\subsubsection{New runtime error messages}
If a coroutine (other than the main process) ends ``normally'' the 
following error message is produced.
\begin{verbatim}
    **** gp.rts: coroutine ended without TRANSFER ****
\end{verbatim}

In the event that the workspace stack limit has been exceeded, and stack 
overflow testing was used in the procedures of the coroutine body, the 
following message is produced.
\begin{verbatim}
    **** gp.rts: stack limit has been exceeded ****
\end{verbatim}

\subsubsection{A typical example}
In the program figure \ref{initco} two coroutines are created.

\opencodebox{14.5cm}
\begin{verbatim}
    MODULE CoTest;
      IMPORT SYSTEM;
      FROM Storage IMPORT ALLOCATE;
      FROM Coroutines IMPORT 
           Coroutine, NEWPROCESS, TRANSFER;

      VAR  adr : SYSTEM.ADDRESS;
           init, c1, c2 : Coroutine;

        ...

    BEGIN
      ALLOCATE(adr,10000); (* get workspace *)
      NEWPROCESS(Proc1,adr,10000,c1);
      ALLOCATE(adr,10000); (* get workspace *)
      NEWPROCESS(Proc2,adr,10000,c2);
        ...
      TRANSFER(init,c1);   (* init is main process *)
        ...
    END CoTest.
\end{verbatim}
\closecodebox{Initialization of coroutines in program}{initco}

\subsection{Procedure TRANSFER}
%
%
%
The two actual parameters to {\em TRANSFER} are both of {\em Coroutine} 
type, and both are of {\em VAR} mode. Prior to the call of {\em 
TRANSFER}, the second parameter designates the variable of {\em 
Coroutine} type which identifies the coroutine which is to be 
activated (or resumed, as the case may be). The first parameter, 
designates the variable which after the transfer will identifies the 
coroutine which has just been suspended.

In a typical example of usage, each newly created coroutine will have a 
variable associated with it by the call of {\em NEWPROCESS}. One further
variable is declared to identify the implicit main coroutine. In the 
previous example, {\em init} identifies the main coroutine, and 
{\em c1, c2} are the new coroutines.

Because of the details of the {\em TRANSFER} 
semantics, it is valid (although unusual) 
to use the same variable for both actual parameters. In a program with 
just two coroutines such a single variable can be arranged to always 
designate the {\em other} process. In this case, the call of
{\em TRANSFER} has the meaning `resume other coroutine'. Figure \ref{resume}
is the skeleton of an example of this unusual structure.
\opencodebox{14.5cm}
\begin{verbatim}
      VAR  adr   : SYSTEM.ADDRESS;
           other : Coroutine;

        PROCEDURE Proc1;
        BEGIN
            ...
          TRANSFER(other,other); (* "resume" *)
            ...
        END Proc1;

    BEGIN
      ALLOCATE(adr,10000); (* get workspace *)
      NEWPROCESS(Proc1,adr,10000,other);
        ...
      TRANSFER(other,other); (* "resume" *)
        ...
    END CoTest.
\end{verbatim}
\closecodebox{Two coroutine program showing the virtual {\em resume}}{resume}

\section{Stack overflow testing}

The facilities for stack overflow testing consist of the following items.
\begin{itemize}
\item Stack size limits are set by a environment variable {\em M2STACK}
\item A new runtime message signals stack overflow
\end{itemize}

\subsection{Setting the stack size limit}
The load builder program {\bf build} queries its environment for the 
variable {\em M2STACK}. The value, if set, is inserted in the tiny program 
which contains the initialization call-chain for the final, executable 
program. The value in the tiny program is used in the initalization of 
the runtime support system.

If the variable {\em M2STACK} is not defined, the runtime system 
allocates a default size of 64k bytes to the stack. 

Note that this value is effective only for the main process. The stack 
size of every other coroutine is 
determined separately by the third parameter to the 
the call of {\em NEWPROCESS} which created it.

\subsubsection{Miscellaneous information}
Stack overflow testing is performed by a simple inline statement.
The cost of this test, in terms of time taken, is approximately that of a 
simple assignment statement to a global variable. The cost is thus 
similar to the inline {\em Assert} ``procedure''.

If stack testing is turned on and off by use of the pragma 
\verb!(* $S+ *)! and
\verb!(* $S- *)! respectively,
and if the stack exceeds the set limit a runtime error is raised. In the 
absence of exception handling, the program is aborted with the following 
message being sent to the {\em StdError} stream.
\begin{verbatim}
    **** gp.rts: stack limit has been exceeded ****
\end{verbatim}

