Google
 

Trailing-Edge - PDP-10 Archives - BB-JF18A-BM - sources/dynlib/dyn2f.rno
There are 4 other files named dyn2f.rno in the archive. Click here to see a list.
.!Dynamic Library product specification (body)
.page size 58, 72
#
.subtitle
.first title
.date
.flag accept `
.flag capitalize
.flag index
.FLAG PERIOD
.set paragraph 0, 1, 3
.autoparagraph
.style headers 6,1,3,7,7,2,1,2
.title Dynamic Library V2 Specification
.number page 1

.page

.! See the Software Policies and Procedures manual for more detail

.hl 1 Product Summary

  A "routine library" (often called simply a "library" in this
document) is a group of routines and data which is intended to provide
services to its caller.  Because the word "library" appears so often
in this document, a routine library is also sometimes called a
"package."+  On TOPS-20, the most familiar form of library is probably
the "REL library" as understood by LINK and MAKLIB.

  A "dynamically linked library" (often called simply a "dynamic
library" in this document) is a library which is merged into a program
on request at execution time.  

  This document describes a dynamic library system for TOPS-20.  This
system provides the following benefits as compared to REL libraries:

.list 1, "o"
.le;Provide a discipline for independently-developed packages to share
a process peacefully while providing access to the resources they need
to do their jobs (resources that require discipline to share
successfully include address space, the APR trap system, and the
software interrupt system).

.le;Easier software updates.  A new version of a package implemented
as a dynamic library can be introduced into all programs calling it by
simply placing it on the directory from which dynamic libraries are
loaded.  There is no need to relink programs using it.

.le;More consistent program behavior.  If a facility is always
provided by the same package of code, then it will always be
provided in the same way.  

.le;More efficient use of physical memory and swapping space.    If a
facility provided by a dynamic library is never called during a run of
a program, that library will never become part of that process'
address space.  If several programs are using the same dynamic
library, they will share a single copy of its "pure" parts.

.le;Lower cost of engineering other products.  Using an existing
package to provide a service is much cheaper than having to modify it
or write one from scratch.
.end list

  The code to perform dynamic library invocation and related functions
will reside in a special dynamic library called the RTL (run-time
library).
.hl 1 Terminology and conventions

  This document specifies the "dynamic library mechanism," which we
define as "that which causes a library to be merged into a program on
request, and performs other functions necessary to make that useful."+
To avoid confusion, I will from now on call this "DYNLIB."+ In the
rest of this document, when I refer to a "dynamic library" I am
referring generically or specifically to some library designed to be
called through the services provided by DYNLIB.

  DYNLIB has associated with it some special facilities for handling
traps and interrupts, allocating memory, and performing other tasks
necessary to allow many packages to co-exist peacefully in a single
process.  These facilities are also specified in this document.  They
are SIG for signalling and condition handling (including interrupt and
trap handling), MEM for memory management and section allocation, and
RTL for other utility functions (message formatting and printing,
etc.).

  Related to DYNLIB are some rules that must be followed by writers of
libraries to be called through DYNLIB.  These appear in this document
in a paragraph by themselves, beginning with "DYNLIB use rule:".  The
full set of rules for writing a dynamic library will be documented as
part of the development effort of this project.

  A "OWL/GBP" is a one-word local/global byte pointer, which is
interpreted as follows:  If it has the form of a one-word global
byte-pointer, then it is interpreted as one.  If it has the form of a
local byte-pointer, then it is interpreted as pointing into the
section of memory from which it is fetched.  This is equivalent to
being able to set an "IFIW" bit in the byte pointer word (which is
unfortunately not supported).  The GETBP macro in DYNSYM.UNV performs
this operation.
.hl 1 Environment

.hl 2 Users

  Dynamic libraries will be written primarily by Digital engineers.
Moderately sophisticated customer system programmers may occassionally
be called upon to write dynamic libraries, as may Digital software
specialists.

  Dynamic libraries will (eventually) be used implicitly by most
higher-level language programs, but this should be transparent to the
users.

  Both application and system programs are likely to invoke dynamic
libraries explicitly.  

  Digital-written utilities will also use dynamic libraries
extensively.

.hl 2 Hardware

  DYNLIB will run on a PDP-10 family processor with
extended addressing (i.e.  KL model B).  KS processors will not be
supported.

    No microcode changes will be required for DYNLIB.

  As described below, DYNLIB will encourage the use of extended
addressing.  Some dynamic libraries may require fixes for extended
addressing bugs.  This will be the responsibility of the project that
produces the dynamic library in question.

.hl 2 Software

  Dynamic libraries cannot be loaded into section zero.  Dynamic
libraries cannot be called from section zero.  Dynamic libraries will
not coexist in the process address-space with other programs like
PA1050 which commandeer the PSI and trap systems.

  There are some specific exceptions to the above rules; in general
they were constructed for specific libraries where a pressing need
existed.  In general, a dynamic library to take advantage of these
exceptions must follow some restrictions, which are not fully
understood and are not therefore well documented.  These facilities
should be used with great caution when writing new libraries;
DEC-supplied libraries using them will be supported and reliable.

.HL 3 Other software required for DYNLIB

  DYNLIB requires TOPS-20 release 5.1 or later.

  In a future release of the operating system, support for DYNLIB
should be built in.  This is discussed under Evolvability.  Operating
system support of DYNLIB is not a goal of this project.

.HL 3 Other software that requires DYNLIB

  DYNLIB is required for Datatrieve-20 V1.0, dynamic extended RMS
(V3), and dynamic callable DBCS (V7) (Dynamic MTHLIB is being produced
as part of the Datatrieve project.)

  All other software projects should consider if they would benefit
from using DYNLIB.  Language systems should consider
invoking their OTS' through DYNLIB.  Languages calling SORT, DBCS, and
RMS should consider calling them through DYNLIB.

.hl 2 Services

  No special services are required for DYNLIB.  
.hl 1 SOFTWARE CAPABILITIES

  The basic capability of DYNLIB is to map in an EXE file containing
some package of code at the time a call is made to it.  There are some
additional functions associated with this part of DYNLIB, but the bulk
of the routines described in this section are actually support
routines -- they don't directly assist DYNLIB, but they make it
possible to write packages of code that will work together without
interference in the DYNLIB environment.

  These support routines are the complicated part of the project.
Please pay close attention to the descriptions of their capabilities
and restrictions.

.hl 2 Streaming

  "Single-stream" libraries are those like the current SORT which can
only handle one stream of operations at a time, but which have a user
interface such that you make more than one call for that single
stream (some sort of state information is preserved between calls).

  "Non-streamed" libraries are those like, perhaps, the MTHLIB, which
can only handle one stream of operations, but where this doesn't
matter to anybody because there is only one call made to perform the
operation.  There is no "state" saved across calls to these libraries.
Note that to really qualify in this category a library must be fully
reentrant.

  "Multi-streamed" libraries are those like callable Datatrieve which
support several concurrent streams of operations.  This classification
can be further divided into "infinitely multi-streamed," where it
should always be possible to start another stream, and "limited
multi-streamed," where you could easily run out of streams.  Where
"multi-streamed" is used without qualification, "infinitely
multi-streamed" should be assumed.

  DYNLIB supports non-streamed and infinitely multi-streamed
libraries.  If a caller attempts to initialize a new LDLBLK to a
library that has its busy bit set, a DYNLIB error will be returned.
If a library receives a request to start a stream which it is unable
to honor, this same error should be signalled by the library.

.hl 2 The run-time library

  The run-time library (RTL) is a special library that contains the
DYNLIB code and associated facilities (memory management, signalling).
This is an appropriate place to put generally useful routines that
aren't big enough to rate their own library.  The MTHLIB has been
included in the RTL, for example.

.HL 2 Dynamic invocation of libraries

  Most calls for DYNLIB services will be made implicitly, by referring
to an address exported from a dynamic library (routine entry point or
"galactic variable").

.hl 3 Calling a routine in a dynamic library

  To be able to call routines in a dynamic library, you must:
.list 1
.le;Be running in a non-zero section
.le;Have a global-format stack pointer in AC17
.le;Have declared as EXTERNAL in your program the names of the
routines you wish to call
.le;Have linked your program with a library-specific REL file for
each of the libraries you call directly (you do not need to consider
libraries that may be called by libraries you call)
.le;Have linked your program with DYNBOO.REL
.end list

  There are two defined types of library-specific REL file that may
be associated with a dynamic library.  The normal type is called an
"LDLBLK file"; it contains simply the definition of the LDLBLK.  The
alternative type is called an "LDLJCK file"; it contains definitions of
jacket routines for each routine in the library.  It may also contain
an ordinary LDLBLK with galactic variable information only.

  Suppose the dynamic library EXAMPL contains a routine RNDNAM.  The
argument-passing rules for this routine and what registers it
preserves are of no concern to DYNLIB (although they must, of course,
be agreed between the routine and its caller).

  To call this routine from MACRO using the LDLBLK file, you must set
up the arguments as specified for the routine, and then 
.I 5;PUSHJ P, @RNDNAM`#`#
.br;This is the normal way of calling a routine in a dynamic library.

  To call this routine from MACRO using the LDLJCK file, you must set
up the arguments as specified for the routine, and then 
.I 5;PUSHJ P, RNDNAM`#`#
.br;Note the lack of indirection.  When converting an existing
program, or a program written in a higher-level language, to use
dynamic libraries, this mode can be essential.  There is no reason for
preferring this mode of call in a newly-written MACRO program, and
some performance reasons for avoiding it.

  You may use any number of levels of indirection in the instruction
that calls a routine in a dynamic library.  It is also perfectly
acceptable for the PUSHJ instruction to be XCT'd from somewhere else.
However, the EA calc should not depend on the values in the AC's (so
don't use indexing, and don't indirect through an AC).

  Normally, the names for the routines in the LDLJCK file and the
names for the transfer vector locations in the LDLBLK file will be the
same.  Thus, they cannot both be used in the same program.  A
technique for making it possible to use both calling conventions in a
single program is described below.

.hl 3 Referring to a galactic variable

  To refer to a data location in another library, you must:
.list 1
.LE;Be running in a non-zero section
.le;Have declared as EXTERNAL in your program the names of the
galactic variables to which you wish to refer
.le;Have linked your program with a library-specific REL file for the
library which defines the galactic variable to which you wish to refer
.end list

  To refer to the galactic variable, make an indirect reference
through a "local galactic vector" (like a transfer vector, but the
things it points to aren't routine entry points) which is provided by
the library-specific REL file mentioned above.

  The method of referring to a galactic variable is the same whether
the LDLBLK file or the LDLJCK file is used.  There is no provision for
referring to galactic variables in languages that do not support the
concept of the indirect reference.

  In version 1 of DYNLIB, referring to a galactic variable before the
library which defines it is loaded (either by explicit call to DYNLIB,
or by calling a routine in that library) is an error.

.hl 3 Errors occurring during dynamic loading

  There are three ways errors occurring during dynamic loading are
handled, depending on the exact conditions.

  If the library being loaded is the RTL, an error message is printed
on the terminal.  This is done to minimize the size of the DYNBOO
bootstrap routine.  All the code for the fancy error handling
described below is contained in the RTL, which is by hypothesis not
available in this situation.

  If the instruction which caused dynamic loading is immediately
followed by an ERJMP or ERCAL instruction, control is transferred to
the location specified.  T1 will contain the address of an SG block
chain describing the error.  T0 will be trashed.  Other registers will
be preserved if so specified for the routine being called.

  If the instruction which caused dynamic loading is not immediately
followed by an ERJMP or ERCAL instruction, a signal is generated for
the error.  This may either be handled by a user error handler, or
ignored; if it is ignored, the last-ditch handler will handle it.  For
dynamic library loading errors, its handling is to print a message
describing the error and abort the program.

In either case, the error can be determined by calling the SG$LER
routine, which returns the signal block for the last RTL error that
occurred.

.hl 2 Memory Allocation

  The RTL will contain the master section allocator, and a basic
memory manager.  All sections must be allocated through the section
allocator.  An allocated section is managed by its allocator.  One
alternative it has is to manage it itself.  Another is to request that
the RTL memory allocator do so for it.

  DYNLIB use rule:  All sections used must be allocated by the DYNLIB
section allocator.

  DYNLIB use rule:  Memory in a section may not be used without the
"permission" of the allocator of that section.  That is, any sort of
cooperative arrangement is fine, but in the absence of agreement, keep
your fingers in your own sections!

  Signal blocks must be allocated by the RTL memory allocator, so that
they can be released by the SIG facility.

  A future version of the RTL must support allocation of groups of
contiguous sections.  Support for a user-written section allocator is
also desirable (and seems easy).

.hl 2 Signalling and Condition handling

  To attain the goals of a truly layered product environment, the
facilities of the interrupt system and of trapping must be available
to each package called by a process, without a package having to worry
about which other packages are being used.

  DYNLIB use rule:  user programs may not directly manipulate the APR
trap system (in particular, they may not use the APR trap function of
the SWTRP% JSYS).  User programs should get APR trapping services by
using the JOV or other JFCL-class instruction after the instruction
they wish to check for overflows, or by handling the condition
generated in the absence of JFCL-class instructions.

  DYNLIB use rule: user programs should not directly manipulate the
software interrupt (PSI) system except for assigning events to
channels allocated from DYNLIB and handling those interrupts.
They should never perform interrupt-specific JSYSes other than DEBRK%.

  There are two asynchronous types of activities that must be
supported.  

  One is asynchronous events requiring attention from the
package that started them.  These occur as a normal part of
processing, are of interest only to the package that initiated the
activity, and must be quite quick.  This mechanism will be called
"layered interrupts". 

  The other is exception (error) conditions generated by the users'
code and requests.  These occur relatively rarely, and quite often
result in an error which is of interest to other packages than the one
generating the condition.  The occurrence of these conditions need not
be blindingly fast.  This mechanism will be called "condition
handling."

  This facility, and the code making it up, is referred to as "SIG"
throughout this document.

.hl 3 Layered Interrupts

  This mechanism is intended for servicing of asynchronous events that
belong to a particular package.  These are handled by user-specified
interrupt handlers at interrupt level.  The user allocates a channel
from SIG, and attaches conditions to the channel himself.

.hl 3 Condition Handling

  This mechanism is intended for information of general hierarchical
use, particularly for error or exception information.

  This mechanism is modeled after the signalling / condition handling
facilities in BLISS-36, VAX/VMS, and RSX-11.  

  Conditions may be signalled by user software by making a call to a
SIG routine.  In addition to this use, all events made available by
TOPS-20 through APR traps or interrupts will be turned into signals by
the SIG facility (APR traps only in V1).

  To handle conditions, a routine must identify its handler to SIG.
Conditions that aren't handled by any level will be dealt with by the
"last-ditch" handler.

  SIG will maintain a list of handlers established.  When a condition
is signalled, the handlers will be called in order from most recently
established to oldest, until one of them handles the situation (see
discussion of handler options below).

  There is no facility for a package to grab complete control of some
category of signal; this would violate the hierarchical layering.

  Because this facility is based on the existing PSI and SWTRP
mechanisms, there are some restrictions on the user handlers.  In
particular, some of them must run at interrupt level.  Here are the
types of events signalled, the level at which handlers for them must
run, and the default actions if they are not handled:
.s 1
.literal
     Description     Level           Default		Continuable
     ----------      -----           -------		-----------

     APR             normal          fixup and signal	Yes
     data error      interrupt       message and exit	Yes
     disk quota      interrupt       message and exit	Yes
     end of file     interrupt       message and exit	Yes
     illegal inst.   normal	     message and exit	Restarts instr
     illegal read    normal          message and exit	Restarts instr
     illegal write   normal          message and exit	Restarts instr
     inferior stop   interrupt       continue		Yes
     non-exist. page interrupt       create, continue	Yes
     PDL overflow    normal          message and exit	Yes
     software signal normal          message & continue	Yes
				     or exit (based on
				     severity)
     system resourc. normal          message and exit	Yes
     character	     interrupt       ^C exits, 		Yes
				     others ignored
     terminal        interrupt	     ignored		Yes
	(carrier transition, break, input available)
.end literal

  When a handler is entered for a signal, it has the following
options: re-signal from current position, continue interrupted code,
unwind to its establisher's caller.  A handler must also receive the
unwind signal and do appropriate things with it (in particular, it
must free dynamic resources that its establisher allocated).  The
continue option is only available for software signals, signals
originating as traps, and signals originating as interrupts that are
handled at interrupt level.

  There are some restrictions on the linkage conventions of routines
which must enable for condition handling:
.list 1, "o"
.le;The routines must be running in a non-zero section at the time
they enable, and at any time their handlers are invoked
.le;There must be a global-format stack pointer in AC17 with
sufficient space available
.le;The routines must be called with PUSHJ 17, adr.
.le;The routines must return a value in AC0.  It is this value that
may be specified in the unwind call
.end list
A routine need not be in a dynamic library to enable for condition
handling.  It can be part of a top-level program or a library called
in some other way.

  A signal block (or error block) will have a fixed heading, including
facility identification, condition identification, severity
identification, print flags, message text, and pointer to next block.
It will contain a pointer to a block containing condition-specific
data.

  The normal appearance of a signal is as a chain of these error
blocks.  The first one in the chain is the most recent, and for most
things is the only one that needs to be examined.  However, for error
message printing, and for more detailed analysis of a situation, the
earlier blocks are available.  One of the print flags will indicate
that a block is for computer use only, that no message should be
printed.

.hl 4 Fixed interrupt channels

  Events that are assigned by TOPS-20 to fixed interrupt channels will
be turned into signals by the SIG facility (Not yet implemented).

   Illegal instruction interrupts can result from monitor call errors.
The interrupt will only occur if there is not an ERJMP or ERCAL
instruction after the JSYS that failed.  The signal block generated
for illegal instruction interrupts will include as its message the
text of the monitor error message for the JSYS failure.

.hl 4 APR traps

  APR traps will generate signals unless the instruction producing the
trap is followed by some flavor of JFCL instruction.  The default
handling of the signal will be to perform the MTHTRP fixup, print a
message, and then continue.

  An alternative method of handling APR traps (and interrupts from
fixed interrupt channels) is discussed under "Performance
Considerations", below.

.hl 4 Character interrupts

  General handling of character interrupts won't be provided in the
first version.  It will probably never be provided.  What will be
provided is likely to be good enough for everybody.

  There will be two parts to using character interrupts:  defining a
character as in interrupt (as opposed to a normal) character, and
processing the signal when it comes by.

  Receiving character interrupt signals is the same as receiving any
other signals.  There will be a word of signal-specific data giving a
mask of the characters that could have caused this signal (combining
interrupt characters is discussed directly below, and elsewhere in the
document; briefly, it is often sufficient to a program to know that
SOME interrupt character, or some from a small set, was typed, and by
assigning more than one character to a channel when possible the
limited set of channels is conserved).

  Characters are defined as interrupt characters by making calls to a
SIG routine giving bit masks.  Each call defines a group of characters
which you wish to see treated as interrupt characters.  The group of
characters given in a call will not necessarily be distinguishable
from each other when the signal arrives.

  If you ask to distinguish between characters that somebody else has
already asked to see combined, you lose (and get a code to that
effect).  As a special exception, `^C, `^T, `^A , and `^Y will never
be combined with anything else, although you can request them in
combination with other things.  (The exact list of characters given
this special treatment is certainly open to debate.  It has no
particular impact on performance or development time.)

  At a future date, the software handling this could be re-written to
optimize assignment of groups of characters to channels so as to allow
you to see any combination you want, subject to the availability of
channels.  This is not a requirement of any software we know.  This
extension would only be implemented if required by some future
software.  Its implementation would be transparent to existing
software.

.hl 3 Performance considerations

  There are many packages which get called many times during a
relatively short program run.  For example, MTHLIB, RMS (once per
record), sometimes SORT.  It is important to minimize the cost of an
explicit layer transition.  

  Actual exceptions occur relatively rarely, and when they do often
result in program termination or at least user interaction.
Accordingly, it is not as important for the actual handling of
exceptions to be fast.  Trading off slower exception handling for
faster layer transitions is a desirable thing to do.  (Obviously in an
ideal world both would take zero time.  If you know how to achieve
this, please come explain it to me....)

  The one possible exception to this is arithmetic traps.  These can
sometimes occur without indicating a package-level error, and thus may
occur frequently in a single run.  Some packages treat arithmetic
traps as errors.  For them, signalling the trap is fine.  Some things
(written in MACRO) want to test for errors immediately after the
instruction that produced them.  For them, we are making the default
handling of a trap include a check for a JFCL-class instruction right
after it.  If such an instruction is present, the trap is ignored.

  To ease conversion of existing libraries, and improve performance of
libraries depending extensively on APR traps, there is a facility for
requesting that all traps originating in a given section be directed to
a specified handler.  This option, if invoked, completely bypasses
MTHTRP fixups, signal generation, and message printing for APR traps
originating in specified sections.

.hl 4 Arithmetic Trap Default Actions

  Fixups are as performed by MTHTRP.  Putting a JFCL (of any flavor)
after an instruction that may cause an overflow will work normally
(MTHTRP looks for them).  In the absence of a JFCL, after determining
the error and possibly fixing things up MTHTRP generates a signal.  If
this signal isn't intercepted, the last-ditch handler will print the
message it describes.

.hl 2 Errors and message printing

  The signal block contains information to make printing error
messages as easy as possible -- for example, facility names and error
messages are present as text, so no decoding is necessary.  There are
also print flags in the blocks, specifying any special aspects of that
block (such as a block which is for computer use only, contains no
message, and should not be printed at all).

  A routine is provided for printing the messages from some initial
segment of the signal blocks in a chain in a uniform format.  This is
used by the last-ditch handler, and is recommended for use by user
routines that wish to print messages.  

.HL 2 Dynamic Library contents

  A dynamic library consists of several pieces, including

  An EXE file which contains:

.LIST 1, "o"
.le;A PDV with the name "DYNLIB$class-name".  Word 2 (formerly called
`.PVSTR) in the PDV should point to the master dynamic library block
(DLBLK) for this library.  Word 4, .PVVER, by convention contains the
version number of the library.
.LE;The DLBLK for the library.  This block describes the entry points
and other exported addresses of the library.
.le;The necessary code and data to perform the library's functions.
.end list

  A REL file which contains information for the caller to link with.

  The normal case (an LDLBLK file):
.list 1, "o"
.le;The local dynamic library block  (LDLBLK) for the library.  This
block describes the entry points and other exported addresses of the
library and contains the address vectors through which references to
the actual library objects are made.
.end list

  A special case, useful when converting callers of existing libraries
or making the calls from higher-level languages that don't support the
concept of pointers to routines (an LDLJCK file):
.list 1, "o"
.le;The local dynamic library block  (LDLBLK) for the library.  This
block describes the entry points and other exported addresses of the
library and contains the address vectors through which references to
the actual library objects are made.
.le;A  jacket routine for each routine in the library.  This routine
expects to be called by a simple PUSHJ.  It then calls the routine in
the library through the transfer vector.
.end list

A very special case, only partially supported, useful when calling
libraries from existing programs which cannot easily be converted to
run in a non-zero section (ALL NEW PROGRAMS SHOULD RUN IN NON-ZERO
SECTIONS) (an LDLZER file): 
.LIST 1, "o"
.le;The local dynamic library block  (LDLBLK) for the library.  This
block describes the entry points and other exported addresses of the
library and contains the address vectors through which references to
the actual library objects are made.
.le;A  jacket routine for each routine in the library.  This routine
expects to be called by a simple PUSHJ.  It then massages the
arguments, PC section, and stack pointer and calls the routine in the
library through the transfer vector.
.end list

.hl 2 Support facilities

  Two REL libraries of support code exist.  One or both of them must
be linked into any program calling a dynamic library:

.LIST 1, "o"
.le;DYNBOO -- This is the normal bootstrap code, used with LDLBLK and
LDLJCK files.
.le;ZERBOO -- This is the special section-zero bootstrap code, used
with LDLZER files.  It must be used along with DYNBOO.  One of its
functions is to map section zero into a non-zero section; this section
is specified by the contents of location DY$ZMS, which may be set by
the user before the first dynlib call (it defaults to 1).
.end list

.HL 2 Section zero capabilities

  These capabilities are provided only to allow existing programs to
call dynamic libraries, in cases where causing the existing program to
run in a non-zero section would be prohibitively expensive.  In
general, dynamic libraries cannot be called from section zero, nor can
they ever be loaded into section zero.  These capabilities are
provided specifically in response to urgent needs of various products,
and should not be considered for general use.

  Provisions are provided for a program running in section zero to
call a specially-written dynamic library, passing arguments.  The
arguments may be passed in any way that provides sufficient
information, and that the library can accept.  In simple cases,
particularly arguments passed by value (which are not addresses), no
special requirements will be imposed on the library.  (See the
description of the LDLZER file above)

  Provisions are provided for a dynamic library called from section
zero to make a callback to a routine in section zero (as an error
handling routine specified in the original call).  The routine called
back to need not be specially written.  (See routine DY$CBK)

  Provisions are provided to disable DYNLIB arithmetic trapping.  This
is advised for all programs that have a portion running in section
zero, as a trap originating in section zero will cause the program to
crash if trapping is enabled.  (See routine SG$NAS)

.HL 2 Writing dynamic libraries

  A library is put together from at least 3 (and perhaps 5) parts:
.s 1.list 0
.le;The code and data to perform the library functions
.le;A definition of the library entry points and characteristics
.le;A LDLBLK file 
.le;A LDLJCK file (optional)
.LE;A LDLZER file (optional)
.end list

  Parts three and four can (and should) be built automatically from
part one by using the $DLBLK, $LDLBLK, and $LDLJCK macros from
DYNSYM.UNV.


  Note that making an existing library into a dynamic library can
sometimes be fairly easy, requiring only the production of a library
definition.

.hl 3 The library definition

  The library definition provides one place to put all the
declarations relating to the dynamic library and its exported
addresses.  This makes for easy reference, and fewer mistakes since
all places using this information get it from the definition.

  The definition must specify:
.s 1.list 0, "o"
.le;Library name -- must be a valid MACRO name
.le;Library abreviation -- two characters
.le;Library macro name -- must be a valid MACRO name
.le;Library version -- TOPS-20 version number word
.le;Default version matching rule for this library
.le;Service class name -- quoted string
.le;File spec for library EXE file -- quoted string
.le;List of DIGITAL-specified entry point names in their specified
order.  Each entry in this list may be either a single name, or a
sublist as follows:
.s 1.list 0
.le;vector name -- Name user calls to get this routine
.le;real name -- Name of routine in library
.le;call name -- Name for jacket routine in LDLJCK, LDLZER files
.le;sect zer call process -- Code to massage arguments when calling
from section zero (see support macros $FC, $AR in DYNSYM.UNV)
.end list
  Default call and real name is vector-name.  The call-name and the
sect-zer-call-process must be blank for galactic variable entries.
  All of the entry points defined by DIGITAL must be present, or an
error will be issued when you compile the definition.
.le;List of library-specific entry point names.  Same rules as for
previous entry
.le;List of DIGITAL-specified galactic variable names in their
specified order.  All of the galactic variables defined by DIGITAL
must be present, or an error will be issued when you compile the
definition.

.le;List of library-specific galactic variable names
.le;Value to statically initialize user word in DLBLK to
.le;Value to statically initialize user word in LDLBLK to
.le;Value to statically initialize flag word in DLBLK to
.le;Value to statically initialize flag word in LDLBLK to
.end list

.hl 3 The LDLBLK file

  For each library, there must be a source file to build the LDLBLK
file.  Its contents should be as follows:
.s 1.lm 4.nofill.nojust
SEARCH DYNSYM, library-sym
$LDLBLK library-macro
END
.fill.just.lm 0

.hl 3 The LDLJCK file

  For each library you wish to support non-indirect calls to, there
must be a source file to build the LDLJCK file.  Its contents should
be as follows:
.s 1.lm 4.nofill.nojust
SEARCH DYNSYM, library-sym
$LDLJCK library-macro
END
.fill.just.lm 0

.hl 3 The LDLZER file

  For each library you wish to support section zero calls to, there
must be a source file to build the LDLZER file.  Its contents should
be as follows:
.s 1.lm 4.nofill.nojust
SEARCH DYNSYM, library-sym
$LDLZER library-macro
END
.fill.just.lm 0

.hl 3 Master Initialization

  The master init routine of a library should, when called, set that
library to a clean state.  A freshly master initialized library should
behave exactly as if a clean copy had been loaded.

  One of the most important things to do in the master initialization
routine is to properly initialize the memory allocation tables.  This
should be done by using a static data structure made at the time the
library was built.  Attempting to snoop for free pages in the master
initialization routine won't work, since pages used during a run will
not be free, and yet should become available after master
initialization.

  The master initialization routine should not do a RESET% JSYS, that
will be done by the top-level program.

  The master init routine is called with a PUSHJ 17, adr.  It may
trash all registers.

  Arguments: None

  Return values:
.s 1.list 0
.le;Completion status.  0 means OK, anything else means failure.  A
master init routine may also signal a condition that indicates
failure. 
.end list

  Error conditions: library-dependent

.hl 3 Condition handling routines

  A condition handler is called with a PUSHJ 17, adr.  It may use all
registers. 

  Arguments:
.s 1.list 0
.le;Address of SIG block for signal to handle.
.end list

  If the signal is of class SG%UNW, the handler is expected to perform
any necessary cleanup and then exit.  No value is returned in this
case.

  If the signal is of any other class, the handler is expected to
decide what should be done about the condition, and indicate this to
SIG by its return value.

  Return values:
.s 1.list 0
.le;AC0 is the value to be returned by this handlers establisher (ONLY
IF AC2 CONTAINS .HNUNW)
.LE;AC1 is the signal block to pass upwards (ONLY IF AC2 CONTAINS
`.HNRES) 
.LE;AC2 is the action code describing what action to take:
.LIST 0, "o"
.le;`.HNUNW -- unwind.  This causes a return from the establisher of
this handler to the caller of the establisher, passing in AC0 the
return value specified now in AC0.
.le;`.HNCON -- continue.  This ends condition handling and causes
processing to continue from after or at the instruction that initiated
the signal.
.le;`.HNRES -- resignal.  This passes the same or a modified condition
on to any higher-level condition handlers.  In general, a signal block
should not be modified unless you own it; to resignal a different
condition than the one you received, make a new signal block
containing what you want to say, and set its .SGNXT pointer to the
block you received.
.end list
.end list

.hl 2 Details of data structures

.hl 3 The Dynamic Library Block

.LIST 0
.LE;`.DYCNT -- block word count (must be 9 currently)
.LE;`.DYFVN -- Block format version number
.LE;`.DYFLG -- Flag word (DIGITAL defined only)
.LIST 0
.LE;DY%BSY -- Busy: library can't start a stream
.le;DY%VER -- Version matching rules.  Version number from DLBLK in
this library is compared to version number in LDLBLK and this library
is accepted if:
.list 0
.le;DY%MAG -- major version of library greater than major version of LDLBLK
.le;DY%MAL -- major version of library less than major version of LDLBLK
.LE;DY%MIG -- major versions equal and minor version of DLBLK greater
.le;DY%MIL -- major versions equal and minor version of DLBLK less
.end list 0
.END LIST 0
.LE;`.DYUSR -- Library-use word
.LE;`.DYVER -- Library version number
.LE;`.DYDTV -- IFIW Address of DIGITAL-specified entry-point vector (DTVEC)
.LE;`.DYCTV -- IFIW Address of library-specific entry-point vector (CTVEC)
.LE;`.DYDGV -- IFIW Address of DIGITAL-specified galactic variable
vector (DGVEC)
.LE;`.DYCGV -- IFIW Address of library-specific galactic variable vector (CGVEC)
.END LIST

  [The possibility of additional entries is reserved to DIGITAL]

  For each of the four classes of exported addresses described above,
there is a separate address vector.  Each is a counted vector.

.s 1.LITERAL
DTVEC:	diglen+1
	IFIW routine entry-point
	. . .
	IFIW routine entry-point

CTVEC:	cuslen+1
	IFIW routine entry-point
	. . .
	IFIW routine entry-point

CGVEC:	cgalen+1
	IFIW address
	. . .
	IFIW address
.END LITERAL

.hl 3 The local dynamic library block

  This block is linked into a calling program from a library-provided
REL file.  It provides the section-local indirect words necessary
for referring to addresses in other sections.  It also provides the
information to identify and map in the library being called, if
necessary.

.s 1.list 0
.LE;`.LDCNT -- Word count (block length) (must be 11 currently)
.LE;`.LDFVN -- DYNLIB version number for which this LDLBLK was compiled 
.LE;`.LDFLG -- Flag word (DIGITAL-defined only).  Flags defined are:
.list 0
.LE;LD%VMA -- Use version match rules from this LDLBLK rather than
from DLBLK
.le;LD%VER -- Version matching rules.  Version number from DLBLK in
library found is compared to version number in this LDLBLK and that
library is accepted if:
.list 0
.le;LD%MAG -- major version of library greater than major version of LDLBLK
.le;LD%MAL -- major version of library less than major version of LDLBLK
.LE;LD%MIG -- major versions equal and minor version of DLBLK greater
.le;LD%MIL -- major versions equal and minor version of DLBLK less
.end list 0
.le;LD%INI -- Initialized: library has been loaded and vectors updated 
.end list 0
.LE;`.LDUSR -- User word; may be set by calling program in any way it
wants 
.LE;`.LDCLS -- OWL/GBP to "service class" string
.LE;`.LDSPC -- OWL/GBP to file spec string
.LE;`.LDVER -- Library version number
.LE;`.LDDTV -- IFIW Address of DIGITAL-specified entry-point vector (LDTVEC)
.LE;`.LDCTV -- IFIW Address of library-specific entry-point vector (LCTVEC)
.LE;`.LDDGV -- IFIW Address of DIGITAL-specified galactic vector
.LE;`.LDCGV -- IFIW Address of library-specific galactic vector (LCGVEC)
.end list
.S 1
[The possibility of additional entries is reserved to DIGITAL]

  As in the DLBLK, there is a transfer vector for each of the four
classes of exported addresses described above.

.hl 3 The signal block

  This data structure represents one level of a signal in progress.
The top (most recently added) level of a signal in progress is
supplied to routines.  Lower levels are available by following the
pointer to next block.

  All of the pointers are expected to point either into the signal
block, or into static storage (which need not be released when the
signal block is released).  The pointers may not point into stack
storage, as this may have been released by the time the pointer is
used!

.test page 6
  Block contents:
.s 1
.list 0
.le;`.SGCC -- Condition code
.le;`.SGNXT -- xFIW address of next block
.le;`.SGFAC -- OWL/GBP to ASCIZ facility name
.le;`.SGCND -- OWL/GBP to ASCIZ condition name
.le;`.SGMSG -- OWL/GBP to ASCIZ message
.le;`.SGPC -- PC of source of signal
.le;`.SGCLS -- Class of condition (bit mask)
.LIST 0, "o"
.LE;SG%UNW -- Unwind
.LE;SG%APR -- APR trap
.LE;SG%DER -- Data error interrupt
.LE;SG%QUO -- Disk quota interrupt
.LE;SG%EOF -- End of File interrupt
.LE;SG%ILI -- Illegal instruction interrupt (or monitor call error)
.LE;SG%ILR -- Illegal memory read interrupt
.LE;SG%ILW -- Illegal memory write interrupt
.LE;SG%INS -- Inferior stop interrupt
.LE;SG%NXM -- Non-existent page interrupt
.LE;SG%PDL -- PDL overflow interrupt (not useful?)
.LE;SG%SOF -- Software-originated signal
.LE;SG%RES -- System resources interrupt
.LE;SG%CHR -- Character interrupt
.LE;SG%TRM -- Terminal interrupt
.END LIST 0
.le;`.SGFLG -- flag word (DIGITAL-defined only)
.LIST 0, "o"
.LE;SG%INT -- At interrupt level
.LE;SG%NPR -- Do not print this block (computer use only)
.LE;SG%DYN -- This block is dynamic and may be thrown away
.END LIST 0
.le;`.SGDAT -- xFIW address of signal-specific data, such as:
.list 0, "o"
.le;Character mask for character interrupt
.le;Values involved for APR traps
.le;Page number for nonexistent page traps
.le;Stack pointer for stack overflow traps
.le;User data for software signals
.end list 0
.end list

.hl 3 The condition code

  A condition code is a one-word representation of the raw bones of a
condition.  It is essentially the same as a BLISS-36 condition code.
.S 1
.LITERAL
                     SG%FAC                     SG%MSG          SG%SEV

     +---+---------------------------+---------------------------+---+
     |   |                           |                           |   |
     +---+---------------------------+---------------------------+---+

      0 0 0                         1 1                         3 3 3
      0 3 4                         7 8                         2 3 5
.END LITERAL

  Bit 4 (SG%FCD) is set if the facility is customer-defined, clear if
DIGITAL-defined.  Bit 18 (SG%MCD) is set if the message is
customer-defined, set if DIGITAL-defined.  SG%ID covers the full
condition ID, bits 4-32.  SG%SUC is the success bit (35).

.hl 3 The handler block

  A handler block is the set of information describing an establishing
of a handler.  It is the argument passed to the SIGEST routine.  This
block may be dynamically allocated, but it must remain in existence
(in the same place) throughout the life of the handler it describes.

.s 1.list 0
.LE;`.HNHND -- xFIW address of handler
.LE;`.HNCLS -- Enable mask (see bit definitions above)
.LE;`.HNCIM -- Character interrupt mask
.LE;`.HNUDA -- xFIW address of user data

.LE;`.HNLEN -- Size of block in words
.end list

.hl 2 Details of explicit calls

  There are many functions that the user may request DYNLIB and
related facilities to perform.  These functions are implemented in the
run-time library; they are called as any dynamic library routine.

  Unless specified otherwise, errors are reported by signalling.  This
signal can be prevented by placing an ERJMP or ERCAL instruction
immediately following the potentially offending instruction (and in
this case the address of the signal block is returned in AC1).

  The calling sequence for these routines is as follows: Arguments go
in sequential registers starting with AC1.  Return values go in
registers sequentially following the arguments, unless specified
otherwise (such as updated values of input arguments).  The routines
should be called as ordinary routines in a dynamic library -- with
.i 5;PUSHJ P, @routine-name
.b 0;if the LDLBLK file is used, or with
.I 5;PUSHJ P, routine-name
.B 0;if the LDLJCK file is used.

  Registers 6-17 are preserved unless otherwise specified.

.HL 3 Call back to section zero -- DY$CBK

  Call a routine in section zero in such a way that when that routine
does a RET, control will return to the statement after the DY$CBK
call.  This is accomplished using support code provided by ZERBOO.

  Preserves no registers (all registers are preserved until the
routine being called back to is reached; all registers are preserved
from when the user routine does a POPJ 17, until the instruction after
the DY$CBK call is reached).

  Arguments (passed on the stack, pushed in the order indicated):
.s 1.list 0
.le;Address of routine to call back to
.le;Return address (in section zero) of library routine user called
(we wouldn't be running in an extended section if the user hadn't
called some library routine; presumably it called something, which
called something, which eventually called DY$CBK)
.end list

  Arguments to the routine being called back to may be passed in AC's,
or pushed onto the stack before the DY$CBK arguments, or both.

  Return values: As implemented by the user routine being called.

.hl 3 Return last DYNLIB error -- DY$LER

  (Not yet implemented)

  Returns the address of the signal block (first of chain) describing
the last DYNLIB error, or 0 if no error has been detected.  This
signal chain is dynamically allocated; if another DYNLIB error occurs
between the time you get the information and the time you use it, it
will be invalid.  You should not attempt to de-allocate this block.

  Arguments: None

  Return values:
.s 1.list 0
.le;Address of signal block (first of chain), or zero if no error
occurred 
.end list

  Error conditions: None

.hl 3 Force loading/Overloading -- DY$LOD

  (Not yet implemented)

  Force the loading of a dynamic library before a reference to an
address exported from it occurs.  This could be useful, for example,
to cause the loading of a library containing a galactic variable you
need to reference when there are no routines in that library, or none
that you want to call.

  This call also supports overloading -- deliberately loading
information about two libraries into one LDLBLK.  This can be useful
to replace a few routines in a library with private copies, without
having to duplicate the entire library.  These private copies could be
debugging versions of routines not yet ready to be included in the
real library, for example.

  Arguments:
.s 1.list 0
.le;Function
.S 1.LIST 0
.LE;`.DYLOD -- Force loading of library.
This function cannot be applied to the run-time library.
.le;`.DYOLB -- overload one library onto another
.LE;`.DYOVC -- overload one vector onto another
.END LIST
.end list

  Other arguments depend on the function code.

  The normal rules for overloading are as follows:

.s 1.list 1
.le;LTVEC entries not containing their default initial state will not
be altered.  The default initial state is "IFIW LDLBLK-1" for the
user-mode implementation.
.le;If an MTVEC entry contains 0 in its right half, the corresponding
LTVEC entry is not altered.  0 in the right half covers IFIW 0 and
location 0 in any section. 
.le;If the LTVEC is longer than the MTVEC, excess LTVEC locations are
not altered.
.le;If the MTVEC is longer than the LTVEC, the additional MTVEC
entries are ignored.
.end list

.HL 4 .DYLOD -- Force loading of library
  Additional arguments:
.s 1.list 0
.le;Address of the LDLBLK of the library to load
.end list

  Error conditions:
.s 1.list 0, "o"
.le;Any error possible when implicitly loading a dynamic library
.end list

.HL 4 .DYOLB -- overload one library onto another

  Load one library over another according to the rules for
overloading.  Standard version checking is performed on both DYNLIB
and library versions for both source and destination libraries.

  Arguments:
.s 1.list 0
.le;Address of LDLBLK of source library (need not be already mapped
in)
.le;Address of LDLBLK of destination library (need not be already
mapped in)
.end list

  Error conditions:
.s 1.list 0, "o"
.le;Any error possible when implicitly loading a dynamic library
.end list

.HL 4 .DYOVC -- overload one vector onto another

  This function is used to overload only one address vector from one
library over another.  Standard version checking is performed on both
source and destination libraries.

  Arguments:
.s 1.list 0
.le;Address of LDLBLK of source library 
.le;Address of source vector
.le;Address of LDLBLK of destination library
.le;Address of destination vector
.end list

  Error conditions: 
.s 1
.list 0, "o"
.le;Any error possible when implicitly loading a dynamic library may
occur 
.end list

.hl 3 Global Master Initialization -- DY$MIN

  Resets all libraries already mapped in to their uninitialized state
by calling the master initialization point in each such library.

  All registers are trashed.

  Arguments: None

  Error conditions: 
.s 1.list 0, "o"
.le;Any error condition signalled or returned in the defined manner by
any of the master initialization routines called is passed on to the
caller of DY$MIN.
.end list

.hl 3 Allocate memory block -- ME$ALM

  Allocate a block of memory without page alignment.

  Arguments:
.s 1.list 0
.LE;Chunk identifier
.le;Block size in words
.end list

  Return values:
.s 1.list 0
.le;(in T1) Chunk identifier
.le;(in T2) Address of block allocated
.end list

  Error conditions:
.s 1.list 0, "o"
.le;No room in chunk specified for block requested
.le;Chunk specified is invalid
.end list

  The block returned starts at the address given and is the length
specified.  The words preceeding and following the block contain RTL
information used when the block is released.  Since this word is not
part of the block given you, it should be no strain to keep your hands
off it!

.hl 3 Allocate Pages of Memory -- ME$ALP

  (Not yet implemented)

  Allocate memory in full, contiguous pages.

  Arguments:
.s 1.list 0
.le;Chunk in which to allocate
.le;Number of pages to allocate
.end list

  Return values:
.s 1.list 0
.le;Address of first page allocated
.end list

  Error conditions:
.s 1.list 0, "o"
.le;Section not under control of RTL
.le;Space requested not available in section requested
.end list

.hl 3 Create a new section -- ME$ALS

  (Not yet implemented)

  Allocates a free section and creates it (the monitor doesn't
automatically create a section when you first refer to an address in
it, as it does for individual pages within pre-existing sections).

  Optionally, puts the newly-created section under the control of the
RTL memory manager.

  This is the only valid way to create a section in the DYNLIB
environment.  (The section that a new dynamic library is mapped into
is allocated through ME$ALS by DYNLIB.)

  This should probably be extended to allocate groups of contiguous
sections.

  Arguments: 
.s 1.list 0
.le;Set if section should be controlled by the RTL memory manager
.end list

  Return values:
.s 1.list 0
.le;Number of the section allocated
.end list

  Error conditions:
.s 1.list 0, "o"
.le;No sections available
.end list

.hl 3 Return memory block -- ME$DLM

  Return a block of memory allocated with ME$ALM.

  Arguments:
.s 1.list 0
.le;Address of block to return
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;ME$NAL: Block wasn't allocated 
.end list

.hl 3 Return Memory Pages -- ME$DLP

  (Not yet implemented)

  Arguments:
.s 1.list 0
.le;Address of first page
.le;Number of pages
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Section not under control of RTL
.le;Some or all of the pages being returned were not allocated
.end list

.hl 3 Destroy a section -- ME$DLS

  (Not yet implemented)

  Sections not under the control of the RTL memory manager are
destroyed immediately on request.

  Sections controlled by the RTL memory manager are "frozen" on this
call -- no more space will be allocated out of them.  They will be
destroyed when all of the space allocated from them is returned.

  This needs support for groups of sections (as in ME$ALS).

  Arguments:
.s 1.list 0
.le;Section number
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Section is not allocated
.end list

.hl 3 Sub-contract Memory Management -- ME$MEM

  Create a memory chunk that can be allocated from.

  Arguments:
.s 1.list 0
.le;Address of first word of chunk
.le;Address of last word of chunk
.end list

  Return values: 
.s 1.list 0
.le;Chunk ID in T3
.end list


  Error conditions:
.s 1.list 0, "o"
.le;ME$NCA: No chunk ID available
.end list

.hl 3 Convert two-word byte pointer to global -- RL$2BG

  Convert a two-word global byte pointer to be a one-word global byte
pointer.  Passes one-word byte pointers unchanged.

  Arguments:
.s 1.list 0
.le;First word of byte pointer
.le;Second word of byte pointer
.end list

  If byte pointer is 2-word, it must be global format and must not
specify indirection or indexing.  (One-word byte pointers are passed
unchanged.) 

  Return values:
.s 1.list 0
.le;One-word global byte pointer
.end list

  Error conditions:
.s 1.list 0, "o"
.le;RL$IBF -- Illegal byte pointer format: !BP
.le;RL$IBS -- Illegal byte size in !BP
.le;RL$IBP -- Illegal byte position in !BP
.end list

.hl 3 Formatted ASCII Output -- RL$FAO

  Format a message given a model string and some arguments to fill in
from.

  Arguments:
.s 1.list 0
.LE;Destination string pointer
.le;Max allowable destination string length
.le;Model (pattern) string pointer
.le;Address of first arg (others follow at higher addresses).  Note
that this may be on the stack, or elsewhere; FAO doesn't care
.le;Count of args
.END LIST

  Return values:
.s 1.list 0
.le;Destination pointer is updated in T1
.le;Count is decremented in T2
.le;T3-T5 are trashed
.end list

  The pattern string is a simple ASCIZ string with special escape
sequences in it that cause substitution from the list of arguments.
Each argument is used at most once, in the order listed.

  All escape codes begin with an exclamation point.  The codes and
their meanings are:
.lm 5
.tab 15
.set paragraph 15, 0, 0
.nofill.nojust
.p;`!/	Put a CRLF into output 
.p;`!`_	Put a TAB into output
.p;`!`!	Put an exclamation mark into output
.p;`!`^G	Put a BEL into output (ASCII 7, not ^G)
.p;`!OW	Put next arg to output as octal word
.p;`!SW	Put next arg to output as signed decimal word
.p;`!OH	Put next arg to output as octal halfwords (good for PC's)
.p;`!AA	Put 7-bit ASCIZ string at address given by next arg to output
.p;`!AZ	Put ASCIZ string pointed to by next arg to output
.p;`!AC	Put string pointed to by next arg to output, max of next arg
chars
.p;`!%S	Put capital S to output if last number printed was not 1
.p;`!%s	Put lower case s to output if last number printed was not 1
.p;`!JFN	Put file spec corresponding to JFN in next arg to
output
.p;`!VER	Put next arg to output interpreted as version number
.p;`!JER	Put JSYS error text for error code in next arg to
output
.P;`!BP	Put next arg to output displayed as  byte pointer
(local or global, one or two words).  Note: You provide one or two
words of argument depending on the byte pointer format.
.lm 0
.set paragraph 0, 1, 3
.fill.just

.hl 3 Convert one-word byte pointer to global -- RL$LBG

  Convert a one-word local byte pointer to be a one-word global byte
pointer pointing into the section from which it was fetched.  Passes
one-word global byte pointers unchanged.

  Unlike the GETBP macro in DYNSYM.UNV, this routine performs
extensive error checking.

  Arguments:
.s 1.list 0
.le;30-bit address of a byte pointer (local or one-word global)
(NOT an EFIW, no indexing or indirection allowed)
.end list

  Return values:
.s 1.list 0
.le;One-word global byte pointer
.end list

  Error conditions:
.s 1.list 0, "o"
.le;RL$IBF -- Illegal byte pointer format: !BP
.le;RL$IBS -- Illegal byte size in !BP
.le;RL$IBP -- Illegal byte position in !BP
.end list

.hl 3 Allocate An Interrupt Channel -- SG$ALC

  (Not yet implemented)

  Arguments: None

  Return values:
.s 1.list 0
.le;Channel assigned
.end list

  Error conditions:
.s 1.list 0, "o"
.le;No interrupt channels available
.end list

.hl 3 Disable Interrupt Characters -- SG$DIC

  (Not yet implemented)

  Requests that a character be made a non-interrupt character.  Note
that the count of enable versus disable requests is what controls the
actual status of a character at any given moment

  Arguments:
.s 1.list 0
.le;Character mask
.end list

  Error conditions: None

.hl 3 Return An Interrupt Channel -- SG$DLC

  (Not yet implemented)

  Arguments:
.s 1.list 0
.le;Interrupt channel to return
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;The interrupt channel returned was not allocated
.end list

.hl 3 Deallocate a signal chain -- SG$DLG

  Deallocate all blocks in a signal chain flagged as dynamic.

  Arguments:
.s 1.list 0
.le;Address of first block in chain
.end list

  Return value: None

  Error conditions:
.list 0, "o"
.le;ME$NAL: Block not allocated (for any block along the chain)
.end list

.hl 3 Dump an SG chain -- SG$DMG

  Print a formatted dump of a chain of SG blocks on the terminal.

  Arguments:
.s 1.list 0
.le;Address of first block in chain
.end list

  Return Value: None

  Error conditions: None

.hl 3 Enable Interrupt Characters -- SG$EIC

  (Not yet implemented) 

   Requests that a set of characters be made interrupt characters.
The count of enable versus disable requests is what controls the
actual status of a character at any given moment.

  Arguments:
.s 1.list 0
.le;Character mask
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Insufficient interrupt channels available
.le;Cannot isolate characters you want from previous requests
.end list

.hl 3 Establish A Condition Handler -- SG$EST

   Establish a condition handler for the current routine.  SIGEST must
be called before anything is done to the stack within the routine.

  There are restrictions on the linkage conventions of routines that
establish handlers.

  ALL registers are preserved.

  Arguments (pushed onto the stack before call):
.s 1.list 0
.le;Address of handler block (this block may be dynamically allocated,
but it must remain in existence throughout the life of the handler)
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Invalid handler block
.le;Insufficient room on enable stack
.end list

.hl 3 Establish a handler locally -- SG$LES

This is a version of SG$EST to be called from within BLISS routines.
This routine is for use by WIZARDS only!!  In particular, unwinding to
a routine that enables for condition handling this way is almost
certainly a mistake.

  Registers 2-16 are preserved.

  Arguments:
.s 1.list 0
.le;Address of handler block 
.end list

  Return Values: None

  Error conditions: None

.hl 3 Remove a handler locally -- SG$LRM

  Remove a locally established handler

  Registers 2-17 are preserved.

  Arguments:
.s 1.list 0
.le;Address of handler block 
.end list

  Return value: None

  Error conditions:
.s 1.list 0, "o"
.le;SG$ROS: Cannot remove a handler other than the most recently established
.end list

.hl 3 Make signal block for last monitor error -- SG$MER

  (Not yet implemented)

  Arguments: None

  Return values:
.s 1.list 0
.le;Address of signal block created
.end list

  Error conditions:
.s 1.list 0, "o"
.le;No monitor error has occurred
.end list

.hl 3 Disable DYNLIB trap handling -- SG$NAS

  Prevent DYNLIB from enabling the arithmetic trap system.  This is
recommended for all programs which run partly in section zero, since a
trap occurring in section zero will crash the trap handler (this was a
trade-off against cost of handling a trap originating in a non-zero
section).

  Arguments: None.

  This routine should be called before DY$MIN in the main program
only.  This is the only case of a dynamic library routine which should
be called before DY$MIN.

.hl 3 Print error messages -- SG$PEM

  Prints a sequence of error messages from a chain of signal blocks.
Various arguments control depth and format of printing.

  Arguments:
.s 1.list 0
.LE;Destination designator
.le;Address of signal block
.le;Maximum depth to print messages for
.le;Address of suffix list
.le;Address of prefix list
.end list

  The prefix and suffix lists are vectors of OWL/GBP to ASCIZ strings,
intended to be indexed by severity.  The strings pointed to are
prefixes and suffixes for messages.

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Invalid signal block encountered
.end list

.hl 3 Remove A Condition Handler -- SG$REM

  Remove the condition handler established for the current routine.
This must be done just before routine exit.

  All registers are preserved.

  Arguments (push on stack):
.s 1.list 0
.le;Address of handler block (must be same block passed to SIGEST)
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;The handler being removed is not the most recently established one
.le;Invalid handler block
.end list

.hl 3 Declare Trap handler for section -- SG$SEC

  (Not yet implemented)

  Specify an APR trap and fixed interrupt handler for all events
occurring in a specified section.  This is provided for convenience in
converting existing libraries with their own trap handlers, and to
allow use of traps in a library without the overhead of enabling for
condition handling.

  Arguments:
.s 1.list 0
.le;Section number
.le;Address of handler block
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;A handler has already been established for the section specified
.le;The section specified does not exist
.end list

.hl 3 Signal -- SG$SIG

  Signal a software condition.  Under some conditions, this routine
does not return.  This is determined by whatever handler finally
handles the signal.  If it does return, it returns with all registers
preserved.

  Arguments:
.s 1.list 0
.le;Address of signal block
.end list

  Return values: None

  Error conditions:
.s 1.list 0, "o"
.le;Invalid signal block
.end list

.hl 2 Details of Galactic Variables defined

  The RTL defines some galactic variables to allow users to control
certain aspects of its operation without having to make calls to
special routines to set internal values.

.HL 3 Signalling information

  SIG makes certain internal information available as galactic
variables.

.hl 4 Enable stack pointer -- SG.ENS

  The stack pointer for the enable stack.  Each frame on the enable
stack holds an establish block describing one handler that is
currently established.

  This is for use by experts only!  You can cause a lot of trouble
with this, if you want.

.HL 3 Last-ditch handler parameters

.HL 4 Maximum depth -- SG.LEV
  No more than this many levels of messages will be printed (blocks in
a signal chain for which no message is printed do not count against
this limit).  To print "all" levels, set this to an outrageously high
positive value.  Signal chains should never get "too" deep.

.hl 4 Destination designator -- SG.OUT
  Last-ditch messages may be directed to places other than primary
output.  If attempting to output to the destination specified fails,
it will be reset to primary output and the message will be printed
there.  Setting this to a byte pointer has some potential problems --
it doesn't get copied back to SG.OUT after it's used, so messages will
overlay each other in the memory area specified.

.hl 4 Prefix table address -- SG.PFX
  The prefix table is indexed by severity to find the OWL/GBP to
an ASCIZ string to print before the message.  This is where the "?"
before errors or the "[" before informational messages comes from.

.hl 4 Suffix table address -- SG.SFX
  Like SG.PFX, but strings go after the message.  This is where the
"CRLF" after errors or the "]CRLF" after informational messages comes
from.

.hl 4 Default prefix table -- SG.DPX
  This is the default prefix table.  By executing
.i 5;XMOVEI T0, @SG.DPX
.I 5;MOVEM T0, @SG.PFX
.BR;you will reset the LDH to use the default prefix table.  You
should not attempt to change the contents of the default prefix table
-- it may be in write-protected memory.

.hl 4 Default suffix table -- SG.DSX
  This is the default suffix table, very similar to SG.DPX.

.hl 2 DYNLIB bootstrap

  As much of DYNLIB as possible will actually reside in the RTL.
Since DYNLIB is used to bring in the RTL, "as much as possible" will
be less than "all".  

  The subset of DYNLIB necessary to bring in the RTL will be available
in the file DYNBOO.  All programs calling dynamic libraries must link
with DYNBOO.
.hl 1 Publications

  DYNLIB development will include the preparation of two documents,
"How to write a Dynamic Library" and "How to call a dynamic library",
intended respectively for developers of dynamic libraries and users of
dynamic libraries.  

  These documents will be prepared by the engineering staff, there is
no funding for technical writers.

  There is no plan to distribute these documents outside of Digital.
.hl 1 Packaging

  The DYNLIB facility is being developed for Datatrieve.  We want to
make it available to all layered products in the longer run.  The
first release of DYNLIB will be packaged with Datatrieve-20 version 1.
.hl 1 Installability

  DYNLIB will be installed as part of the installation of
Datatrieve-20. 
.hl 1 Ease of Use
.hl 1 Performance

  Since DYNLIB is intended to be widely used as the basis for building
products out of layers of building-blocks, performance can be an
important issue.  We believe, based on the usage of existing
libraries, that the vast majority of the interactions between a caller
and a package will be routine calls.

  Calling a routine in a dynamic library will be done with a single
PUSHJ using one level of indirect addressing (unless the user writes
code requiring more to get to the transfer vector) after the first
call through any given LDLBLK.

  Referring to an exported address will simply require one additional
level of indirection relative to referring to that address locally.
Since indirection is necessary to reference outside of the current
section anyway, DYNLIB will cost absolutely nothing on references
after the first.

  The first reference to an address exported from a dynamic library
will potentially take a long time, since a GTJFN% is performed.  This
could potentially require searching through thousands of file-names,
if the logical names used are defined wrong.  There is also the matter
of creating a section and mapping the file into that section.  On a
"reasonably" heavily loaded system, and assuming only moderately
perverse search lists, it could take 5 seconds to load a dynamic
library.

  The other DYNLIB functions are very infrequently used and are not
performance-critical.

  Many of the RTL functions have no performance requirements in the
Product Requirements document.  This is because they aren't required
in and of themselves, but turn out to be necessary to meet other
requirements.
.hl 1 Reliability

  Because the first product using dynamic libraries to be seen by
customers, Datatrieve-20, is aimed at inexperienced users, it is
especially important that dynamic libraries not introduce any
mysterious (from the users' points of view) errors.  Ideally, no
errors should occur.  Next best is for errors to explain themselves
clearly.

  DYNLIB use rule: all programs which call dynamic libraries should
check for errors after each call, and present them to the user in a
manner compatible with the other user interactions made by the
program.
.hl 1 Maintainability

  DYNLIB and its support procedures will be written in MACRO.  I view
this as an unfortunate choice, but since DYNLIB is intended to become
a bundled part of the TOPS-20 operating system eventually, it should
be written in a language which purchasers of TOPS-20 sources can
understand.   The tools for building libraries must be in macro
anyway, since they must be usable at all customer sites.

  Most of the actual DYNLIB code will live in the RTL, with only a
small bootstrap routine to load the RTL on the first call to a dynamic
library.

  DYNLIB will be autopatchable in the field. (What will it be
autopatched as part of?  At first?  Later?)
.hl 1 Maintenance

  Maintenance of this product will be performed by Software
Engineering.

  Updates will appear as necessary on the autopatch tapes.
.hl 1 Compatibility

.HL 2 Compatibility with existing libraries

  An existing library that will run in an arbitrary non-zero section,
using no traps or interrupts, can be made a dynamic library simply by
writing a library definition and an appropriate master initialization
routine. 

  A library using traps and interrupts would be somewhat more
difficult.  The degree of dificulty would depend on how the traps and
interrupts were used.  It could still be quite simple, on the order of
a day's work by somebody who already understood dynamic libraries.

.hl 2 Product Compatibility

.hl 3 Dependency issues

  We must come to a consensus with the TOPS-20 monitor group on
interpretation of PDV's.

  We must come to a consensus with the LINK and monitor groups on
LINK-provided memory maps.

.hl 2 Standards Conformance

.hl 2 Internationalization
 
  No requirements in this area.
.hl 1 Evolvability

  A Monitor DYNLIB facility could be written which would replace
DYNBOO.  This would, I hope, be relatively simple.  All the rest of
DYNLIB version would would be preserved, and performance would improve
somewhat.
.hl 1 Costs

  DYNLIB is being developed as part of the Datatrieve-20 project.
  We hope to limit the development of DYNLIB to 4 man-months
(including all time spent from writing specification to field-test
entry).
.hl 1 Timeliness

  The product must be ready to field-test and ship along with
Datatrieve-20.
.hl 1 Constraints and Trades-off

  Ease of conversion of an existing library is more important than
keeping the call overhead of that library within the bounds specified.
However, new libraries implemented according to the instructions to be
developed as part of DYNLIB must meet the call overhead limits.  There
may be different techniques for defining a new dynamic library and a
dynamic interface to an existing library.
.hl 1 Approval process

   DYNLIB is being developed within the Datatrieve-20 project, but
will probably be used by many other projects.  The normal approval
process as applied to Datatrieve-20 probably will not give sufficient
visibility to DYNLIB to ensure that necessary feedback from other
groups is received.

  Special efforts will be made to circulate DYNLIB documents to
project leaders and supervisors throughout LSG Software Engineering.
Selected consultant-level people within the group will be approached
individually for their comments.