%THIS IS THE HELIOS STANDALONE MANUAL, PUBLISHED NOVEMBER 1991.
%PLEASE IGNORE THE `overfull h-box' MESSAGE (26.67253pt): IT HAS NO
%EFFECT ON THE FINAL OUTPUT. ALSO, IGNORE THE `underfull h-box' MESSAGE
%(badness 1490).
%$Id: HEL91005.tex,v 1.1 1992/01/23 18:13:13 doc Exp $
\documentstyle[times,a5,makeidx,bezier,epic]{psl}
\makeindex

\title{\Huge {\bf Helios Standalone Support}}
\author{}
\date{}

\pagestyle{empty}
\begin{document}

\include{docinfo}

\docinfotitle{Helios Standalone Support}
\docinfoauthor{PERIHELION SOFTWARE LIMITED}
\docinfoproject{HEL}
\docinfoauthinit{PSL}
\docinfoyear{91}
\docinfodocno{005}
\docinforev{1}
\docinfooperator{ID}
\docinfostate{APPROVED}
\docinfosecurity{PUBLISHED 1991}
\docinforeader{PSL}

\maketitle
\setcounter{tocdepth}{4}
%\pagenumbering{roman}
%\tableofcontents
\include{HEL91008}
\pagestyle{plain}

\cleardoublepage
\pagenumbering{arabic}



\section*{1 Introduction}

\index{Standalone!support}
\index{Support!standalone}
The Helios standalone runtime system allows the user to run programs in
naked transputers without the need for Helios to be loaded. There are several
reasons for doing this. The processor may not have enough memory to
run Helios (many early transputer cards have only 256k),
the program may need to control all the resources of the
processor itself (for example, a device interface) or the user may want
maximum performance from the program.

The standalone system may be used in two distinct ways. In the
first an existing program is run alone for performance reasons and
in the second a custom program has been written.
These two uses are reflected in the two environments supplied to support
standalone programming.
The first is a virtual Helios environment in which a program runs as if
it were running under a limited version of Helios. Such a program
can be tested under Helios and then moved into a standalone environment
without recompilation or relinking.
The second is a more limited environment in which only a small subset
of library routines are available. This is much closer in style to that
available under {\bf occam} or any other standalone language system.

\section*{2 Host support}

\index{Host!support}\index{Standalone!host support}
\index{Support!standalone!host support}
The standalone system is designed to be hosted from Helios. Therefore
it will only work in a hardware configuration consisting of at least
two processors.

\subsection*{2.1 Programmer interface}

\index{Programmer interface!standalone}\index{Standalone!programmer
interface} 

The support provided to {\bf host} 
programs consists of the header {\bf \verb+<+linkio.h\verb+>+}
and the module {\bf sasup.o}.
The latter contains three procedures:
\small
\begin{verbatim}
      link_open 
      link_close 
      link_boot
\end{verbatim}
\normalsize

%\begin{sloppypar}
The function {\bf link\_open (word linkno)} opens the given link for raw I/O.
The result will be {\bf TRUE} if it succeeds and {\bf FALSE} if it fails.
Similarly {\bf link\_close (word linkno)} 
closes the link down and returns it to its original state.
%\end{sloppypar}
The function {\bf link\_boot (word linkno, char *file)} runs the program in 
the named file in the processor through the given link. The file must have been
generated by {\bf salink}. The result of {\bf link\_boot} is either zero if it
succeeded or an error number if it failed. The error numbers are as follows:
\vfill
\newpage
%\begin{table}[h]
%\begin{tabular}{ll}
%1.  \it Could not find /helios/lib/nboot.i. & 5.  \it Could not send bootstrap.\\
%\\
%2.  \it Could not read bootstrap. & 6.  \it Could not send command to bootstrap.\\
%\\
%3.  \it Could not open program file. & 7.  \it Could not send program.\\
%\\
%4.  \it Could not send bootstrap size.\\
%\end{tabular}
%\end{table}

\begin{itemize}
\item {\it Could not find /helios/lib/nboot.i}.
\item {\it Could not read bootstrap}.
\item {\it Could not open program file}.
\item {\it Could not send bootstrap size}.
\item {\it Could not send bootstrap}.
\item {\it Could not send command to bootstrap}.
\item {\it Could not send program}.
\end{itemize}

The header file {\bf linkio.h}, in addition to the function templates for the
above procedures, contains a set of macros to perform link I/O. These
correspond to the macros available in {\bf chanio.h} and are described in
section 4.5.
The variable {\bf \_LinkTimeout} controls the timeout applied to link transfers.
It is initialised to {\it 2*OneSec}. The failure of {\bf link\_boot} is
commonly caused by the target processor awaiting a bootstrap message
when it is not in a reset state.

\subsection*{2.2 Sarun}

\index{Standalone!sarun program@{\bf sarun} program}\index{sarun@{\bf sarun} program - standalone}
\begin{sloppypar}
This is a simple program which itself executes a standalone program.
It takes two arguments: a link number and a system file generated by 
{\bf salink}.
Once the program has been run, {\bf sarun} will transfer any data received on its
standard input through the link, and similarly transfer any data read from the
link to its standard output.
The {\bf sarun} program will terminate on EOF (or CTRL-D) on its standard input.
Therefore a standalone program may be placed in a conventional shell pipeline
or even in a CDL script.
For example:
\end{sloppypar}
\small
\begin{verbatim}
     produce | sarun 2 munge | consume
\end{verbatim}
\normalsize

\indent The program {\bf munge} will run on the processor through link 2. It will get
input from {\bf produce} and its output will go to {\bf consume}.
Care must  be taken to ensure that {\bf sarun} is executed on the
correct processor.

\subsection*{2.3 Salink}

\index{salink@{\bf salink} program - standalone}\index{Standalone!salink@{\bf salink}
 program}
The program {\bf salink} is used to prepare a program for standalone execution.
It generates a system file which may be passed to {\bf link\_boot} or to
{\bf sarun}.
The arguments are as follows:
\small
\begin{verbatim}
     salink [-t4|8] -o dest program
\end{verbatim}
\normalsize

\indent The program is a linked Helios program generated in the usual way.
The {\bf -o} flag must be present (it introduces the output file).
The {\bf -t} flag is followed by either {\bf 4} or {\bf 8}, indicating whether
the target processor is a T414/425 or a T800.

The program is examined  by {\bf salink} for references to shared library modules.
If these are present then a {\bf virtual} Helios environment is built containing
the modules referenced. If the program contains no such references, it can be
run on its own and a minimal system is built around it.

\section*{3 Virtual Helios environment}

\index{Standalone!virtual Helios environment}\index{Virtual Helios
environment!standalone}\index{Environment!virtual Helios - standalone}
In this environment certain Helios programs may be run `standalone' without
needing to be recompiled or relinked, although most operating system 
features, such as
message passing and file access, are absent.
Instead the program is linked with a special standalone version of
the Kernel, System library and Posix library. The usual versions
of all other libraries are used.

The standalone Kernel lacks all the routines concerned with port
manipulation, message passing, event handling, and link configuration and
allocation. All other routines such as list handling, semaphores, link I/O
and memory allocation function as before.
The absent functions, if called, generate a suitable error.
The standalone System library is almost entirely non-functional with the
exception of {\bf Malloc} and {\bf Free}. As in the Kernel, 
the absent functions will generate an error if called.

%\begin{sloppypar}
The standalone Posix library is also non-functional, with the exception of
the routines
{\bf read()}, {\bf write()}, {\bf close()} and 
{\bf dup2()}.
All read and write operations are translated into link transfers. The link
used depends on the file descriptor. File descriptors 0 and 1 
({\bf standard input} and {\bf standard output}) 
are mapped onto the processor's boot link. Descriptors
2 and 3 ({\bf stderr} and {\bf stddbg}) are simply duplicates of descriptor 1.
Descriptors 4 to 11 are mapped onto the four links in numerical order
so that link \(n\) may be read on descriptor \(2n+4\) 
and written on descriptor \(2n+5\).
Descriptors may be closed and the mapping rearranged using {\bf dup2()} but new
streams may not be opened.
%\end{sloppypar}

All remaining libraries function exactly as before except that any routines
which make calls on now absent Kernel, System library or Posix library
functions will generate errors. Thus for example, the C library {\bf fopen()} call
will fail. However, the standard C library streams {\bf stdin}, {\bf stdout} 
and {\bf stderr}
will function normally by transferring data through the boot link.
The virtual Helios environment may therefore be used to run programs
which communicate only through their standard I/O streams. 

\section*{4 Limited standalone environment}

\index{Environment!limited standalone}
\index{Standalone!limited standalone environment}
The limited standalone environment provides a level of support equivalent to
that found in {\bf occam} and other standalone transputer language systems.
Runtime support is limited to the facilities supplied by a small set
of headers and a simple library of procedures. These provide the means to
use links and channels, create new processes and perform other simple
functions. The intended use for this environment is in low-level
hardware control or lightweight applications.

Definitions for this standalone environment are found in the headers
{\bf chanio.h}, {\bf thread.h}, {\bf trace.h}, {\bf salib.h} and 
{\bf sysinfo.h}.  Additionally, some of the routines found in the 
following normal Helios headers
are also supported:
{\bf stdlib.h}, {\bf string.h}, {\bf time.h}, {\bf math.h}, {\bf nonansi.h}, 
{\bf setjmp.h}, {\bf queue.h}, {\bf sem.h}, {\bf syslib.h}.
The code is present in two libraries: {\bf salib} and {\bf samath} which come 
in both T4 and T8 versions.

To build a limited standalone program, compile the program as usual and link it
with the libraries. A system image is then generated by {\bf salink} as before
and run via {\bf sarun}.
As an example, consider compiling the program {\bf worm.c}. The source is
compiled in the usual way, to generate an object file: {\bf c -c -o worm.o worm.c}.
This file must then be linked with {\bf sastart.o},
{\bf salib} and (optionally) one of the math libraries to produce an executable program:
\small
\begin{verbatim}
asm /helios/lib/sastart.o worm.o -l/helios/lib/salib 
-l/helios/lib/samath.t4 -o worm
\end{verbatim}
\normalsize

The {\bf -l} flag indicates that {\bf salib} and {\bf samath.t4} 
are libraries. Only the modules 
actually referenced will be linked with the program.
Finally, the program must be passed to {\bf salink} to generate a program which
may be executed standalone:
\small
\begin{verbatim}
     salink -o worm.sa worm
\end{verbatim}
\normalsize

\indent The following sections describe the standalone-specific routines 
in {\bf SALIB}
under the headers used to define them.

\subsection*{4.1 salib.h}

\index{salib.h@{\bf salib.h} - standalone}\index{Standalone!salib.h@{\bf salib.h}}
\begin{sloppypar}
The header {\bf salib.h} defines some miscellaneous routines, 
mostly concerned with the memory management system.
{\bf memtop} may only be called before the first call to 
{\bf malloc}. It determines
the size of the free memory and returns the address of the first byte beyond
the end of {\bf store}.
{\bf memtest} performs a memory test cycle on the supplied area of memory.
{\bf malloc\_fast} and {\bf free\_fast} are used to allocate and free areas of the
fast RAM. Since these routines differ from the Helios fast memory allocation
routines, {\bf Accelerate} must be used slightly differently.
Where the code under Helios might be:
\end{sloppypar}
\small
\begin{verbatim}
        Carrier *carrier;

        carrier = AllocFast(size,&MyTask->MemPool);

        Accelerate(carrier,fn,sizeof(int),x);

        Free(carrier);
\end{verbatim}
\normalsize

The code in the standalone environment is:
\small
\begin{verbatim}
        Carrier carrier;

        carrier.Addr = malloc_fast(size);
        carrier.Size = size;

        Accelerate(&carrier,fn,sizeof(int),x);

        free_fast(carrier.Addr);
\end{verbatim}
\normalsize

\subsection*{4.2 sysinfo.h}

\index{sysinfo.h@{\bf sysinfo.h} (standalone)}\index{Standalone!sysinfo.h@{\bf sysinfo.h}}
The header {\bf sysinfo.h} defines the {\bf SysInfo} structure, 
which is initialised to contain some useful values. These values
are the base address of the free memory in the processor,
the address of the program's module table and the identity of the processor's
boot link. A pointer to the trace vector is also kept here but it is only initialised
if {\bf \_TraceInit} is called.
A macro called {\bf \_SYSINFO} is supplied to return the address of the 
{\bf SysInfo} structure.

\subsection*{4.3 trace.h}

\index{trace.h@{\bf trace.h} (standalone)}\index{Standalone!trace.h@{\bf trace.h}}
The standalone library contains copies of the {\bf \_Trace}, {\bf \_Mark} and
{\bf \_Halt} routines defined in the Helios Kernel.
These all place entries into a {\bf trace vector} at the 
top of the memory, which may be examined with the debugger.
The trace vector must be initialised with {\bf \_TraceInit} before entries may
be made. 

\index{Standalone!thread.h@{\bf thread.h}}\index{thread.h@{\bf thread.h}}

\section*{4.4 thread.h}
%\begin{sloppypar}
Most programs can use the Helios-compatible {\bf Fork} procedure to create
new processes. However, the procedure {\bf thread\_create}, defined in this
header, may be used where a more primitive form is required.
{\bf Fork} will normally
allocate the stack of a new process using {\bf malloc}. If you do not want your
program to initialise the memory system then you may use {\bf thread\_create},
which passes a pointer to the {\bf top} of the memory to be used
as the stack. For example,
\small
\begin{verbatim}
     static char stack[2000];

     thread_create( stack+2000, 1, fn, sizeof(x), x );
\end{verbatim}
\normalsize
\noindent runs {\bf fn} as a parallel process at low priority, using the array 
{\bf stack} as its
stack. No vector stack is created and the module table is passed directly
to the function.
Therefore, any C program must be compiled with \verb+#+{\bf pragma -s1 -f0}
at the top to switch off stack checking and the vector stack.
The {\bf thread\_stop} procedure simply halts the calling process.
%\end{sloppypar}

\subsection*{4.5 chanio.h}

\index{chanio.h@{\bf chanio.h} - standalone header}\index{Standalone!chanio.h@ 
{\bf chanio.h}}
\begin{sloppypar}
The {\bf chanio.h} header defines a number of macros to be used for channel 
and link I/O.
These macros are named according to the following convention:
{\bf medium\_direction\_item} where {\bf medium} is either {\bf link} or
{\bf chan}, {\bf direction} is either {\bf in} or {\bf out}, and {\bf item} is
{\bf byte}, {\bf word}, {\bf struct} or {\bf data}.
The first argument is always either a pointer to the channel or the number
(0--3) of the link to be used for transfer.
The second argument is either the data item to be transferred, or a pointer
to it.
Where {\bf item} is {\bf data} a third argument defines the size of the data
to be transferred.
For example, the following code transmits a word, followed by a string, and
receives a data structure back from a link:
\end{sloppypar}


\small
\begin{verbatim}
     char *name;
     struct Answer answer;

     link_out_word(link,123);
     link_out_byte(link,strlen(name));
     link_out_data(link,name,strlen(name));

     link_in_struct(link,answer);
\end{verbatim}
\normalsize

The function {\bf alt} performs an {\bf occam}-style alternate on an array of
channel pointers. 
The first argument is a time interval in ticks of the current priority
clock. If it is zero, a non-timer alternate is performed.
The second argument is the size of the channel array.
The third argument is a pointer to an array of channel pointers.
The result of the {\bf alt} function is either the index in the array of the
channel which was selected, or -1 if a timeout occurred.
Unlike the {\bf occam} construct, if a channel is selected, the input is not
performed by the {\bf alt} routine, and must be performed by the subsequent
code.
The procedure {\bf boot} attempts to boot a copy of the program into the
processor through the link given.

\section*{5 Examples}

This chapter illustrates, with some examples, how the standalone system may 
be used.


\subsection*{5.1 Sarun}
\index{sarun@{\bf sarun}}\index{Standalone!sarun@{\bf sarun}}
The {\bf sarun} program is used to load and execute a program on a naked
processor. It shows how the {\bf host} support routines are used.

\footnotesize
\begin{verbatim}
/* SARUN - 20/8/89                                             */
/* Program to load and run a stand alone program               */
/* To compile:  c sarun.c sasup.o -o sarun                     */

#include <stdio.h>
#include <stdarg.h>
#include <linkio.h>
#include <stdlib.h>
#include <sem.h>
#include <nonansi.h>

Semaphore sync;                 /* Termination synchronisation */

bool finished = FALSE;          /* set True on EOF             */

static int error(char *f,...)
{
       va_list a;
             
       va_start(a,f);
        
       vfprintf(stderr,f,a);
        
       putc( '\n', stderr );
        
       exit(1);
}
/* Input process                                                */
/* Reads characters from STDIN and passes them through link     */
void input(word link)
{
        word c;
        do {
                c = getchar();
                if( c == EOF ) break;
                link_out_byte(link,c);
        } while( !finished );
        finished = TRUE;
        Signal(&sync);
}
/* Output process                                              */
/* Reads characters from link and prints them on STDOUT        */
     
void output(word link)
{
        word c = 0;
        do {
                 word e = link_in_byte(link,c);
                 if( e < 0 ) continue;   /* timeout, just loop  */
                 putchar(c);
         } while( !finished );
         finished = TRUE;
         Signal(&sync);
 }
 /* Main                                                         */
 /* Get control of link, boot program through it, fork input and */
 /* output processes and then wait for them to finish.           */
     
 int main(int argc, char **argv)
 {
      int e;
      int link;
             
      if( argc < 3 ) error("usage: sarun link bootfile");
     
      link = atoi(argv[1]);
     
      /* open the link for raw I/O */ 
      if( !link_open(link) ) error("failed to open link %d",link);
      /* boot the program through it */
      if( (e=link_boot(link,argv[2]))!=0 ) 
      error("link_boot error %d",e);
      /* now spool stdin into the link and    */
      /* anything from the link to stdout     */
             
      InitSemaphore(&sync,0);
             
      Fork(2000,input,4,link);
             
      Fork(2000,output,4,link);
             
 Wait(&sync);
 Wait(&sync);
        
 if( !link_close(link) ) error("failed to close link %d",link);
}
\end{verbatim}
\normalsize

\subsection*{5.2 Exploratory worm}
\index{Exploratory worm - standalone}\index{Standalone!exploratory
worm}\index{Worm (exploratory)}
This is a recoding into C of an {\bf occam} worm.
It has two parts: the program \linebreak {\bf explore} which runs under Helios
and the worm, which is run on naked processors.
The program as it stands is intended to generate a resource
map for an unknown processor network. It assumes that Helios has been booted
into the first processor of the network and {\bf explore} has been run there.
It checks each link, identifying booted processors and 
passing the worm through unused links. Then a
text resource map, which may be captured and compiled, is produced as output.
Another use of this worm is to flood-fill a processor network with copies
of a particular program. The worm may then generate a load 
balancing task farm. The Helios standalone support package contains the
source of the worm. It is in the examples directory, under the
directory {\bf sa}. (For example: {\bf /helios/users/guest/examples/sa}.)

\section*{6 SALIB summary}
\index{SALIB summary - standalone}\index{Standalone!SALIB summary}
This chapter lists the functions supplied by {\bf SALIB} under the headers used
to define them.

\footnotesize
\begin{tabbing}
   \= {\it \verb+<+stdlib.h\verb+>+} \= \\
 \> \> {\it void free(void *ptr);}\\
 \> \> {\it void *malloc(size\_t size);}\\
 \> \> {\it void *realloc(void *ptr, size\_t size);}\\
 \> \> {\it void exit(int status);}\\
%halts the processor
\\
 \> {\it \verb+<+string.h\verb+>+}\\
 \> \> {\it void *memcpy(void *s1, const void *s2, size\_t n);}\\
 \> \> {\it void *memmove(void *s1, const void *s2, size\_t n);}\\
 \> \> {\it char *strcpy(char *s1, const char *s2);}\\
 \> \> {\it char *strncpy(char *s1, const char *s2, size\_t n);}\\
 \> \> {\it char *strcat(char *s1, const char *s2);}\\
 \> \> {\it char *strncat(char *s1, const char *s2, size\_t n);}\\
 \> \> {\it int memcmp(const void *s1, const void *s2, size\_t n);}\\
 \> \> {\it int strcmp(const char *s1, const char *s2);}\\
 \> \> {\it int strncmp(const char *s1, const char *s2, size\_t n);}\\
 \> \> {\it void *memchr(const void *s, int c, size\_t n);}\\
 \> \> {\it char *strchr(const char *s, int c);}\\
 \> \> {\it size\_t strcspn(const char *s1, const char *s2);}\\
 \> \> {\it char *strpbrk(const char *s1, const char *s2);}\\
 \> \> {\it char *strrchr(const char *s, int c);}\\
 \> \> {\it size\_t strspn(const char *s1, const char *s2);}\\
 \> \> {\it char *strstr(const char *s1, const char *s2);}\\
 \> \> {\it char *strtok(char *s1, const char *s2);}\\
 \> \> {\it void *memset(void *s, int c, size\_t n);}\\
 \> \> {\it size\_t strlen(const char *s);}\\
 \\
 \> {\it \verb+<+time.h\verb+>+}\\
 \> \> {\it extern clock\_t clock(void);}\\
 \\ 
 \> {\it \verb+<+math.h\verb+>+}\\
 \> \> {\it extern double acos(double x);}\\
 \> \> {\it extern double asin(double x);}\\
 \> \> {\it extern double atan(double x);}\\
 \> \> {\it extern double atan2(double x, double y);}\\
 \> \> {\it extern double cos(double x);}\\
 \> \> {\it extern double sin(double x);}\\
 \> \> {\it extern double tan(double x);}\\
 \> \> {\it extern double cosh(double x);}\\
 \> \> {\it extern double sinh(double x);}\\
 \> \> {\it extern double tanh(double x);}\\
 \> \> {\it extern double exp(double x);}\\
 \> \> {\it extern double frexp(double value, int *exp);}\\
 \> \> {\it extern double ldexp(double x, int exp);}\\
 \> \> {\it extern double log(double x);}\\
 \> \> {\it extern double log10(double x);}\\
 \> \> {\it extern double modf(double value, double *iptr);}\\
 \> \> {\it extern double pow(double x, double y);}\\
 \> \> {\it extern double sqrt(double x);}\\
 \> \> {\it extern double ceil(double x);}\\
 \> \> {\it extern double fabs(double x);}\\
 \> \> {\it extern double floor(double d);}\\
 \> \> {\it extern double fmod(double x, double y);}\\
 \\
 \> {\it \verb+<+nonansi.h\verb+>+}\\
 \> \> {\it void *NewProcess(WORD stacksize, VoidFnPtr function, WORD argsize);}\\
 \> \> {\it void RunProcess(void *process);}\\
 \> \> {\it void ZapProcess(void *process);}\\
 \> \> {\it WORD Fork(WORD stacksize, VoidFnPtr function, WORD argsize,\ldots );}\\
 \> \> {\it void Accelerate(Carrier *fastram, VoidFnPtr function, WORD argsize, \ldots);}\\
 \> \> {\it void AccelerateCode(VoidFnPtr function);}\\
 \> \> {\it void IOdebug(const char *fmt,\ldots);}\\
 \> \> {\it void IOputs(char *s);}\\
 \> \> {\it void IOputc(char c);}\\
%generates raw characters out boot link
 \\
 \> {\it \verb+<+setjmp.h\verb+>+}\\
 \> \> {\it extern int setjmp(jmp\_buf env);}\\
 \> \> {\it extern void longjmp(jmp\_buf env, int val);}\\
 \\
 \> {\it \verb+<+queue.h\verb+>+}\\
 \> \> {\it PUBLIC void InitList(List *);}\\
 \> \> {\it PUBLIC void PreInsert(Node *, Node *);}\\
 \> \> {\it PUBLIC void PostInsert(Node *, Node *);}\\
 \> \> {\it PUBLIC Node *Remove(Node *);}\\
 \> \> {\it PUBLIC void AddHead(List *, Node *);}\\
 \> \> {\it PUBLIC void AddTail(List *, Node *);}\\
 \> \> {\it PUBLIC Node *RemHead(List *);}\\
 \> \> {\it PUBLIC Node *RemTail(List *);}\\
 \> \> {\it PUBLIC word WalkList(List *,WordFnPtr,\ldots );}\\
 \> \> {\it PUBLIC Node *SearchList(List *,WordFnPtr,\ldots );}\\
 \\
 \> {\it \verb+<+sem.h\verb+>+}\\
 \> \> {\it PUBLIC void InitSemaphore(Semaphore *, word);}\\
 \> \> {\it PUBLIC void Wait(Semaphore *);}\\
 \> \> {\it PUBLIC void Signal(Semaphore *);}\\
 \> \> {\it PUBLIC void SignalStop(Semaphore *);}\\
 \> \> {\it PUBLIC word TestSemaphore(Semaphore *);}\\
 \\
 \> {\it \verb+<+syslib.h\verb+>+}\\
 \> \> {\it void Delay(word usec);}\\
 \\
 \> {\it \verb+<+salib.h\verb+>+}\\
 \> \> {\it extern void *memtop(void);}\\
 \> \> {\it extern int memtest(word *base, int size);}\\
 \> \> {\it extern void boot(int link);}\\
 \> \> {\it extern void freestop(void *addr);}\\
 \\
 \> \> {\it \verb+<+sysinfo.h\verb+>+}\\
 \> \> {\it \_SYSINFO}\\
 \\
 \> {\it \verb+<+trace.h\verb+>+}\\
 \> \> {\it extern void \_TraceInit(void);}\\
 \> \> {\it extern void \_Mark(void);}\\
 \> \> {\it extern void \_Trace(int x,\ldots );}\\
 \> \> {\it extern void \_Halt(void);}\\
 \\ 
 \> {\it \verb+<+thread.h\verb+>+}\\
 \> \> {\it extern void thread\_create(void *stack, word pri, VoidFnPtr fn, word nargs,\ldots );}\\
 \\ 
 \> {\it \verb+<+chanio.h\verb+>+}\\
 \> \> {\it chan\_out\_byte(c,b)}\\
 \> \> {\it chan\_out\_word(c,w)}\\
 \> \> {\it chan\_out\_data(c,d,s)}\\
 \> \> {\it chan\_out\_struct(c,d)}\\
 \> \> {\it chan\_in\_byte(c,b)}\\
 \> \> {\it chan\_in\_word(c,w)}\\
 \> \> {\it chan\_in\_data(c,d,s)}\\
 \> \> {\it chan\_in\_struct(c,d)}\\
 \> \> {\it link\_out\_byte(l,b)}\\
 \> \> {\it link\_out\_word(l,w)}\\
 \> \> {\it link\_out\_data(l,d,s)}\\
 \> \> {\it link\_out\_struct(l,d)}\\
 \> \> {\it link\_in\_byte(l,b)}\\
 \> \> {\it link\_in\_word(l,w)}\\
 \> \> {\it link\_in\_data(l,d,s)}\\
 \> \> {\it link\_in\_struct(l,d)}\\
 \> \> {\it extern int alt(int timeout, int nchans, Channel **chans);}
\\
\end{tabbing}
\normalsize
\printindex
\end{document}




