THE SEGMENTER [ MPE Segmenter Reference Manual ] MPE/iX 5.0 Documentation
MPE Segmenter Reference Manual
THE SEGMENTER
The Segmenter is a subsystem of the MPE operating system. It performs
all intermediate functions between source code compilation and program
execution. One of its primary responsibilities is to gather and link
into pieces, or segments, most of the resources needed to form an
executable program file. The Segmenter gives programmers considerable
control over the arrangement of code within segments, which in turn
affects the efficiency of individual programs and the economical use of
system resources in general.
The Segmenter In Context: The Program Development Process
To get a clear idea of what the Segmenter is and how it works, it helps
to have in mind the process of program creation. Figure 1-1 provides an
overview of the entire process.
An analogy will help to summarize the process and to highlight some
particularly important points.
Think of the various elements and events of the program development
process, taken together, as forming a multi-floor condominium, with the
elements corresponding as follows:
* Relocatable Binary Modules (RBMs): rooms.
* Entry points: doors.
* Segments: floors (groups of rooms).
* Procedure libraries: files of pre-designed common areas, such as
hallways, bathrooms, kitchens.
Figure 1-1. Program Development Overview
* User Subprogram Library (USL): preliminary plans.
* Program file: final plans.
The program development process is analogous to the architectural process
of designing the condominium. The architect takes her ideas and
translates them into a preliminary plan. This floorplan may contain one
or more rooms per floor, and each room may have one or more doors.
Since these are preliminary plans, the architect can rearrange rooms and
even move rooms to different floors. She can also go to her portfolios
for copies of already-created rooms or groups of rooms to incorporate
into one of her floors.
When the architect is finally satisfied with the design, she prepares the
final plan, inking in the lines and in effect locking the doors, rooms,
and floors into a permanent arrangement.
Since a copy of the preliminary plans still exists, the architect can get
them out and go through the process as often as she wishes to create
other, slightly different final plans to be followed during actual
construction (program loading and execution).
In the following explanation, the boxed portions of the accompanying
diagrams indicate which parts of the process are active for that step.
COMPILATION. The first step, illustrated in Figure 1-2, is to translate
the source program units (sometimes called procedures, functions, or
subroutines) into blocks of machine instructions called "relocatable
binary modules", or RBMs. This is done by the various MPE language
compilers, which automatically store the RBMs in a specially-formatted
file called the user subprogram library, or USL.
Figure 1-2. Compilation
Relocatable Binary Modules. An RBM is the smallest unit of object code
generated by a compiler. RBMs for the various subprograms contain
program instructions and external references (references to procedures in
other RBMs or in library files). In addition to these subprogram RBMs,
the compiler constructs a main, or outer block, RBM, which contains
instructions for the main program as well as program constants. The main
RBM may also contain fixed addresses for locating items in the data
stack; this information will be used later in the program development
process.
The different compilers have their own specific conventions for
constructing program units into RBMs. See Appendices A through F for a
discussion of these.
Some programming languages (FORTRAN and SPL) allow you to specify
parameters within RBMs as "entry points". These are points within the
code unit which you can selectively instruct the system to use as
starting locations for a particular action.
When the compiler places the RBMs in the USL file, it "associates" them
with particular code segments. Actual code segments do not yet exist,
but you can think of the RBMs as "belonging" to their associated
segments.
The RBMs are relocatable, which means that using the Segmenter you can
move RBMs around and associate them with different code segments. You
can also copy RBMs from other USLs, add new RBMs to a USL, or purge RBMs.
An analogy will help clarify some of the important characteristics of
RBMs.
Suppose you are designing posters for a presentation. Each poster will
contain one or more pictures or diagrams. You lay the pictures out on
the poster board but leave them unglued, so you can rearrange them on the
boards or move them from board to board as often as you wish. Once they
are glued down, however, their positions are fixed, and they can no
longer be moved around.
Think of RBMs as the diagrams and the code segment names as the poster
board. While in the USL, the RBMs can be rearranged and associated with
one code segment name (board) or another. At preparation time, the
Segmenter looks at the current arrangement and applies the "glue" to form
the final poster, or code segment, which is output to the program file.
However, unlike the pictures which were glued to the poster board, the
pieces of code used to form the code segments still exist in the USL,
waiting to be further manipulated or changed in another cycle of segment
design. The picture, or code, glued into the code segment was just a
copy of the code modules found in the USL.
User Subprogram Libraries (USLs). Users often think of code as residing
only in program files, but in Hewlett-Packard's design for code-handling,
code can also be stored, maintained, and managed in three different kinds
of specially formatted files called "libraries." The user subprogram
library, or USL, is the first of the procedure libraries used in the
program development process. It is the file used for compiler output and
forms the basis for the other two libraries ("Relocatable Libraries," or
RLs; and "Segmented Libraries," or SLs). The USL is the file you can
manipulate to achieve effective segmentation.
In addition to an RBM for the main program and each subprogram
successfully compiled, the compiler generates and places the following
into the USL:
* A directory to keep track of the RBMs stored in the USL.
* Data stack information that will be required at a later stage.
A major advantage of this library is that once code is compiled into the
USL, the programmer can manipulate it and even copy it into another USL
without having to perform time-consuming recompilation.
Users can also compile several versions of a procedure into a USL, using
the Segmenter's indexing capability to select at execution time the
version they wish to use. Although USLs are usually created by the
compiler, the programmer can create them, using commands within the
Segmenter subsystem. Segmenter commands also allow users to list the
contents of the USL they are currently working with.
PREPARATION. The second step in the program development process is to
"prepare" the USL. This step, which is illustrated in Figure 1-3, is
performed by the MPE Segmenter subsystem, and results in a "program file"
containing:
* Loadable code segments.
* A skeleton data segment, or "stack".
The Segmenter may bring in procedures from a "relocatable library" (RL)
to resolve external references made within the RBMs, such as a call to a
procedure which finds the cosine of a number generated within the
program.
Figure 1-3. Preparation
Code Segments. During preparation, the Segmenter uses the associations
found in the USL to bind the RBMs into one or more code segments. It is
important to realize that no segments actually existed in the USL. By
associating RBMs with segments, the compiler was, in effect, looking
forward to segments which would eventually be created. That creation is
the sole responsibility of the Segmenter.
As it establishes the necessary linkages between RBMs, the Segmenter
creates an "external reference list", which contains information about
those RBMs not present in the program file, but which are referred to
within it.
The Segmenter also generates a Segment Transfer Table (STT) for each code
segment it creates. This table contains linkage information, used during
execution when control has to transfer from one RBM within the segment to
another. If control has to transfer to an RBM in another segment, the
STT will keep track of that linkage as well.
Code segments may contain only non-modifiable material; that is, material
not subject to change during execution. Therefore, code segments may
contain program instructions, but they may not contain data. The
only exception to this rule is that program constants (which are
non-modifiable data) may be contained in code segments.
Although you cannot change the code segments themselves, you can
manipulate the original copy of the code, which resides in the USL, and
re-prepare it into a variation of your first code segment.
In summary, each code segment contains the following:
* The instructions of the program itself.
* Program constants.
* Addresses for locating items in the data stack.
* An external reference list.
* An STT for keeping track of intra-segment and inter-segment
transfers.
The Skeleton Data Segment, or Stack. The Segmenter is also responsible
for creating a skeleton data segment (or stack), based on references in
the code, and placing it in the program file. Each program file will
have only one data segment.
To construct the data segment, the Segmenter uses the initial stack
information compiled into the USL. That information defines and
initializes storage space for data that is considered global (available
to all program units directly). This area, usually referred to as the
Primary DB, contains information about and pointers into the other parts
of the data segment. A secondary storage area accessible to all program
units indirectly through local or global pointers is defined as well, and
parts of it may also be initialized. The secondary storage area is
called the Secondary DB.
Relocatable Libraries. The relocatable library, or RL, is the second of
the three libraries which may be accessed during the program development
process. RLs contain procedures, in RBM form, needed for program
execution. They can be created by the programmer, using Segmenter
commands, from the material in a USL. Programmers can also use Segmenter
commands to add RBMs from a USL to an already-built RL, to purge RBMs
within RLs, and to list the contents of the currently-managed RL.
When a program makes a call to some or all of the RBMs kept in an RL
file, the Segmenter copies the RBMs at preparation time and binds them to
the calling program as a single segment, known as the "RL segment."
Different programs will likely ask for different RBMs or combinations of
RBMs and will need to use them in unique ways, so the RL segment must be
unique to each program.
No segmentation information accompanies the code in RL RBMs, as it does
those in a USL. Since all required RBMs are added to the calling program
file as a single segment, individual segment associations for each RBM
are unnecessary. The Segmenter binds the single RL segment to the code
segment it is constructing from USL material.
Since a copy of requested RL material is prepared into the program file,
your program file will have to be re-prepared should the RL code change.
In fact, all program files prepared with that code will have to be
re-prepared.
RLs are used to keep procedures that are likely to be used with some
frequency by more than one programmer. Keeping such common procedures in
an RL means that programmers can access them more efficiently: they can
use a call to the procedure and receive a copy of it for their program
file. They do not have to rewrite it each time it is needed in a new
program.
Different programming languages have different rules for the specific
kinds of code that may be placed in an RL; these are discussed in the
reference manual for each language. All languages allow you to place
either global or non-global procedures in an RL. Global procedures
reference the global storage area of a program's data stack, so that the
system will have instructions on how to handle the RL code that are
appropriate to each particular file in which it is used. Non-global
(also called local or dynamic) procedures are more general and can be
prepped and run without any knowledge of the program's data stack.
EXECUTION. In the third and final step, illustrated in Figure 1-4, the
MPE Loader allocates entries in the HP 3000 Code Segment Table (CST) for
each of the program file's SL code segments and in the code segment table
extension for each of its other code segments. It also allocates an
entry in the HP 3000 Data Segment Table for the process's data stack.
These two tables keep track of all the segments needed for your program's
execution, as well as for the execution of all other programs ready to
run at that time. The Loader also searches segmented libraries to
resolve any external references remaining in the program file.
Figure 1-4. Execution
Segmented Libraries. The Segmented Library, or SL, is the third of the
three libraries which may be accessed during the program development
process. An already-existing system SL contains procedures applicable to
all HP 3000 systems, such as the procedure for program termination.
Segmenter subsystem commands also allow the programmer to create SLs from
the material in one or more USLs, to add segments to an already-built
SL, to purge segments within SLs, to list the contents of the
currently-managed SL, and to copy the contents of one SL into another SL.
SLs and RLs share three important characteristics. Both:
* Contain procedures needed for program execution.
* Are created by the programmer, using Segmenter commands, from USL
material.
* Are used to permit programs to share procedures.
However, the two libraries are intended for different purposes, so there
are important differences in how and when they are constructed and used.
First, as its name indicates, the segmented library contains procedures
in segmented form, not in RBM form as in the RL. When you use the
segmenter to build an SL file, it uses the USL's segment association
information to bind the required RBMs into code segments as it places
them into the file. Procedures thus exist in the SL as runnable code
segments.
SLs are intended for the storage of procedures with wider applicability
than those placed in RLs. Examples are general utility procedures such
as FOPEN, which are used in exactly the same way by every calling
program. Because of this generality, the Segmenter does not have to
allow for the unique combinations and uses of procedures that occur when
a program calls for procedures from an RL. Instead, it can prepare, or
segment, such general procedures at the moment you specify that you want
them placed in an SL. Since the segmentation is not altered when
different programs reference procedures in an SL, these segments may be
shared concurrently by many programs.
While RLs contain code that can be copied and bound to each calling
program file, SLs contain code that can be shared; that is, every program
references the original version of the code. SL code is not copied or in
any way combined with the program file. When a program calls an SL
procedure, the procedure is read into memory from its place in disc
storage. This method makes economical use of system resources, since
each SL procedure exists only once in main memory and does not need to be
brought in as part of every program file that requires it.
As is true of RLs, the various programming languages have different rules
for what kinds of code may go into an SL. The general requirement,
however, is that SLs can only contain non-global procedures. These are
procedures that make no references to the global storage area of the data
stack on which they will run: all parameters must be passed in
explicitly. SL procedures may not read information about the stack's
global storage area. Sharability is the primary feature of SL
procedures. If they required knowledge of global storage, they wouldn't
be sharable, since each program's global storage area is different.
While the Segmenter links RLs to the program file at preparation time,
SLs don't enter the program development process until run time. They are
used for the final resolution of external references, and their linkage
to the program file is handled by the Loader, rather than the Segmenter.
The Segmenter reserves space for called SL procedures in the Segment
Transfer Table (STT) at preparation time, but the entries are actually
made by the Loader when it searches the SL library files at run time.
You may build multiple SLs at each of three levels:
SL.group.acct: The Group Library SL. It is the library of the group
under which the program file is stored and is readable
by any user who can access the group.
SL.PUB.acct: The account's Public Library SL. It is the library of
the public group of the account under which the program
file is stored. It is readable by any user who can
access the account.
SL.PUB.SYS: The System Library SL. It is the library of the public
group of the System account. It can be accessed by all
users of the system.
If your program file is a permanent file, then then group and account
refer to the group and account where the program file resides, which may
or may not be the same as your log-on group and account. However, if
your program file is not a permanent file but is a job/session temporary
or passed file, then group and account refer to your log-on group and
account. The LOADPROC intrinsic, which you may use at times to
dynamically load and unload SL procedures while your program is running,
searches the SL libraries according to the user's log-on group and
account, or the group and account where the program resides, as specified
by the 'LIB' parameter. See the discussion of the LOADPROC intrinsic in
the MPE V Intrinsics Reference Manual (32033-90007) for more information.
The search order and the number of libraries searched depend on the the
;LIB parameter specified as part of either the :RUN or the :PREPRUN
commands. The table below illustrates this relationship.
PARAMETER SEARCH ORDER
---------------------------------------------------------------------------------------
;LIB=G SL.group.acct
SL.PUB.acct
SL.PUB.SYS
;LIB=P SL.PUB.acct
SL.PUB.SYS
;LIB=S SL.PUB.SYS
(or no LIB parameter)
While you can search only one RL during any one program preparation
process, you can search one SL at each of the levels (group, account, and
system) during any one execution process.
The Code Segment Table (CST) and the Data Segment Table (DST) keep track
of the loading and unloading of the necessary segments as program
execution proceeds. Although their operation is completely invisible to
users, some explanation of what they are and how they work will help
complete your picture of the Segmenter.
The Code Segment Table. The CST is a main memory-resident table which is
maintained by the MPE operating system. It contains a list of code
segments that are being referenced by executing programs and keeps track
of whether these segments are present in main memory or are out on disc.
Entries in the CST are dynamically allocated by the operating system as
programs are loaded and unloaded.
Although it is often referred to as a single table, the CST is actually
divided, logically and physically, into two portions:
* The CST contains entries for coded segments in segmented libraries
(including the system SL, which contains large chunks of the MPE
operating system). Some entries or parts of entries in the CST also
contain various service procedures for internal interrupts, external
interrupts, system intrinsics, and library procedures.
* The CST Extension (CSTX) contains blocks of code segment entries, one
block for each loaded program. Note that "loaded" as used here does
not necessarily mean "loaded into main memory." Rather, it means that
since the segment is part of an executing program, information about
it has been loaded, or entered, into the CSTX. The segment itself may
still be waiting out on disc.
The CST contains space for 2048 entries. The number of blocks of entries
in the CSTX is configurable and can be set at system configuration time,
but any one block has space for no more than 255 code segment entries.
Thus, a program may contain as many as 255 code segments. One larger
than that would not be runnable, since there would not be enough room in
the CSTX to enter all the information the system needs in order to find
and manage all the segments needed for execution.
Each segment required for the program receives a unique identifying
number (the code segment number), and a CST entry which consists of a
single 4-word descriptor providing the following information:
* Control information (such as whether the segment is present in main
memory or is out on disc).
* The segment's length.
* The segment's disc (or starting) address if it is not present in main
memory.
When the system needs to read the code segment into main memory, it uses
this information to determine where to start reading and how much to
read.
Since SLs are sharable, two different programs running at the same time
may be using one particular SL code segment. If a CST entry has already
been made for a segment, a new entry is not made. Instead, the existing
entry is used.
The Data Segment Table. Like the Code Segment Table, the Data Segment
Table is a main-memory resident table which is maintained by the MPE
operating system. It contains a list of data segments currently in use
by the operating system and user programs. Each segment receives a
four-word entry recording its length, location, presence or absence in
main memory, and other characteristics.
The length of the table is determined at system generation time. Entries
in the DST are dynamically allocated by the system as programs are
initiated or terminated, or special capability processes request or
release additional data segments.
Summary: The Program Development Process
Events which occur both before and after the Segmenter's part in program
development affect the final segmentation of your program. To ensure
good results, you need to keep the Segmenter's purpose and operation in
mind as you begin developing your programs, even if you are not yet
planning to control the process explicitly. For instance, what you
compile into your USL will determine what is available to be placed into
an SL, which in turn will affect what the loader will need to do at :RUN
time to run your program, and how efficiently it will do so.
MPE/iX 5.0 Documentation