@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             SYS143
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS143
~S1~M~OSYS IMPLEMENTATION DESCRIPTION~
~
~M~OSection 14  Version 3~
~S1~OSection 14.3 Virtual Store Manager (Paged and Segmented Version)~
~S1~O1. General Description~
~BThis module is responsible for managing the virtual stores of
processes. In addition to providing the organisational commands which
allow users to manipulate their virtual stores, this module arranges
for mapping the virtual store on to the real store, transferring
blocks from the drum as required, and performing store rejection
when insufficient free space is available in core.
~BThis particular version of the virtual store manager is intended
for machines which support a paged and segmented virtual store,
where the virtual addresses are translated via segment tables
pointing to page tables.
~S1~O2. Interfaces
Other modules used~
   Section  1 (Coordinator)~
   Section  2 (Core Manager)~
   Section  3 (Drum Manager)~
   Section 10 (Virtual Machine Interrupts)~
   Section 13 (Process Manager)~
   Section 16 (File Manager)~
   Section 21 (Performance Monitoring)~
Hardware registers used~
   V.NEQ.ACCESS~
   V.VAL.ACCESS~
   V.NEQ.SEG~
   V.NEQ.BLK~
   V.RESET.SEG~
   V.RESET.BLK~
   V.RESET.STATUS~
Interrupt level interface procedures~
   GET.BLOCK (SEG, BLOCK) CORE ADDR~
   REL.BLOCK (CORE ADDR)~
   UPDATE.BLOCK (CORE ADDR)~
   STORE.REJECTION ()~
   MAP.ADDRESS (CORE ADDR, PREF SEG) ACCESSIBLE VECTOR~
   DISC.STATUS (DISC NO, STATUS)~
Organisational command procedures~
   CREATE.SEGMENT (SEG NO, SIZE)~
   RELEASE.SEGMENT (SEG NO)~
   CHANGE.SIZE (SEG NO, NEW SIZE)~
   CHANGE.ACCESS (SEG NO, REQD ACCESS)~
   INTERCHANGE (SEG1, SEG2)~
   READ.SEGMENT.STATUS (SEG NO)~
   CREATE.X.SEGMENT (SEG NO, SIZE)~
   MAP (SEG NO, ACCESSIBLE SEG, COUNT)~
   COPY.BLOCK (SEG1, BLK1, SEG2, BLK2)~
   SECURE.SEGMENT (SEG NO)~
Command level interface procedures~
   ASSIGN.USER.SEGMENT (SSN, SEG NO, REQD ACCESS)~
   ASSIGN.SYS.SEGMENT (SEG NO) SSN~
   CMD.MAP(SEG.NO,ACCESSIBLE.SEG,COUNT)~
   INIT.SEGS (SPN, STORE LIMIT)~
   TINI.SEGS (SPN)~
   READ.SYS.SEGMENT.STATUS (SEG)~
   PROTECT (SSN, VALUE)~
   RESERVE.SEG(FILE.ADDRESS,FILE.SIZE,FILE.STATUS)~
Data types~
   SEG.VARS~
Configuration parameters~
   SEG.SIZE~
   SEG.SHIFT~
   X.SEG.SIZE~
   PAGE.SIZE~
   PAGE.SHIFT~
   FREE.LIMIT~
   NO.OF.PAGES~
   NO.OF.LOCAL.SEGS~
   NO.OF.COMMON.SEGS~
   NO.OF.MAPPED.SEGS~
   NO.OF.SYS.SEGS~
   NO.OF.X.SEGS~
   NO.OF.INITIAL SEGS~
   FIRST.COMMON.SEG~
   FIRST.X.SEG~
   PT.SEG~
   REAL.STORE.ADDRESS~
   RESERVED.BLOCK~
~S1~O2.1 Hardware Interface
~BThe users' virtual store is divided into a number of segments, each of
up to a maximum size SEG.SIZE. Some of the segments are private
to the process and cannot be accessed by any other process, others are
common to all the processes and contains all the systems software; generally
processes are prevented from modifying the information in these segments. All
the segments are paged, each of size PAGE.SIZE. Thus a virtual address has the f
orm:
~3
~
~Q5
~
~M~O                     ~O~
~N~O| SEG | PAGE | BYTE |~O~
~0
~BEach virtual store is described
by two segment tables, the local segment table, LST and the common segment table
,
CST.
The LST which exists in each process' register block, and is
indexed by segment number, contains a list of all the private segments
of the process. For each segment, this table holds access control information
together with a global system identifier for the segment - the system segment
number (SSN).
~BThe CST, also indexed by segment number, contains similar information
as the LST for the common segments. Since the system segments are shared by all
the processes in the system, only one CST is provided.
Together, the LST and the CST define the total number of segments available
to a process.
~BIn addition to the LST and CST, the ideal machine maintains two tables,
the system segment table, SST, and the SST.PT, for holding global information
on all the segments which are known within the system.
~BThe SST, which is indexed by SSN, holds information
for the segment, such as the segment size, which
does not change frequently.
This table also has space available for fields which are of relevance to the sof
tware.
~3
~Q 25
~
~
~
~O    LST     ~O    ~O    SST    ~O    ~O      SST.PT     ~O    ~O      PT
~O~
|          |    |         |    |               |    |            |~
|          |    |         |    |               |    |            |~
~O|          |~O    ~O|         |~O    ~O|               |~O    ~O|            |
~O~
~O|ACCESS|SSN|~O    ~O|DRUM ADDR|~O    ~O|VALID |STATUS  |~O    ~O|VALID|STATUS|
~O~
|          |    |software |    ~O|  PAGE TABLE   |~O    ~O|PAGE ADDRESS|~O~
|          |    ~O|use      |~O    ~O|ADDRESS ALTERED|~O    ~O|ALTERED     |~O~
|          |    |         |    |               |    |            |~
|          |    |         |    |               |    |            |~
~O|          |~O    |         |    |               |    ~O|            |~O~
                |         |    |               |~
                |         |    |               |~
                |         |    |               |~
~O    CST     ~O    ~O|         |~O    ~O|               |~O~
|          |~
|          |~
~O|          |~O~
~O|ACCESS|SSN|~O~
|          |~
|          |~
|          |~
|          |~
~O|          |~O~
~0
~BThe SST.PT, also indexed by SSN, holds all the information about
the segment which changes frequently.
Each entry describes the location and status of the page table and it is defined

to be of identical format to the page table entries.
Each page table occupies a page, this
enables the paging mechanism to treat page tables in a similar way to pages.
~BThe page number of the virtual address is used to index into the page table
for the segment. Each entry holds the address and status of the page/page
table. A page is allowed the following status:~
~
~Mnot allocated~
~Nin core~
~Non drum~
~Nlockout~
~
Additional fields indicating whether the page/page table is valid or
whether it has been written to are also maintained in each page table entry.
~BIf a process attempts to access a segment
for which the paging mechanism cannot translate the address, a process based, vi
rtual
store interrupt occurs, and the registers V.NEQ.SEG,
V.NEQ.BLK and V.NEQ.ACCESS are set to the segment number, block number and
type of access attempted. If the attempted access
contravened the permission bits held in:~
~3
~
   WITH DIVARRAY [INDEX] DO~
      BEGIN~
     n V.NEQ.ACCESS.~
~0
~BIn cases when an address translation buffer is provided for optimising
address translation, the ideal machine allows the buffer to be cleared
completely or selectively using the block number and/or segment number.
The required virtual address is loaded into the registers V.RESET.BLK and
V.RESET.SEG respectively and the clear operation is triggered by writing to
the register V.RESET.STATUS. This has the following format:
~3
~
~Q 15
~
          ~O                              ~O~
          ~O|                      | | | |~O~
                                  | | |~
                                  | | |~
                                  | | |--RESET ALL~
                                  | |~
                                  | |----RESET ON SEG~
                                  |~
                                  |------RESET ON SEG/BLK~
~0
~
Each time after page rejection for example, the buffer must be cleared
completely. This ensures that the buffer entries are pointing correctly to
core pages.
~BThe address translation unit also has associated
with it a machine instruction known as VALIDATE.
When this order is used, the access permission
associated with the virtual address of the operand
is returned in V.VAL.ACCESS. This register is
accessible from within user programs, and is one
of the process specific registers dumped in the PRB
of the current process on entering interrupt level.
This VALIDATE order forces the paging mechanism to access the appropriate
page table looking for a specific entry. If it cannot
translate the virtual address, a validate fail interrupt occurs and the
operand address is deposited in V.NEQ.SEG and
V.NEQ.BLK. The operating system is then able
to compute the permitted access from its tables,
and deposit it explicitly in the copy of V.VAL.ACCESS
in the PRB.~
~S1~O2.2 Software Interface~
~
~
~
1) GET.BLOCK (SEG, BLOCK) CORE.ADDR~
~BThis procedure arranges for the specified
virtual address to be locked into core. If it
is not already in core, it will be transferred in.
The core address, returned as the result of the
procedure, is that of the specified block.
~
~
~
2) REL.BLOCK (CORE.ADDR)~
~BThis procedure removes the locked in status
for the specified page, thus making
it eligible for rejection.~
~
~
~
3) UPDATE.BLOCK (CORE.ADDR)~
~BThis procedure updates the usage information for the specified page in core,
so that any backing store copy will be updated (at some time in the future).~
~
~
~
4) STORE.REJECTION ()~
~BThis procedure is called whenever insufficient core space is available.
The page rejection process is started by this procedure and
the current process is halted until free space become available.~
~
~
~
5) MAP.ADDRESS (CORE.ADDR, PREF.SEG) BYTE VECTOR~
~BThis function is the means by which interrupt
level software may obtain an accessible address
for accessing a specified real core address. A
vector of LOGICAL8 is returned as the result. In this implementation the
prefered segment parameter is ignored.~

~
~
~
6) DISC.STATUS (DISC.NO, STATUS)~
~BThis is called by the drum manager to indicate a change in status
of disc DISC.NO. STATUS is zero if the disc is going offline and
one if it is coming online.~
~
~
~
7) ASSIGN.USER.SEGMENT (SSN, SEG.NO, REQ.ACCESS)~
~BSegments may exist outside of the virtual
store of processes, for example, as messages passing
between processes. In this state, the segment
only has a system segment number to identify
it. This procedure allows a system segment (SSN)
to be assigned to a specified segment within the
current process. The access permission given by
REQ.ACCESS is associated with the segment in
the process' virtual store. If the user segment number
is negative a suitable segment number will be chosen.
The segment number actually used is returned in PW1.~
~
~
~
8) ASSIGN.SYS.SEGMENT (SEG.NO) SSN~
~BThis procedure removes the specified segment
from the virtual store of the current process, and
returns the system segment number (SSN) for
subsequent identification of the segment.~
~
~
~
9) CMD.MAP(SEG.NO,ACCESSIBLE.SEG)~
~BThis procedure is called to ensure that the specified segment number
is accessible at command level. In this implementation, the ACCESSIBLE.SEG
parameter is ignored. The procedure sets PW6 to the segment number
to be used for addressing the segment.~
~
~
~
10) INIT.SEGS (SPN, STORE.LIMIT)~
~BThis procedure is called by the process manager
to initialise the virtual store variables in the register
block of the specified process.~
~
~
~
11) TINI.SEGS (SPN)~
~BThis procedure is called by the process manager
to relinquish all store resources held by the
specified process, releasing all segments still
existing in that process' virtual store.~
~
~
~
12) READ.SYS.SEGMENT.STATUS(SEG)~
~BThis procedure is called to find the system information about
a segment. It returns the maximum size of the segment in PW1,
its status (X.seg or not) in PW2, its SSN in PW3, current size
in PW4 and disc address in PWW1.~
~
~
~
13) PROTECT(SSN,VALUE)~
~BThis procedure is called by the file manager to mark a file
segment as in a protected state, so that the drum space occupied
by it is not released when the segment is released. The value
parameter indicates the status of the segment, if non zero the
segment is protected, if zero, the segment is unprotected and
the disc space will be recovered when the segment is released.~
~
~
~
14) RESERVE.SEG(FILE.ADDRESS,FILE.SIZE,FILE.STATUS)~
~BThis procedure is called by the file manager to reserve space
on the backing store for a file. Parameters P1 and P2 specify
the disc address and size of the file. P3 indicates if the file
is a segment or an X.segment.~
~
~
~
15) SEG.VARS.TYPE~
~BThis data type is exported to the process
manager, for the definition of the store management
variables within the process register block.~
~
~
~
16) SEG.SIZE~
~BThe maximum size in bytes of an accessible
segment.~
~
~
~
17) SEG.SHIFT~
~BLog base 2 of SEG.SIZE.~
~
~
~
18) X.SEG.SIZE~
~BThe maximum size of an X.segment in blocks.~
~
~
~
19) PAGE.SIZE~
~BThe standard unit of store within the system.
This is the minimum size of a transfers to/from the
drum, and the basic unit of which core and drum
space is allocated.~
~
~
~
20) PAGE.SHIFT~
~BLog base 2 of PAGE.SIZE.~
~
~
~
21) FREE.LIMIT~
~BThe number of pages freed by the page rejection process. Rejection
ceases when a total of FREE.LIMIT pages are available.
~
~
~
~
22) NO.OF.PAGES~
~BThe size of the core store in PAGE.SIZE units.~
~
~
~
23) NO.OF.LOCAL.SEGS~
~BThe number of segments which each process can own
privately.~
~
~
~
24) NO.OF.MAPPED.SEGS~
~BThe number of directly addressible segments.
~
~
~
~
25) NO.OF.COMMON.SEGS~
~BThe number of segments common to all processes.~
~
~
~
26) NO.OF.SYS.SEGS~
~BThe maximum number of segments which may
exist in the system at any one time.~
~
~
~
27) NO.OF.X.SEGS~
~BThe number of X.segments available to each process.~
~
~
~
28) NO.OF.INITIAL.SEGS~
~BThe number of system segments preassigned.~
~
~
~
29) FIRST.COMMON.SEG~
~BThe segment number of the first common segment.~
~
~
~
30) FIRST.X.SEG~
~BThe segment number used to reference the first X.segment
available to a process.~
~
~
~
31) PT.SEG~
~BThe segment number to be used for addressing the page tables.~
~S1~O3. Implementation~
~S1~O3.1 Outline of Operation~
~BOne of the function of this module is to provide a process to manage the
store rejection process. This process is normally triggered by the core manager
calling the interface procedure CORE.REJECTION. This procedure halts the current
 process
and starts the rejection process. Rejection then continues until a sufficient
number of pages have been freed.
~BThe rejection algorithm relies upon maintaining a usage count for each page of
 core.
Pages are selected for rejection by a cyclic scan of all core pages.
During the scan, the usage count is decremented. If it falls to a certain
threshold the page is regarded as a suitable candidate for rejection and it
is no longer marked as valid. If on a subsequent scan the usage count is found
to be zero the page is rejected. The usage count is reset to its maximum
value when a virtual store interrupt occurs on a page which is still in core.
The page is marked as valid at this point.~
~BIn addition to the local segments and common segments
supported by the ideal hardware, the system also provides a number
of X.segments for each process. An X.segment is a potentially large,
disc resident segment whose size is not dependent on the segment
size of the host machine. X.segments may not be addressed directly,
but should be used in conjunction with the COPY.BLOCK organisational
command to extract blocks of the X.segment and make them available
in part of the users addressable space.
~S1~O3.2 Data Structures~
~T# 20
~
~
BSA~IA vector indexed by page number holding the drum key (backing store address
)
of the page.~
HFP~IA vector with one entry per activity holding the page number for which the
process is waiting. If the process is not waiting for a page transfer
the entry is cleared.~
CMT~Ia table of CMT.TYPE and indexed by page number, holding the information nee
ded
to remove the page to backing store.~
CMT.TYPE~IInformation required to completely describe a core page.~
   :SSN~IThe system segment number of the segment.~
   :BLOCK~IAn indication of which block of the segment is held in the core page.
~
SEG.VARS~IThe data structure within the process register block, defining the sto
re management
variables of each process.~
   :LST~IInformation about each of the segment known to the process. Defined to
be of
type LST.TYPE.~
   :XST~IInformation about each X.segment known to the process.
Defined to be of type LST.TYPE.~
LST.TYPE~IAll the information required to define the state of a segment.~
   :ACCESS~IThe access permission allowed to the pages of the segment. In additi
on to
the permission bits, ACCESS also has a bit indicating if the user is allowed
to alter the access permission.~
   :SSN~IThe system segment number of the segment.~
CST~IA table similar to the LST, but holding the details about each of the commo
n
segments.~
SST~IA table of type SST.TYPE, holding information about each of the system segm
ents.
It is indexed by SSN.~
SST.TYPE~IInformatin required to define the state of a system segment.~
   :LIMIT~IThe size of the segment (in pages).~
   :DRUM.KEY~IThe backing store address to which the page table is to be rejecte
d.~
   :STATUS~IAdditional information about a segment indicating whether
it is a file or X.segment.~
   :SST.LINK~IA linked list of free SST entries (see FREE.SST).~
SST.PT~IA table indexed by SSN, holding all the information required
to define the state of the page tables of the system segments.~
   :VALID~IA bit indicating whether the page table is valid.~
   :STATUS~IIndicate whether the page table is in core, on the drum, not allocat
ed
or locked out.~
   :ALTERED~IA bit indicating whether the page table has been altered - i.e. whe
ther
there is an up to date copy on the backing store.
This may be set by both hardware and software.~
   :PAGE.ADDRESS~IThe address of the page table. If STATUS indicates
that the page table is on the drum, this field holds the backing store address
otherwise it holds the core address of the page table.~
IN.USE~IA bit map indexed by page number indicating which core pages are in use.
~
USAGE.COUNT~IA count monitoring the usage of a page.~
FREE.SST~IHead of the list of free SST entries.
~
~V1 0
~S1~O3.3 Special Notes~
~BThe page size is assume to be the same as the block size on the drum.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                SYS143
~V9 -1
~F
@TITLE SYS14(3,11)
@COL 1S-2R-3R-4R-5R-6F

@FLOW 1-2-3-4-5-6

@BOX 1.0
VIRTUAL STORE MANAGER
@BOX 4.0
PROCEDURES IN MODULE:
   INT1  VIRTUAL STORE INTERRUPT
   INT2  VALIDATE FAIL INTERRUPT
   INT3  GET BLOCK
   INT4  REL BLOCK
   INT5  UPDATE BLOCK
   INT6  STORE REJECTION
   INT7  RELEASE PAGES
   INT8  RESET PAGING REGISTERS
   INT9  MAP ADDRESS
   INT10 COPY
   INT11 CORE REJECT
   INT12 SECURE PAGES
   INT13 CHECK LOCKOUT
   INT14 GET SYS BLOCK
   INT15 DISC STATUS
   INT16 GET PT
   INT17 WRITE PAGE TO DRUM
   CMD1  CREATE SEGMENT
   CMD2  RELEASE SEGMENT
   CMD3  CHANGE SIZE
   CMD4  CHANGE ACCESS
   CMD5  INTERCHANGE
   CMD6  READ SEGMENT STATUS
   CMD7  CREATE  SEGMENT
   CMD8  ASSIGN USER SEGMENT
   CMD9  ASSIGN SYS SEGMENT
   CMD90 RELEASE SYS SEGMENT
   CMD11 INIT SEGS
   CMD12 TINI SEGS
   CMD12 ALLOCATE SYS SEG
   CMD14 MAP
   CMD15 COPY BLOCK
   CMD16 SECURE SEGMENT
   CMD17 CMD MAP
   CMD18 PROTECT
   CMD19 READ SYS SEGMENT STATUS
   CMD20 RESERVE SEG
@BOX 6.0
END
@BOX 1.1
#SYS14/1
MODULE SYS14 (VIRTUAL.STORE.INTERRUPT, VALIDATE.FAIL.INTERRUPT, CORE.REJECT, GET
.BLOCK, REL.BLOCK, DISC.STATUS,
   UPDATE.BLOCK, STORE.REJECTION, RESET.PAGING.REGISTERS, MAP.ADDRESS, CREATE.SE
GMENT, RELEASE.SEGMENT,
   CHANGE.SIZE, CHANGE.ACCESS, INTERCHANGE, MAP, CMD.MAP, ALLOCATE.SYS.SEG, PROT
ECT,
   READ.SEGMENT.STATUS, CREATE.X.SEGMENT, CHANGE.X.SIZE, ASSIGN.USER.SEGMENT, AS
SIGN.SYS.SEGMENT,
   CREATE.DISC.SEGMENT, CREATE.DISC.X.SEGMENT,
   RELEASE.SYS.SEGMENT, COPY.BLOCK, INIT.SEGS, TINI.SEGS, SST.PT, SST, CST,
   LST.TYPE, SST.TYPE, SEG.VARS, CMT.TYPE, CMT, SECURE.SEGMENT, READ.SYS.SEGMENT
.STATUS, RESERVE.SEG, STATS.TYPE, X.SEG,
   USAGE.COUNT, LOCKIN, BSA, IN.USE);
@BOX 2.1
TYPE LST.TYPE IS
   LOGICAL8 ACCESS, SSN
OR
   LOGICAL16 LST.ENTRY;
TYPE SST.TYPE IS
   INTEGER DRUM.ADDR, LIMIT, COUNT
   LOGICAL8 STATUS, DISC.NO
OR
   INTEGER SST.LINK;
TYPE CMT.TYPE IS
   LOGICAL16 SSN
   INTEGER16 BLOCK
OR
   LOGICAL32 ENTRY;
TYPE SEG.VARS IS
   LST.TYPE [NO.OF.LOCAL.SEGS] LST
   LST.TYPE [NO.OF.X.SEGS] XST;
TYPE STATS.TYPE IS
   INTEGER32 SEGS.CREATED, X.SEGS.CREATED, PAGES.IN, NEW.PAGES, INVALID.ACCESS;
@BOX 3.1
*GLOBAL 5;
LITERAL / INTEGER ACCESS.VIOLATION = %20, ACCESS.FAULT = 8, SEG.UNDEFINED = %10,
   SEG.OVERFLOW = %20, PAGE.UNAVAILABLE = 4, INITIAL.USAGE = 4, FREE.LIMIT = 4,
   DEFINED = %80, PROTECTED = 1, X.SEG = 2, TRANSFER.FAIL = %1401, SYSTEM.DISC.O
FF = %1402,
   USAGE.THRESHOLD = 2, RESET.ALL = 1, RESET.SEG = 2, RESET.SEG.BLOCK = 4;
LITERAL / LOGICAL DISC.VALID = 1;
LOGICAL REJECTION.HALT;
ADDR [INTEGER8] USAGE.COUNT;
INTEGER FREE.SST, WORDS.PER.PAGE, PTE.PER.PAGE;
INTEGER [SYS01.NO.OF.ACTIVITIES] HFP;
ADDR [LOGICAL8] IN.USE;
SST.TYPE [NO.OF.SYS.SEGS] SST;
LST.TYPE [NO.OF.COMMON.SEGS] CST;
ADDR [LOGICAL32] PT;
ADDR STATS.TYPE STATS;
LOGICAL [SYS03.NO.OF.DISCS] DISC.STATE;
*GLOBAL 8;
LOGICAL32 [NO.OF.SYS.SEGS] SST.PT;
*GLOBAL 5;
ADDR [CMT.TYPE] CMT;
ADDR [INTEGER] BSA;
ADDR [INTEGER16] LOCKIN;
@BOX 4.1
#SYS14/2
@BOX 5.1
*CODE 7;
PSPEC INIT.SYS14 ();
INIT.SYS14 ();
PROC INIT.SYS14;
NO.OF.SYS.SEGS - 1 => FREE.SST;
-1 => SST.LINK OF SST [FREE.SST];
WHILE FREE.SST /= NO.OF.INITIAL.SEGS DO
   FREE.SST => SST.LINK OF SST [1 -> FREE.SST];
OD
PAGE.SIZE / BYTES.PER.WORD => WORDS.PER.PAGE;
PAGE.SIZE / 4 => PTE.PER.PAGE;
MAKE (LOGICAL32, NO.OF.SYS.SEGS * PTE.PER.PAGE, PT.SEG * SEG.SIZE) => PT;
MAKE (STATS.TYPE, 0, SYS21.GET.STATS (14)) => STATS;
END
@BOX 6.1
*END
@END
@TITLE SYS14/1(3,10)

@COL 1S-2R-3R-4R
@FLOW 1-2-3-4

@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
   SYS01 COORDINATOR
   SYS02 CORE MANAGER
   SYS03 DRUM MANAGER
   SYS10 VIRTUAL MACHINE INTERRUPTS
   SYS16 FILE MANAGER
   SYS21 PERFORMANCE MONITORING
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 2.1
IMPORT VSTORE V.VAL.ACCESS, V.NEQ.ACCESS, V.NEQ.SEG, V.NEQ.BLK, V.STACK.SEG,
   V.RESET.BLK, V.RESET.SEG, V.RESET.STATUS;
IMPORT LITERAL X.SEG.SIZE, SEG.SHIFT, PAGE.SIZE, PAGE.SHIFT, LOCKED.SIZE, NO.OF.
INITIAL.SEGS,
   PT.SEG, PAGE.FIELD, IN.CORE, ON.DRUM, LOCKOUT, PAGE.STATUS,
   ALTERED, VALID, REAL.STORE.ADDRESS, RESERVED.BLOCK1, RESERVED.BLOCK2;
IMPORT LITERAL ADDR SEG.SIZE;
IMPORT LITERAL NO.OF.LOCAL.SEGS, NO.OF.COMMON.SEGS, NO.OF.X.SEGS, NO.OF.SYS.SEGS
,
   FIRST.COMMON.SEG, FIRST.X.SEG;
IMPORT LITERAL REG.DUMP.SIZE, DUMPED.V.VAL.ACCESS.REG.NO;
@BOX 3.1
PSPEC BIT (INTEGER) / LOGICAL;
PSPEC SET.BIT (ADDR [LOGICAL8], INTEGER);
PSPEC CLEAR.BIT (ADDR [LOGICAL8], INTEGER);
PSPEC TEST.BIT (ADDR [LOGICAL8], INTEGER) / INTEGER;
IMPORT LITERAL BYTES.PER.WORD;
@BOX 4.1
IMPORT LITERAL SYS01.PAGING.HALT, SYS01.NO.OF.ACTIVITIES,
   SYS01.PAGING.ACTIVITY, SYS01.INT.ACTIVITIES, SYS01.PZ.ACTIVITY;
INTEGER SYS01.CURRENT.ACTIVITY;
LOGICAL SYS01.CURRENT.ACTIVITY.BIT;
PSPEC SYS01.HALT (LOGICAL, INTEGER);
PSPEC SYS01.FREE (LOGICAL, INTEGER);
PSPEC SYS01.SET.INTERRUPT (LOGICAL, LOGICAL);
PSPEC SYS01.CHECKIN (INTEGER, INTEGER);
PSPEC SYS01.CHECKOUT (INTEGER, INTEGER);
PSPEC SYS01.NEXT.ACTIVITY ();
PSPEC SYS01.CLEAR.INTERRUPT ();
INTEGER SYS02.NO.OF.PAGES, SYS02.NO.OF.PAGES.BIT.VEC.SIZE;
PSPEC SYS02.OBTAIN.PAGE (INTEGER) / INTEGER;
PSPEC SYS02.RELEASE.PAGE (INTEGER, INTEGER);
IMPORT LITERAL SYS03.NO.OF.DISCS;
PSPEC SYS03.CHANGE.DRUM.SIZE (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC SYS03.INT.ALLOCATE.DRUM.BLOCK (INTEGER, INTEGER) / INTEGER;
PSPEC SYS03.RELEASE.DRUM.BLOCK (INTEGER, INTEGER, INTEGER);
PSPEC SYS03.REQUEST.DRUM.TRANSFER (INTEGER, INTEGER, INTEGER, INTEGER,
   INTEGER, INTEGER)  / INTEGER;
PSPEC SYS03.CMD.ALLOCATE.DRUM.BLOCK (INTEGER, INTEGER) / INTEGER;
PSPEC SYS03.RESERVE.DRUM.SPACE (INTEGER, INTEGER, INTEGER);
PSPEC SYS10.SET.VM.INT (INTEGER, LOGICAL);
PSPEC SYS12.SYSTEM.ERROR (INTEGER);
INTEGER SYS13.CURRENT.SPN;
IMPORT LITERAL SYS13.NO.OF.PROCS;
LOGICAL [SYS13.NO.OF.PROCS] SYS13.PROC.RESULT;
PSPEC SYS13.INT.PROC (LOGICAL, LOGICAL);
PSPEC SYS13.ENTER.INT.LEVEL (ADDR SYS13.INT.PROC, LOGICAL, LOGICAL);
PSPEC SYS13.GET.PRB (INTEGER, INTEGER) / ADDR;
PSPEC SYS13.INT.GET.PRB (INTEGER) / ADDR;
PSPEC SYS16.CLOSE.FILE (INTEGER);
PSPEC SYS21.GET.STATS (INTEGER) / ADDR;
ADDR PW0, PW1, PW2, PW3, PW4, PW5, PW6;
LOGICAL64 PWW1;
@END


@TITLE SYS14/2(3,10)

@COL 1S

@BOX 1.1
*CODE 2;
PSPEC VIRTUAL.STORE.INTERRUPT ();
PSPEC VALIDATE.FAIL.INTERRUPT ();
PSPEC GET.BLOCK (INTEGER, INTEGER) / INTEGER32;
PSPEC REL.BLOCK (INTEGER32);
PSPEC UPDATE.BLOCK (INTEGER32);
PSPEC STORE.REJECTION ();
PSPEC RELEASE.PAGES (INTEGER, INTEGER);
PSPEC RESET.PAGING.REGISTERS (INTEGER, INTEGER);
PSPEC MAP.ADDRESS (INTEGER32, INTEGER) / ADDR [LOGICAL8];
PSPEC COPY (INTEGER, INTEGER);
PSPEC CORE.REJECT ();
PSPEC SECURE.PAGES (INTEGER, INTEGER);
PSPEC CHECK.LOCKOUT (INTEGER) / INTEGER;
PSPEC GET.SYS.BLOCK (INTEGER, INTEGER, INTEGER) / INTEGER32;
PSPEC DISC.STATUS (INTEGER, INTEGER);
PSPEC WRITE.PAGE.TO.DRUM (INTEGER, INTEGER);
PSPEC SET.SST.PT.0 (LOGICAL32);
   #SYSINT14.1
   #SYSINT14.2
   #SYSINT14.3
   #SYSINT14.4
   #SYSINT14.5
   #SYSINT14.6
   #SYSINT14.7
   #SYSINT14.8
   #SYSINT14.9
   #SYSINT14.10
   #SYSINT14.11
   #SYSINT14.12
   #SYSINT14.13
   #SYSINT14.14
   #SYSINT14.15
   #SYSINT14.17
   #SYSINT14.18
*CODE 15;
PSPEC ASSIGN.USER.SEGMENT (INTEGER, INTEGER, LOGICAL);
PSPEC ASSIGN.SYS.SEGMENT (INTEGER) / INTEGER;
LSPEC MAP (INTEGER, INTEGER, INTEGER);
PSPEC CMD.MAP (INTEGER, INTEGER);
   #SYSCMD14.8
   #SYSCMD14.9
   #SYSCMD14.14
   #SYSCMD14.17
*CODE 16;
LSPEC CREATE.SEGMENT (INTEGER, ADDR);
LSPEC RELEASE.SEGMENT (INTEGER);
LSPEC CHANGE.SIZE (INTEGER, ADDR);
LSPEC CHANGE.ACCESS (INTEGER, LOGICAL);
LSPEC INTERCHANGE (INTEGER, INTEGER);
LSPEC READ.SEGMENT.STATUS (INTEGER);
LSPEC CREATE.X.SEGMENT (INTEGER);
PSPEC RELEASE.SYS.SEGMENT (INTEGER);
PSPEC ALLOCATE.SYS.SEG (INTEGER, INTEGER, INTEGER, INTEGER,
   INTEGER) / INTEGER;
LSPEC COPY.BLOCK (INTEGER, INTEGER, INTEGER, INTEGER);
LSPEC SECURE.SEGMENT (INTEGER);
PSPEC PROTECT (INTEGER, INTEGER);
PSPEC READ.SYS.SEGMENT.STATUS (INTEGER);
PSPEC RESERVE.SEG (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC CREATE.DISC.SEGMENT (INTEGER, ADDR, INTEGER);
PSPEC CREATE.DISC.X.SEGMENT (INTEGER, INTEGER);
   #SYSCMD14.1
   #SYSCMD14.2
   #SYSCMD14.3
   #SYSCMD14.4
   #SYSCMD14.5
   #SYSCMD14.6
   #SYSCMD14.7
   #SYSCMD14.10
   #SYSCMD14.13
   #SYSCMD14.15
   #SYSCMD14.16
   #SYSCMD14.18
   #SYSCMD14.19
   #SYSCMD14.20
   #SYSCMD14.21
   #SYSCMD14.22
*CODE 19;
PSPEC INIT.SEGS (ADDR SEG.VARS, INTEGER, INTEGER);
   #SYSCMD14.11
PSPEC TINI.SEGS (ADDR SEG.VARS);
   #SYSCMD14.12
@END
@TITLE SYSINT14.1(3,11)

@COL 1S-2T-20N-21T-3R-4T-5T-6T-7R-8N-9F
@COL 10N-11R-12N-13R-14N-15R-17R-16R

@ROW 2-10
@ROW 20-11
@ROW 4-12
@ROW 5-14
@ROW 8-16

@FLOW 1-2NO-20-21-3-4DEFINED-5NO-6OK-7-8-9
@FLOW 2YES-10-11-16-8
@FLOW 21INVALID-12-13
@FLOW 4UNDEFINED-12-13-16
@FLOW 5YES-14-15-16
@FLOW 6FAIL-17-16

@BOX 1.0
VIRTUAL STORE INTERRUT
@BOX 2.0
ACCESS VIOLATION?
@BOX 3.0
SET POINTERS TO
RELEVANT SEGMENT TABLE
@BOX 4.0
IS SEGMENT DEFINED?
@BOX 5.0
IS ADDRESS OUT OF RANGE?
@BOX 6.0
GET SYS BLOCK
[SYSINT14.14]
@BOX 7.0
RELEASE LOCKIN
@BOX 9.0
END
@BOX 11.0
SET VIRTUAL MACHINE INTERRUPT
FOR ACCESS VIOLATION
[SYS10]
@BOX 13.0
SET VIRTUAL MACHINE INTERRUPT
FOR SEGMENT UNDEFINED
[SYS10]
@BOX 15.0
SET VIRTUAL MACHINE INTERRUPT
FOR SEGMENT OVERFLOW
[SYS10]
@BOX 16.0
INCREMENT INVALID ACCESS
STATS
@BOX 17.0
SET VIRTUAL MACHINE INTERRUPT
FOR PAGE UNAVAILABLE
[SYS10]
@BOX 21.0
IS SEGMENT NUMBER VALID?
@BOX 1.1
PROC VIRTUAL.STORE.INTERRUPT;
INTEGER SEG, BLK, TEMP;
INTEGER32 PAGE.ADDR;
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
@BOX 2.1
IF V.NEQ.ACCESS & ACCESS.VIOLATION /= 0
@BOX 3.1
V.NEQ.BLK => BLK;
IF SEG < NO.OF.LOCAL.SEGS THEN
   MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   ^LST [SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^CST [SEG - FIRST.COMMON.SEG] => SEG.TABLE;
FI
SELECT SEG.TABLE^;
@BOX 4.1
IF ACCESS & DEFINED = 0
@BOX 5.1
IF LIMIT OF SST [SSN] =< BLK
@BOX 6.1
IF GET.SYS.BLOCK (SEG, SSN, BLK) => PAGE.ADDR < 0
@BOX 7.1
PAGE.ADDR ->> PAGE.SHIFT => TEMP;
1 -> LOCKIN^ [TEMP];
@BOX 9.1
END
@BOX 11.1
SYS10.SET.VM.INT (0, ACCESS.FAULT);
@BOX 13.1
SYS10.SET.VM.INT (0, SEG.UNDEFINED);
@BOX 15.1
SYS10.SET.VM.INT (0, SEG.OVERFLOW);
@BOX 16.1
1 +> INVALID.ACCESS OF STATS^;
@BOX 17.1
SYS10.SET.VM.INT (0, PAGE.UNAVAILABLE);
@BOX 21.1
IF V.NEQ.SEG => SEG < FIRST.COMMON.SEG >= NO.OF.LOCAL.SEGS
   OR SEG >= FIRST.COMMON.SEG + NO.OF.COMMON.SEGS
@END

@TITLE SYSINT14.2(3,10)

@COL 1S-8T-2R-3T-4T-5R-6F
@COL 7R

@ROW 5-7

@FLOW 1-8-2-3DEFINED-4NO-5-6
@FLOW 8INVALID-7-6
@FLOW 3UNDEFINED-7-6
@FLOW 4YES-7

@BOX 1.0
VALIDATE FAIL INTERRUPT
@BOX 2.0
SET POINTERS TO
RELEVANT SEGMENT TABLE
@BOX 3.0
IS SEGMENT DEFINED?
@BOX 4.0
IS ADDRESS OUT OF RANGE?
@BOX 5.0
RETURN ALLOWED ACCESS PERMISSION
IN DUMPED REGISTER
@BOX 6.0
END
@BOX 7.0
RETURN ZERO ACCESS PERMISSION
IN DUMPED REGISTER
@BOX 8.0
IS SEGMENT NUMBER VALID?
@BOX 1.1
PROC VALIDATE.FAIL.INTERRUPT;
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
ADDR [LOGICAL] PRB.PTR;
MAKE (LOGICAL, REG.DUMP.SIZE, SYS13.INT.GET.PRB (13)) => PRB.PTR;
@BOX 2.1
IF V.NEQ.SEG < NO.OF.LOCAL.SEGS THEN
   MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   ^LST [V.NEQ.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^CST [V.NEQ.SEG - FIRST.COMMON.SEG] => SEG.TABLE;
FI
SELECT SEG.TABLE^;
@BOX 3.1
IF ACCESS & DEFINED = 0
@BOX 4.1
IF LIMIT OF SST [SSN] =< V.NEQ.BLK
@BOX 5.1
ACCESS & %1E => PRB.PTR^ [DUMPED.V.VAL.ACCESS.REG.NO];
@BOX 6.1
END
@BOX 7.1
0 => PRB.PTR^ [DUMPED.V.VAL.ACCESS.REG.NO];
@BOX 8.1
IF V.NEQ.SEG < FIRST.COMMON.SEG >= NO.OF.LOCAL.SEGS
   OR V.NEQ.SEG >= FIRST.COMMON.SEG + NO.OF.COMMON.SEGS
@END


@TITLE SYSINT14.3(3,10)

@COL 1S-3R-5F

@FLOW 1-3-5

@BOX 1.0
GET BLOCK (SEG, BLOCK)
@BOX 3.0
GET SYS BLOCK
[SYSINT14.14]
@BOX 5.0
END
@BOX 1.1
PROC GET.BLOCK (SEG, BLOCK);
@BOX 3.1
IF SEG >= FIRST.X.SEG < FIRST.X.SEG + NO.OF.X.SEGS THEN
   -1 -:> BLOCK;
FI
GET.SYS.BLOCK (SEG, -1, BLOCK) => GET.BLOCK;
@BOX 5.1
END
@END

@TITLE SYSINT14.4(3,10)

@COL 1S-2R-4T-5R-3F

@FLOW 1-2-4NO-5-3
@FLOW 4YES-3

@BOX 1.0
REL BLOCK (CORE ADDR)
@BOX 2.0
DECREMENT LOCKIN COUNT
FOR THE BLOCK
@BOX 3.0
END
@BOX 4.0
NORMAL SEGMENT BLOCK
OR STILL LOCKED IN?
@BOX 5.0
RELEASE X SEGMENT BLOCK
@BOX 1.1
PROC REL.BLOCK (CORE.ADDR);
INTEGER PAGE, PT.BLOCK, PT.ENTRY, X.ENTRY, TEMP;
@BOX 2.1
CORE.ADDR ->> PAGE.SHIFT => PAGE;
1 -> LOCKIN^ [PAGE];
@BOX 3.1
END
@BOX 4.1
SELECT CMT^ [PAGE];
IF BLOCK >= 0 OR LOCKIN^ [PAGE] > 0
@BOX 5.1
SET.SST.PT.0 (PT^ [SSN * PTE.PER.PAGE + (-1 -:> BLOCK / PTE.PER.PAGE
   => PT.BLOCK) => X.ENTRY]);
PT.BLOCK * PTE.PER.PAGE -: BLOCK => PT.ENTRY;
VALID ! ALTERED ! PAGE.STATUS ! PAGE.FIELD & PT^ [PT.ENTRY]
  -=> PT^ [PT.ENTRY];
IF BSA^ [PAGE] /= 0 THEN
   ON.DRUM ! BSA^ [PAGE] !> PT^ [PT.ENTRY];
FI
ALTERED !> PT^ [X.ENTRY];
0 => ENTRY;
SST.PT [0] & PAGE.FIELD => TEMP;
1 -> LOCKIN^ [TEMP];
CLEAR.BIT (IN.USE, PAGE);
SYS02.RELEASE.PAGE (PAGE, 1);
@END


@TITLE SYSINT14.5(3,10)
@COL 1S-2T-3R-8F
@COL 9R

@ROW 3-9

@FLOW 1-2X SEG-3-8
@FLOW 2-9-8

@BOX 1.0
UPDATE BLOCK (CORE ADDR)
@BOX 2.0
NOT X SEG?
@BOX 3.0
WRITE PAGE TO DRUM
[SYSINT14.17]
@BOX 8.0
END
@BOX 9.0
MARK PAGE ALTERED
@BOX 1.1
PROC UPDATE.BLOCK (CORE.ADDR);
INTEGER PAGE, PT.ENTRY, PT.BLOCK, X.BLOCK;
@BOX 2.1
CORE.ADDR ->> PAGE.SHIFT => PAGE;
SELECT CMT^ [PAGE];
IF BLOCK >= 0
@BOX 3.1
SET.SST.PT.0 (PT^ [SSN * PTE.PER.PAGE + (-1 - BLOCK => X.BLOCK
   / PTE.PER.PAGE => PT.BLOCK)]);
WRITE.PAGE.TO.DRUM (PAGE, PT.BLOCK * PTE.PER.PAGE -: X.BLOCK);
@BOX 8.1
END
@BOX 9.1
SSN * PTE.PER.PAGE + BLOCK => PT.ENTRY;
ALTERED !> PT^ [PT.ENTRY];
@END


@TITLE SYSINT14.6(3,10)

@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5

@BOX 1.0
STORE REJECTION
@BOX 2.0
SET SOFTWARE INTERRUPT
FOR REJECTION PROCESS
@BOX 3.0
MARK PROCESS HALTED
FOR REJECTION
@BOX 4.0
HALT PROCESS FOR PAGING
[SYS01]
@BOX 5.0
END
@BOX 1.1
PROC STORE.REJECTION;
@BOX 2.1
SYS01.SET.INTERRUPT (SYS01.PAGING.ACTIVITY, 0);
@BOX 3.1
SYS01.CURRENT.ACTIVITY.BIT !> REJECTION.HALT;
@BOX 4.1
SYS01.HALT (SYS01.CURRENT.ACTIVITY.BIT,
   SYS01.PAGING.HALT);
@BOX 5.1
END
@END


@TITLE SYSINT14.7(3,10)

@COL 1S-2R-3T-6R-14T-15R-16T-5T-7R-8R-10R-9T-13R-11R-12F

@FLOW 1-2-3OK-6-14NO-15-16NO-5IN CORE-7-8-10-9NO-13-11-12
@FLOW 3FAIL-12
@FLOW 5-10
@FLOW 9YES-6
@FLOW 14YES-5
@FLOW 16YES-9

@BOX 1.0
RELEASE PAGES (SEG, NEW COUNT)
@BOX 2.0
SET POINTER TO THE FIRST
PAGE TABLE ENTRY
@BOX 3.0
GET PAGE TABLE IN CORE
@BOX 5.0
IS NEXT PAGE IN CORE?
@BOX 6.0
WAIT TILL PAGE AVAILABLE
@BOX 7.0
MARK PAGE NOT IN CORE
@BOX 8.0
RELEASE PAGE
[SYS02]
@BOX 9.0
ANY MORE PAGES?
@BOX 10.0
RELEASE DRUM BLOCKS
IF NECESSARY
@BOX 11.0
RELEASE PAGE TABLE
IF NECESSARY
@BOX 12.0
END
@BOX 13.0
RELEASE LOCKIN ON THE
PAGE TABLE
@BOX 14.0
NORMAL SEGMENT?
@BOX 15.0
RELEASE X SEGMENT BLOCKS
@BOX 16.0
PARTIALLY FULL PAGE TABLE?
@BOX 1.1
PROC RELEASE.PAGES (SEG, NEW.SIZE);
INTEGER PAGE.PNO, PT.ENTRY, BLOCK.NO, BLK, COUNT, PROTECT.STATUS, DISC.SEG, DISC
.NUMBER, X.COUNT, X.PT.ENTRY, I, TEMP;
INTEGER32 PT.ADDR, X.PT.ADDR;
LOGICAL32 SST.PT.0;
@BOX 2.1
STATUS OF SST [SEG] & PROTECTED => PROTECT.STATUS;
SEG => DISC.SEG;
IF NEW.SIZE < 0 THEN
   1 => COUNT;
   SEG / PTE.PER.PAGE => BLOCK.NO * PTE.PER.PAGE -: SEG => BLK;
   SSN OF CST [PT.SEG - FIRST.COMMON.SEG + BLOCK.NO] => SEG;
ELSE
   IF STATUS OF SST [SEG] & X.SEG = 0 THEN
      LIMIT OF SST [SEG] - NEW.SIZE => COUNT;
      NEW.SIZE => BLK;
   ELSE
      LIMIT OF SST [SEG] + PTE.PER.PAGE - 1 / PTE.PER.PAGE - (NEW.SIZE / PTE.PER
.PAGE => BLK) => COUNT;
      BLK * PTE.PER.PAGE -: NEW.SIZE -: PTE.PER.PAGE => X.COUNT;
   FI
FI
SEG * PTE.PER.PAGE + BLK => PT.ENTRY;
SEG / PTE.PER.PAGE => BLOCK.NO * PTE.PER.PAGE -: SEG => BLK;
@BOX 3.1
IF GET.SYS.BLOCK (PT.SEG + BLOCK.NO, -1, BLK) => PT.ADDR < 0
@BOX 5.1
IF PAGE.STATUS & PT^ [PT.ENTRY] /= IN.CORE
@BOX 6.1
WHILE CHECK.LOCKOUT (PT.ENTRY) /= 0 DO OD
@BOX 7.1
PAGE.FIELD & PT^ [PT.ENTRY] => PAGE.PNO;
VALID ! ALTERED ! PAGE.STATUS ! PAGE.FIELD & PT^ [PT.ENTRY] -=> PT^ [PT.ENTRY];
IF BSA^ [PAGE.PNO] /= 0 THEN
   ON.DRUM ! BSA^ [PAGE.PNO] !> PT^ [PT.ENTRY];
FI
@BOX 8.1
PT.ADDR ->> PAGE.SHIFT => TEMP;
1 -> LOCKIN^ [TEMP];
0 => ENTRY OF CMT^ [PAGE.PNO];
SYS02.RELEASE.PAGE (PAGE.PNO, 1);
CLEAR.BIT (IN.USE, PAGE.PNO);
@BOX 9.1
PTE.PER.PAGE => X.COUNT;
1 +> PT.ENTRY;
IF 1 -> COUNT > 0
@BOX 10.1
IF PAGE.STATUS & PT^ [PT.ENTRY] = ON.DRUM AND PROTECT.STATUS = 0 THEN
   IF DISC.NO OF SST [DISC.SEG] => DISC.NUMBER >= 0 THEN
      SYS03.RELEASE.DRUM.BLOCK (DISC.NUMBER, PT^ [PT.ENTRY] & PAGE.FIELD, 1);
   FI
   PAGE.FIELD ! ON.DRUM & PT^ [PT.ENTRY] -=> PT^ [PT.ENTRY];
FI
@BOX 11.1
SEG => V.RESET.SEG;
NEW.SIZE => V.RESET.BLK;
RESET.ALL => V.RESET.STATUS;
IF NEW.SIZE = 0 THEN
   RELEASE.PAGES (SEG, -1);
FI
@BOX 12.1
END
@BOX 13.1
PT.ADDR ->> PAGE.SHIFT => TEMP;
1 -> LOCKIN^ [TEMP];
@BOX 14.1
IF STATUS OF SST [SEG] & X.SEG = 0
@BOX 15.1
IF GET.SYS.BLOCK (-1, SEG, SEG * PTE.PER.PAGE -: PT.ENTRY) => X.PT.ADDR >= 0 THE
N
   X.PT.ADDR ->> PAGE.SHIFT => TEMP;
   1 -> LOCKIN^ [TEMP];
   SST.PT [0] => SST.PT.0;
   FOR I < X.COUNT DO
      PTE.PER.PAGE - 1 - I => X.PT.ENTRY;
      IF PT^ [X.PT.ENTRY] & PAGE.STATUS = ON.DRUM
         AND PROTECT.STATUS = 0 THEN
         IF DISC.NO OF SST [DISC.SEG] => DISC.NUMBER >= 0 THEN
            SYS03.RELEASE.DRUM.BLOCK (DISC.NUMBER, PT^ [X.PT.ENTRY] & PAGE.FIELD
, 1);
            SET.SST.PT.0 (SST.PT.0);
         FI
         PAGE.FIELD ! ON.DRUM & PT^ [X.PT.ENTRY] -=> PT^ [X.PT.ENTRY];
      FI
   OD
FI
@BOX 16.1
IF X.COUNT /= PTE.PER.PAGE
@END

@TITLE SYSINT14.8(3,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
RESET PAGING REGISTERS (SEG, STATUS)
@BOX 2.0
SET THE NECESSARY V STORES
@BOX 3.0
END
@BOX 1.1
PROC RESET.PAGING.REGISTERS (SEG, STATUS);
@BOX 2.1
0 => SST.PT [0];
SEG => V.RESET.SEG;
0 => V.RESET.BLK;
STATUS => V.RESET.STATUS;
@BOX 3.1
END
@END


@TITLE SYSINT14.9(3,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MAP ADDRESS (CORE ADDRESS, PREF SEG)
@BOX 2.0
RETURN MAPPED ADDRESS
@BOX 3.0
END
@BOX 1.1
PROC MAP.ADDRESS (CORE.ADDR, PREF.SEG);
@BOX 2.1
MAKE (LOGICAL8, PAGE.SIZE, REAL.STORE.ADDRESS + CORE.ADDR) => MAP.ADDRESS;
@BOX 3.1
END
@END


@TITLE SYSINT14.10(3,10)

@COL 1S-2R-3T-4T-7R-8R-9F
@COL 10R

@ROW 10-7

@FLOW 1-2-3OK-4OK-7-8-9
@FLOW 3FAIL-9
@FLOW 4FAIL-10-9

@BOX 1.0
COPY (SSN1/BLK1, SSN2/BLK2)
@BOX 2.0
UNPACK SEGMENT AND BLOCK NUMBERS
@BOX 3.0
GET FIRST BLOCK
@BOX 4.0
GET SECOND BLOCK
@BOX 7.0
STORE TO STORE COPY
@BOX 8.0
UPDATE AND RELEASE BLOCKS
@BOX 9.0
END
@BOX 10.0
RELEASE FIRST BLOCK
@BOX 1.1
PROC COPY (SSN1.BLK1, SSN2.BLK2);
INTEGER SSN1, BLK1, SSN2, BLK2, SPN, TEMP;
INTEGER32 PAGE1, PAGE2;
ADDR [LOGICAL] BLOCK1, BLOCK2;
-1 => SYS13.PROC.RESULT [SYS13.CURRENT.SPN => SPN];
@BOX 2.1
SSN1.BLK1 / X.SEG.SIZE => SSN1 * X.SEG.SIZE -: SSN1.BLK1 => BLK1;
SSN2.BLK2 / X.SEG.SIZE => SSN2 * X.SEG.SIZE -: SSN2.BLK2 => BLK2;
IF STATUS OF SST [SSN1] & X.SEG /= 0 THEN
   -1 -:> BLK1;
FI
IF STATUS OF SST [SSN2] & X.SEG /= 0 THEN
   -1 -:> BLK2;
FI
@BOX 3.1
IF GET.SYS.BLOCK (-1, SSN1, BLK1) => PAGE1 < 0
@BOX 4.1
IF GET.SYS.BLOCK (-1, SSN2, BLK2) => PAGE2 < 0
@BOX 7.1
MAKE (LOGICAL, WORDS.PER.PAGE, REAL.STORE.ADDRESS + PAGE1) => BLOCK1;
MAKE (LOGICAL, WORDS.PER.PAGE, REAL.STORE.ADDRESS + PAGE2) => BLOCK2;
FOR TEMP < WORDS.PER.PAGE DO
   BLOCK1^ [TEMP] => BLOCK2^ [TEMP];
OD
@BOX 8.1
UPDATE.BLOCK (PAGE2);
REL.BLOCK (PAGE1);
REL.BLOCK (PAGE2);
0 => SYS13.PROC.RESULT [SPN];
@BOX 9.1
END
@BOX 10.1
REL.BLOCK (PAGE1);
@END
@TITLE SYSINT14.11(3,10)

@COL 1S-26N-2T-3R-4T-5T-6R-27T-7T-8T-9R-14R-15R-16R-17F
@COL 23N-18R-19R-24N-20R

@ROW 26-23
@ROW 3-18
@ROW 27-24
@ROW 8-20

@FLOW 1-26-2NO-3-4NO-5NO-6-27-7ZERO-8ALTERED-9-14-15-16-26
@FLOW 2YES-18-19-23-26
@FLOW 4YES-3
@FLOW 5YES-3
@FLOW 27YES-3
@FLOW 7-20-24-3
@FLOW 8-14


@BOX 1.0
CORE REJECT
@BOX 2.0
SUFFICIENT SPACE AVAILABLE?
@BOX 3.0
INCREMENT INDEX INTO CMT
(CYCLICALLY)
@BOX 4.0
IS PAGE OUT OF USE?
@BOX 5.0
IS PAGE LOCKED IN?
@BOX 6.0
SET POINTER TO PAGE TABLE ENTRY
@BOX 7.0
DECREMENT USAGE COUNT
@BOX 8.0
IS PAGE MARKED ALTERED?
@BOX 9.0
WRITE PAGE TO DRUM
[SYSINT14.17]
@BOX 14.0
MARK PAGE AS ON DRUM AND
NOTE DRUM ADDRESS
@BOX 15.0
RELEASE PAGE
[SYS02]
@BOX 16.0
FREE ALL ACTIVITIES
HALTED FOR SPACE
@BOX 17.0
END
@BOX 18.0
CLEAR SOFTWARE INTERRUPT
FOR CURRENT ACTIVITY
@BOX 19.0
CALL LOW LEVEL SCHEDULER
(NEXT ACTIVITY)
@BOX 20.0
MARK PAGE TABLE ENTRY AS NOT VALID
IF USAGE COUNT HAS PASSED THRESHOLD
@BOX 27.0
IS PAGE LOCKED OUT?
@BOX 1.1
PROC CORE.REJECT;
INTEGER PAGE.PNO, PT.ENTRY, TEMP, COUNT;
0 => COUNT;
LOCKED.SIZE - 1 => PAGE.PNO;
@BOX 2.1
IF 1 +> COUNT > FREE.LIMIT
@BOX 3.1
IF 1 +> PAGE.PNO >= SYS02.NO.OF.PAGES THEN
   LOCKED.SIZE => PAGE.PNO;
FI
@BOX 4.1
IF TEST.BIT (IN.USE, PAGE.PNO) = 0
@BOX 5.1
IF LOCKIN^ [PAGE.PNO] /= 0
@BOX 6.1
SELECT CMT^ [PAGE.PNO];
SSN * PTE.PER.PAGE + BLOCK => PT.ENTRY;
@BOX 7.1
IF 1 -> USAGE.COUNT^ [PAGE.PNO] /= 0
@BOX 8.1
IF ALTERED & PT^ [PT.ENTRY] = 0
@BOX 9.1
WRITE.PAGE.TO.DRUM (PAGE.PNO, PT.ENTRY);
@BOX 14.1
VALID ! ALTERED ! PAGE.STATUS ! PAGE.FIELD & PT^ [PT.ENTRY] -=> PT^ [PT.ENTRY];
ON.DRUM ! BSA^ [PAGE.PNO] !> PT^ [PT.ENTRY];
SSN OF CMT^ [PAGE.PNO] => V.RESET.SEG;
BLOCK OF CMT^ [PAGE.PNO] => V.RESET.BLK;
RESET.ALL => V.RESET.STATUS;
@BOX 15.1
SST.PT [SSN OF CMT^ [PAGE.PNO]] & PAGE.FIELD => TEMP;
1 -> LOCKIN^ [TEMP];
CLEAR.BIT (IN.USE, PAGE.PNO);
0 => BSA^ [PAGE.PNO];
0 => ENTRY OF CMT^ [PAGE.PNO];
SYS02.RELEASE.PAGE (PAGE.PNO, 1);
@BOX 16.1
SYS01.FREE (REJECTION.HALT, SYS01.PAGING.HALT);
0 => REJECTION.HALT;
@BOX 17.1
END
@BOX 18.1
0 => COUNT;
SYS01.CLEAR.INTERRUPT ();
@BOX 19.1
SYS01.NEXT.ACTIVITY ();
@BOX 20.1
IF USAGE.COUNT^ [PAGE.PNO] = USAGE.THRESHOLD THEN
   VALID & PT^ [PT.ENTRY] -=> PT^ [PT.ENTRY];
FI
@BOX 27.1
IF PAGE.STATUS & PT^ [PT.ENTRY] = LOCKOUT
@END
@TITLE SYSINT14.12(3,10)

@COL 1S-18R-2T-6T-5T-24T-7R-8R-9R-10R-11R-22R-23R-12T-16R-17R-13F

@FLOW 1-18-2OK-6-5IN CORE-24VALID-7-8-9-10-11-22-23-12ZERO-16-17-13
@FLOW 6LOCKED OUT-6
@FLOW 5-12
@FLOW 12-6
@FLOW 2FAIL-13
@FLOW 24INVALID-22

@BOX 1.0
SECURE PAGES (SYS SEG, INIT VALUE)
@BOX 2.0
GET PAGE TABLE IN CORE
@BOX 5.0
IS PAGE NOT IN CORE?
@BOX 6.0
IS PAGE LOCKED OUT?
@BOX 8.0
ALLOCATE DRUM SPACE IF NECESSARY
@BOX 7.0
MARK PAGE LOCKED OUT
@BOX 9.0
REQUEST DRUM TRANSFER
@BOX 10.0
REMOVE LOCKOUT
@BOX 11.0
FREE ALL ACTIVITIES
HALTED FOR THE PAGE
@BOX 12.0
DECREMENT PAGE COUNT
@BOX 13.0
END
@BOX 16.0
RELEASE LOCKIN ON THE
PAGE TABLE
@BOX 17.0
SECURE PAGE TABLE
IF NECESSARY
@BOX 18.0
SET PAGING COUNT
@BOX 22.0
MAKE PAGES AS ON DRUM AND
NOTE DRUM ADDRESS
@BOX 23.0
FREE ALL ACTIVITIES HALTED
FOR THE PAGE
@BOX 24.0
DISC INVALID?
@BOX 1.1
PROC SECURE.PAGES (SYS.SEG, INIT.VALUE);
INTEGER PT.ENTRY, PAGE.PNO, PTR, COUNT, BLOCK.NO, BLK,
   DISC.SEG, DISC.NUMBER, TEMP;
INTEGER32 PT.ADDR;
@BOX 2.1
IF GET.SYS.BLOCK (PT.SEG + BLOCK.NO, -1, BLK) => PT.ADDR < 0
@BOX 5.1
IF PAGE.STATUS & PT^ [PT.ENTRY] /= IN.CORE
@BOX 6.1
IF CHECK.LOCKOUT (PT.ENTRY) /= 0
@BOX 8.1
PAGE.FIELD & PT^ [PT.ENTRY] => PAGE.PNO;
IF BSA^ [PAGE.PNO] = 0 THEN
   SYS03.INT.ALLOCATE.DRUM.BLOCK (DISC.NUMBER, 1) => BSA^ [PAGE.PNO];
FI
@BOX 7.1
LOCKOUT -= IN.CORE -=> PT^ [PT.ENTRY];
@BOX 9.1
WHILE SYS03.REQUEST.DRUM.TRANSFER (DISC.NUMBER, PAGE.PNO, BSA^ [PAGE.PNO], 0, 1,
 1) /= 0
   AND DISC.NO OF SST [DISC.SEG] => DISC.NUMBER >= 0 DO
   SYS03.INT.ALLOCATE.DRUM.BLOCK (DISC.NUMBER, 1) => BSA^ [PAGE.PNO];
OD
@BOX 10.1
LOCKOUT -= IN.CORE -=> PT^ [PT.ENTRY];
@BOX 11.1
FOR PTR < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [PTR] = PT.ENTRY THEN
      0 => HFP [PTR];
      SYS01.FREE (BIT (PTR), SYS01.PAGING.HALT);
   FI
OD
@BOX 12.1
1 +> PT.ENTRY;
IF 1 -> COUNT > 0
@BOX 13.1
END
@BOX 16.1
PT.ADDR ->> PAGE.SHIFT => TEMP;
1 -> LOCKIN^ [TEMP];
@BOX 17.1
SYS.SEG => V.RESET.SEG;
INIT.VALUE => V.RESET.BLK;
RESET.ALL => V.RESET.STATUS;
IF INIT.VALUE = 0 THEN
   SECURE.PAGES (SYS.SEG, -1);
   SST.PT [SYS.SEG] & PAGE.FIELD => DRUM.ADDR OF SST [SYS.SEG];
FI
@BOX 18.1
SYS.SEG => DISC.SEG;
SYS.SEG / PTE.PER.PAGE => BLOCK.NO * PTE.PER.PAGE -: SYS.SEG => BLK;
IF INIT.VALUE = 0 THEN
   LIMIT OF SST [SYS.SEG] => COUNT;
   IF STATUS OF SST [SYS.SEG] & X.SEG /= 0 THEN
      COUNT + PTE.PER.PAGE - 1 / PTE.PER.PAGE => COUNT;
   FI
   SYS.SEG * PTE.PER.PAGE => PT.ENTRY;
ELSE
   0 => COUNT;
   SSN OF CST [PT.SEG - FIRST.COMMON.SEG + BLOCK.NO] => SYS.SEG;
   SYS.SEG * PTE.PER.PAGE + BLK => PT.ENTRY;
   SYS.SEG / PTE.PER.PAGE => BLOCK.NO * PTE.PER.PAGE -: SYS.SEG => BLK;
FI
@BOX 22.1
VALID ! ALTERED ! PAGE.STATUS ! PAGE.FIELD & PT^ [PT.ENTRY] -=> PT^ [PT.ENTRY];
ON.DRUM ! BSA^ [PAGE.PNO] !> PT^ [PT.ENTRY];
@BOX 23.1
SST.PT [SSN OF CMT^ [PAGE.PNO]] & PAGE.FIELD => TEMP;
1 -> LOCKIN^ [TEMP];
CLEAR.BIT (IN.USE, PAGE.PNO);
0 => BSA^ [PAGE.PNO];
0 => ENTRY OF CMT^ [PAGE.PNO];
SYS02.RELEASE.PAGE (PAGE.PNO, 1);
@BOX 24.1
IF DISC.NO OF SST [DISC.SEG] => DISC.NUMBER < 0
@END


@TITLE SYSINT14.13(3,10)

@COL 1S-2T-3R-4R-5F

@FLOW 1-2LOCKED OUT-3-4-5
@FLOW 2-5

@BOX 1.0
CHECK LOCKOUT (PT ENTRY)
@BOX 2.0
NOT LOCKED OUT?
@BOX 3.0
MARK PROCESS HALTED
FOR THIS PAGE
@BOX 4.0
HALT PROCESS FOR PAGING
[SYS01]
@BOX 5.0
END
@BOX 1.1
PROC CHECK.LOCKOUT (PT.ENTRY);
0 => CHECK.LOCKOUT;
@BOX 2.1
IF PAGE.STATUS & PT^ [PT.ENTRY] /= LOCKOUT
@BOX 3.1
PT.ENTRY => HFP [SYS01.CURRENT.ACTIVITY];
@BOX 4.1
SYS01.HALT (SYS01.CURRENT.ACTIVITY.BIT, SYS01.PAGING.HALT);
1 => CHECK.LOCKOUT;
@BOX 5.1
END
@END
@TITLE SYSINT14.14(3,10)

@COL 1S-7T-8R-26T-3T-4T-5T-6R-9T-10R-13R-14F
@COL 19R-25N

@ROW 5-19

@FLOW 1-7NO-8-26VALID-3OK-4-5-6-9NO-10-13-14
@FLOW 7YES-26
@FLOW 4IN CORE-19-25-9
@FLOW 5LOCKED OUT-4
@FLOW 3FAIL-9
@FLOW 26INVALID-9
@FLOW 9YES-13

@BOX 1.0
GET SYS BLOCK (SEG, SYS SEG, BLOCK)
@BOX 3.0
GET PAGE TABLE
#SYSINT14.14.2
@BOX 4.0
IS PAGE IN CORE?
@BOX 5.0
IS PAGE LOCKED OUT?
@BOX 6.0
NEW BLOCK
#SYSINT14.14.1
@BOX 7.0
SYSTEM SEGMENT KNOWN?
@BOX 8.0
FIND SYSTEM SEGMENT NUMBER
@BOX 9.0
X SEGMENT BLOCK?
@BOX 10.0
RESET PAGING REGISTERS
@BOX 13.0
UPDATE USAGE INFORMATION
FOR THE PAGE
@BOX 14.0
END
@BOX 19.0
MARK PAGE TABLE ENTRY VALID
AND LOCK PAGE IN CORE
@BOX 26.0
REQUIRED DISC INVALID?
@BOX 1.1
PROC GET.SYS.BLOCK (SEG.NO, SYS.SEG, BLOCK);
INTEGER PT.ENTRY, PAGE.PNO, PT.PNO, TEMP, DISC.NUMBER, I;
LOGICAL32 SST.PT.0, P.STATUS;
INTEGER32 PAGE.ADDR, PT.ADDR;
ADDR [LOGICAL] CLEAR.PAGE;
ADDR SEG.VARS C.SEG.VARS;
-1 => PAGE.ADDR;
@BOX 3.1
#SYSINT14.14.2
IF PT.ADDR < 0
@BOX 4.1
IF BLOCK < 0 THEN
   SET.SST.PT.0 (SST.PT.0);
FI
IF PAGE.STATUS & PT^ [PT.ENTRY] = IN.CORE
@BOX 5.1
IF CHECK.LOCKOUT (PT.ENTRY) /= 0
@BOX 6.1
#SYSINT14.14.1
@BOX 7.1
IF SYS.SEG >= 0
@BOX 8.1
IF SEG.NO < NO.OF.LOCAL.SEGS OR
   SEG.NO >= FIRST.X.SEG < FIRST.X.SEG + NO.OF.X.SEGS THEN
   MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   IF SEG.NO < NO.OF.LOCAL.SEGS THEN
      SSN OF LST [SEG.NO] OF C.SEG.VARS^ => SYS.SEG;
   ELSE
      SSN OF XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SYS.SEG;
   FI
ELSE
   SSN OF CST [SEG.NO - FIRST.COMMON.SEG] => SYS.SEG;
FI
@BOX 9.1
IF BLOCK < 0
@BOX 10.1
IF SEG.NO >= 0 THEN
   SEG.NO => V.RESET.SEG;
   BLOCK => V.RESET.BLK;
   RESET.SEG.BLOCK => V.RESET.STATUS;
ELSE
   IF STATUS & X.SEG /= 0 THEN
      SET.SST.PT.0 (PT^ [PT.ENTRY]);
      ALTERED !> PT^ [PT.ENTRY];
   FI
FI
@BOX 13.1
IF PAGE.ADDR >= 0 THEN
   INITIAL.USAGE => USAGE.COUNT^ [PAGE.PNO];
FI
PAGE.ADDR => GET.SYS.BLOCK;
@BOX 14.1
END
@BOX 19.1
VALID !> PT^ [PT.ENTRY];
PT^ [PT.ENTRY] & PAGE.FIELD => PAGE.PNO
   <<- PAGE.SHIFT => PAGE.ADDR;
1 -> LOCKIN^ [PT.PNO];
1 +> LOCKIN^ [PAGE.PNO];
@BOX 26.1
SELECT SST [SYS.SEG];
DISC.NO => DISC.NUMBER;
FOR I < NO.OF.SYS.SEGS / PTE.PER.PAGE DO
   IF SSN OF CST [PT.SEG - FIRST.COMMON.SEG + I] = SYS.SEG THEN
      DISC.NO OF SST [I * PTE.PER.PAGE + BLOCK]
         => DISC.NUMBER;
   FI
OD
IF DISC.NUMBER < 0
@END


@TITLE SYSINT14.14.1(3,11)

@COL 1S-6R-7R-9T-20R-10R-11R-8R-12R-13F
@COL 21R-17T-18R-19R

@ROW 20-21

@FLOW 1-6-7-9UNALLOCATED-20-10-11-8-12-13
@FLOW 9ON DRUM-21-17OK-18-8
@FLOW 17FAIL-19-12

@BOX 1.0
NEW BLOCK
@BOX 6.0
MARK PAGE TABLE ENTRY
LOCKED OUT
@BOX 7.0
OBTAIN A PAGE OF CORE
[SYS02]
@BOX 8.0
NOTE CORE ADDRESS OF PAGE
@BOX 9.0
IS PAGE ON DRUM?
@BOX 10.0
SET PAGE TABLE ENTRY FOR
PAGE IN CORE, VALID AND ALTERED
REMOVE LOCKOUT
@BOX 11.0
SET INITIAL VALUE IN PAGE
@BOX 12.0
FREE ALL ACTIVITIES HALTED
FOR THIS PAGE
@BOX 13.0
END
@BOX 17.0
REQUEST DRUM TRANSFER
[SYS03]
@BOX 18.0
SET PAGE TABLE ENTRY FOR
PAGE IN CORE AND VALID
REMOVE LOCKOUT
@BOX 19.0
RETURN ERROR STATUS
@BOX 20.0
INCREMENT NEW PAGES
OF STATS
@BOX 21.0
INCREMENT PAGES IN
OF STATS
@BOX 1.1
BEGIN :: NEW BLOCK
@BOX 6.1
PT^ [PT.ENTRY] & PAGE.STATUS => P.STATUS -=> PT^ [PT.ENTRY];
LOCKOUT !> PT^ [PT.ENTRY];
@BOX 7.1
SYS02.OBTAIN.PAGE (1) => PAGE.PNO;
IF BLOCK < 0 THEN
   SET.SST.PT.0 (SST.PT.0);
FI
PAGE.PNO <<- PAGE.SHIFT => PAGE.ADDR;
PT^ [PT.ENTRY] & PAGE.FIELD => BSA^ [PAGE.PNO];
@BOX 8.1
1 +> LOCKIN^ [PAGE.PNO];
SET.BIT (IN.USE, PAGE.PNO);
PT^ [PT.ENTRY] & PAGE.FIELD -= PAGE.PNO -=> PT^ [PT.ENTRY];
SYS.SEG => SSN OF CMT^ [PAGE.PNO];
BLOCK => BLOCK OF CMT^ [PAGE.PNO];
@BOX 9.1
IF P.STATUS = ON.DRUM
@BOX 10.1
LOCKOUT -=> PT^ [PT.ENTRY];
IN.CORE ! VALID ! ALTERED !> PT^ [PT.ENTRY];
@BOX 11.1
MAKE (LOGICAL, WORDS.PER.PAGE, BYTE (MAP.ADDRESS (PAGE.ADDR, 0)))
   => CLEAR.PAGE;
FOR TEMP < WORDS.PER.PAGE DO
   0 => CLEAR.PAGE^ [TEMP];
OD
@BOX 12.1
FOR TEMP < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [TEMP] = PT.ENTRY
      OR PTE.PER.PAGE > HFP [TEMP] > PT.ENTRY THEN
      0 => HFP [TEMP];
      SYS01.FREE (BIT (TEMP), SYS01.PAGING.HALT);
   FI
OD
@BOX 13.1
END
@BOX 17.1
IF SYS03.REQUEST.DRUM.TRANSFER (DISC.NUMBER, PAGE.PNO,
   BSA^ [PAGE.PNO], 0, 1, 0) /= 0
@BOX 18.1
IF BLOCK < 0 THEN
   SET.SST.PT.0 (SST.PT.0);
FI
LOCKOUT -=> PT^ [PT.ENTRY];
IN.CORE ! VALID !> PT^ [PT.ENTRY];
@BOX 19.1
IF BLOCK < 0 THEN
   SET.SST.PT.0 (SST.PT.0);
FI
-1 => PAGE.ADDR;
LOCKOUT -=> PT^ [PT.ENTRY];
0 => BSA^ [PAGE.PNO];
SYS02.RELEASE.PAGE (PAGE.PNO, 1);
@BOX 20.1
1 +> NEW.PAGES OF STATS^;
@BOX 21.1
1 +> PAGES.IN OF STATS^;
@END

@TITLE SYSINT14.14.2(3,10)
@COL 1S-3T-2T-6T-7R-5F

@FLOW 1-3OK-2NO-6OK-7-5
@FLOW 2YES-5
@FLOW 3FAIL-5
@FLOW 6FAIL-5

@BOX 1.0
GET PAGE TABLE
@BOX 2.0
X SEGMENT BLOCK?
@BOX 3.0
GET PAGE TABLE IN CORE
@BOX 5.0
END
@BOX 6.0
GET SECONDARY PAGE TABLE IN CORE
@BOX 7.0
FILL IN SPARE SEGMENT TABLE
ENTRY
@BOX 1.1
::GET PAGE TABLE
BEGIN
INTEGER PT.OFFSET, PT.BLOCK, X.ENTRY;
@BOX 2.1
IF BLOCK >= 0
@BOX 3.1
IF SST.PT [SYS.SEG] & VALID = 0 OR
   SST.PT [SYS.SEG] & PAGE.STATUS /= IN.CORE THEN
   SYS.SEG / PTE.PER.PAGE => PT.OFFSET;
   GET.SYS.BLOCK (PT.SEG + PT.OFFSET, -1, PT.OFFSET * PTE.PER.PAGE
      -: SYS.SEG => PT.BLOCK) => PT.ADDR ->> PAGE.SHIFT => PT.PNO;
   IF PT.ADDR >= 0 THEN
      BSA^ [PT.PNO] => DRUM.ADDR OF SST [SYS.SEG];
   FI
ELSE
   SST.PT [SYS.SEG] & PAGE.FIELD => PT.PNO <<- PAGE.SHIFT
      => PT.ADDR;
   1 +> LOCKIN^ [PT.PNO];
FI
SYS.SEG * PTE.PER.PAGE + BLOCK => PT.ENTRY;
IF PT.ADDR < 0
@BOX 5.1
END
@BOX 6.1
1 -> LOCKIN^ [PT.PNO];
-1 - BLOCK / PTE.PER.PAGE => PT.BLOCK;
IF GET.SYS.BLOCK (-1, SYS.SEG, PT.BLOCK) => PT.ADDR < 0
@BOX 7.1
PT.ADDR ->> PAGE.SHIFT => PT.PNO;
SST.PT [0] => SST.PT.0;
-1 - BLOCK - (PT.BLOCK * PTE.PER.PAGE) => PT.ENTRY;
@END

@TITLE SYSINT14.15(3,10)

@COL 1S-2R-3T-4T-5R-6F
@COL 7R

@ROW 7-5

@FLOW 1-2-3NO-4NO-5-6
@FLOW 3YES-6
@FLOW 4YES-7-6

@BOX 1.0
DISC STATUS (DISC NUMBER, STATE)
@BOX 2.0
NOTE NEW DISC STATE
@BOX 3.0
DISC ON LINE?
@BOX 4.0
DISC ZERO OFF LINE?
@BOX 5.0
INVALIDATE ALL SEGMENTS ON
THIS DISC
@BOX 6.0
END
@BOX 7.0
SYSTEM ERROR
[SYS12]
@BOX 1.1
PROC DISC.STATUS (DISC.NUMBER, STATE);
INTEGER SSN;
@BOX 2.1
IF STATE /= 0 THEN
   DISC.VALID => DISC.STATE [DISC.NUMBER];
ELSE
   0 => DISC.STATE [DISC.NUMBER];
FI
@BOX 3.1
IF STATE /= 0
@BOX 4.1
IF DISC.NUMBER = 0
@BOX 5.1
FOR SSN < NO.OF.SYS.SEGS DO
   IF DISC.NO OF SST [SSN] = DISC.NUMBER THEN
      -1 => DISC.NO OF SST [SSN];
   FI
OD
@BOX 6.1
END
@BOX 7.1
SYS12.SYSTEM.ERROR (SYSTEM.DISC.OFF);
@END
@TITLE SYSINT14.17(3,10)

@COL 1S-13T-9R-10R-11R-12R-2F

@FLOW 1-13VALID-9-10-11-12-2
@FLOW 13INVALID-2

@BOX 1.0
WRITE PAGE TO DRUM (PAGE, PT ENTRY)
@BOX 2.0
END
@BOX 9.0
ALLOCATE SPACE ON DRUM
IF NECESSARY
@BOX 10.0
MARK PAGE LOCKED OUT
@BOX 11.0
REQUEST DRUM TRANSFER
[SYS03]
@BOX 12.0
REMOVE LOCKOUT STATUS ON THE PAGE
@BOX 13.0
DISC INVALID?
@BOX 1.1
PROC WRITE.PAGE.TO.DRUM (PAGE, PT.ENTRY);
INTEGER DISC.NUMBER, DISC.SEG, I, TEMP;
LOGICAL32 SST.PT.0;
SELECT CMT^ [PAGE];
@BOX 2.1
END
@BOX 9.1
IF BSA^ [PAGE] = 0 THEN
   SYS03.INT.ALLOCATE.DRUM.BLOCK (DISC.NUMBER, 1) => BSA^ [PAGE];
FI
@BOX 10.1
IN.CORE -=> PT^ [PT.ENTRY];
LOCKOUT !> PT^ [PT.ENTRY];
@BOX 11.1
SST.PT [0] => SST.PT.0;
WHILE SYS03.REQUEST.DRUM.TRANSFER (DISC.NUMBER, PAGE, BSA^ [PAGE], 0, 1, 1) /= 0
   AND DISC.NO OF SST [DISC.SEG] => DISC.NUMBER >= 0 DO
   SYS03.INT.ALLOCATE.DRUM.BLOCK (DISC.NUMBER, 1) => BSA^ [PAGE];
OD
@BOX 12.1
SET.SST.PT.0 (SST.PT.0);
LOCKOUT ! ALTERED -=> PT^ [PT.ENTRY];
IN.CORE !> PT^ [PT.ENTRY];
FOR TEMP < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [TEMP] = PT.ENTRY
      OR PTE.PER.PAGE > HFP [TEMP] > PT.ENTRY THEN
      0 => HFP [TEMP];
      SYS01.FREE (BIT (TEMP), SYS01.PAGING.HALT);
   FI
OD
@BOX 13.1
DISC.NO OF SST [SSN => DISC.SEG] => DISC.NUMBER;
FOR I < NO.OF.SYS.SEGS / PTE.PER.PAGE DO
   IF SSN = SSN OF CST [PT.SEG - FIRST.COMMON.SEG + I] THEN
      DISC.NO OF SST [I * PTE.PER.PAGE + BLOCK => DISC.SEG]
         => DISC.NUMBER;
   FI
OD
IF DISC.NUMBER < 0
@END

@TITLE SYSINT14.18(3,10)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
SET SST PT 0
@BOX 2.0
SET ZEROTH ENTRY OF SST PT
@BOX 3.0
RESET PAGING REGSITERS
@BOX 4.0
END
@BOX 1.1
PROC SET.SST.PT.0 (SST.PT.0);
@BOX 2.1
SST.PT.0 => SST.PT [0];
@BOX 3.1
PT.SEG => V.RESET.SEG;
0 => V.RESET.BLK;
RESET.SEG.BLOCK => V.RESET.STATUS;
@BOX 4.1
END
@END

@TITLE SYSCMD14.1(3,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
CREATE SEGMENT (SEG NO, SIZE)
@BOX 2.0
CREATE SEGMENT ON SYSTEM DISC
[SYSCMD14.21]
@BOX 3.0
END
@BOX 1.1
PROC CREATE.SEGMENT (SEG.NO, REQ.SIZE);
@BOX 2.1
CREATE.DISC.SEGMENT (SEG.NO, REQ.SIZE, 0);
@BOX 3.1
END
@END
@TITLE SYSCMD14.2(3,10)

@COL 1S-2T-3T-7R-4R-5R-8F
@COL 20N-9R-30N-10R-12N

@ROW 2-20
@ROW 3-30

@FLOW 1-2NO-3NO-7-4-5-8
@FLOW 2YES-20-9-12-8
@FLOW 3YES-30-10-12

@BOX 1.0
RELEASE SEGMENT (SEG NO)
@BOX 2.0
ILLEGAL SEGMENT NUMBER
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
RELEASE SYSTEM SEGMENT
[SYSCMD14.10]
@BOX 5.0
ENTER INTERRUPT LEVEL
TO RESET PAGING REGISTERS
[SYSINT14.8]
@BOX 7.0
CLEAR LOCAL SEGMENT TABLE ENTRY
@BOX 8.0
END
@BOX 9.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 10.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 1.1
PROC RELEASE.SEGMENT (SEG.NO);
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
INTEGER SYS.SEG;
0 => PW0;
@BOX 2.1
IF SEG.NO =< 0 OR SEG.NO = V.STACK.SEG
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^
IF ACCESS = 0
@BOX 4.1
RELEASE.SYS.SEGMENT (SYS.SEG);
@BOX 5.1
IF SEG.NO < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG.NO, RESET.SEG);
FI
@BOX 7.1
SSN => SYS.SEG;
0 => LST.ENTRY;
@BOX 8.1
END
@BOX 9.1
-3 => PW0;
@BOX 10.1
-6 => PW0;
@END
@TITLE SYSCMD14.3(3,10)
@COL 1S-5T-7T-3T-9T-25T-26T-12R-27R-15R-22N-16F
@COL 6N-18R-8N-19R-4N-17R-21N-20R-24N

@ROW 3-4
@ROW 5-6
@ROW 7-8
@ROW 9-21
@ROW 22-24

@FLOW 1-5NO-7NO-3NO-9NO-25-26N-12-27-15-22-16
@FLOW 25-15
@FLOW 26YES-27
@FLOW 3YES-4-17-24-22
@FLOW 5YES-6-18-24
@FLOW 7YES-8-19-24
@FLOW 9YES-21-20-24

@BOX 1.0
CHANGE SIZE (SEG NO, SIZE)
@BOX 3.0
IS NEW SIZE ZERO?
@BOX 5.0
IS SEGMENT NUMBER ILLEGAL?
@BOX 7.0
IS SEGMENT UNDEFINED?
@BOX 9.0
IS SIZE ILLEGAL?
@BOX 12.0
ENTER INTERRUPT LEVEL
TO RELEASE CORE PAGES
[SYSINT14.7]
@BOX 13.0
REQUIRED SIZE ILLEGAL?
@BOX 14.0
RETURN FAULT STATUS -4
(ILLEGAL SEGMENT SIZE REQUESTED)
@BOX 15.0
RETURN NEW SIZE
@BOX 16.0
END
@BOX 17.0
RELEASE SEGMENT
@BOX 18.0
RETURN FALSE STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 19.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 20.0
RETURN FAULT STATUS -4
(ILLEGAL SIZE REQUESTED)
@BOX 25.0
NO CHANGE IN SIZE?
@BOX 26.0
INCREASE IN SIZE?
@BOX 27.0
INSERT NEW SIZE IN
SYSTEM SEGMENT TABLE
AND RESET PAGING REGISTERS
@BOX 1.1
PROC CHANGE.SIZE (SEG.NO, REQ.SIZE);
INTEGER PAGE.PNO, SEGMENT.SIZE, DISC.NUMBER;
ADDR NEW.SIZE, TEMP;
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
0 => PW0;
@BOX 3.1
SELECT SST [SSN];
IF NEW.SIZE =< 0
@BOX 5.1
IF SEG.NO =< 0 OR SEG.NO = V.STACK.SEG
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 7.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   X.SEG.SIZE => SEGMENT.SIZE;
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
   REQ.SIZE => NEW.SIZE;
ELSE
   SEG.SIZE ->> PAGE.SHIFT => TEMP => SEGMENT.SIZE;
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
   REQ.SIZE - 1 ->> PAGE.SHIFT + 1 => REQ.SIZE;
   REQ.SIZE <<- PAGE.SHIFT => NEW.SIZE;
FI
SELECT SEG.TABLE^;
IF ACCESS = 0
@BOX 9.1
IF REQ.SIZE > SEGMENT.SIZE
@BOX 12.1
SYS13.ENTER.INT.LEVEL (^RELEASE.PAGES, SSN, REQ.SIZE);
@BOX 13.1
IF REQ.SIZE > LIMIT
@BOX 14.1
-4 => PW0;
@BOX 15.1
NEW.SIZE => PW1;
@BOX 16.1
END
@BOX 17.1
RELEASE.SEGMENT (SEG.NO);
@BOX 19.1
-6 => PW0;
@BOX 18.1
-3 => PW0;
@BOX 20.1
-4 => PW0;
@BOX 25.1
IF REQ.SIZE = LIMIT
@BOX 26.1
IF REQ.SIZE > LIMIT
@BOX 27.1
REQ.SIZE => LIMIT;
IF SEG.NO < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG.NO, RESET.SEG);
FI
@END
@TITLE SYSCMD14.4(3,10)
@COL 1S-2T-20N-3T-30N-4T-6R-5R-7F
@COL 8R-9R-10R-12N

@ROW 20-8
@ROW 30-9
@ROW 6-10
@ROW 5-12


@FLOW 1-2NO-20-3NO-30-4NO-6-5-7
@FLOW 2YES-8-12-7
@FLOW 3YES-9-12-7
@FLOW 4YES-10-12

@BOX 1.0
CHANGE ACCESS (SEG NO, REQD ACCESS)
@BOX 2.0
IS SEGMENT NUMBER ILLEGAL?
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
IS NEW ACCESS PERMITTED?
@BOX 5.0
ENTER INTERRUPT LEVEL
TO RESET PAGING REGISTERS
[SYSINT14.8]
@BOX 6.0
CHANGE ACCESS FIELD OF LST ENTRY
@BOX 7.0
END
@BOX 8.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 9.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 10.0
RETURN FAULT STATUS -5
(ILLEGAL ACCESS REQUESTED)
@BOX 1.1
PROC CHANGE.ACCESS (SEG.NO, REQD.ACCESS);
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
0 => PW0;
@BOX 2.1
IF SEG.NO =< 0 OR SEG.NO = V.STACK.SEG
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^;
IF ACCESS = 0
@BOX 4.1
IF ACCESS & %10 = 0
    AND %1F &> REQD.ACCESS -= ACCESS & REQD.ACCESS /= 0
@BOX 5.1
IF SEG.NO < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG.NO, RESET.SEG);
FI
@BOX 6.1
ACCESS & %E0 ! REQD.ACCESS => ACCESS;
@BOX 7.1
END
@BOX 8.1
-3 => PW0;
@BOX 9.1
-6 => PW0;
@BOX 10.1
-5 => PW0;
@END
@TITLE SYSCMD14.5(3,10)
@COL 1S-2T-3R-7R-4R-5F
@COL 6R

@ROW 7-6

@FLOW 1-2NO-3-7-4-5
@FLOW 2YES-6-5

@BOX 1.0
INTERCHANGE (SEG1, SEG2)
@BOX 2.0
ARE SEGMENT NUMBERS ILLEGAL?
@BOX 3.0
SET POINTER TO THE
CORRECT SEGMENT TABLE
@BOX 4.0
ENTER INTERRUPT LEVEL
TO RESET PAGING REGISTERS
[SYSINT14.8]
@BOX 5.0
END
@BOX 6.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBERS)
@BOX 1.1
PROC INTERCHANGE (SEG1, SEG2);
ADDR [LST.TYPE] SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
LST.TYPE TEMP;
0 => PW0;
@BOX 2.1
IF SEG1 =< 0 OR SEG2 =< 0
   OR SEG1 = V.STACK.SEG OR SEG2 = V.STACK.SEG
   OR SEG1 < FIRST.X.SEG >= NO.OF.LOCAL.SEGS
   OR SEG2 < FIRST.X.SEG >= NO.OF.LOCAL.SEGS
   OR SEG1 >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG2 >= FIRST.X.SEG + NO.OF.X.SEGS
   OR NO.OF.LOCAL.SEGS > SEG1 =< SEG2
   OR NO.OF.LOCAL.SEGS > SEG2 =< SEG1
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
IF SEG1 >= FIRST.X.SEG THEN
   ^XST => SEG.TABLE;
   SEG1 - FIRST.X.SEG => SEG1;
   SEG2 - FIRST.X.SEG => SEG2;
ELSE
   ^LST => SEG.TABLE;
FI
@BOX 7.1
LST.ENTRY OF SEG.TABLE^ [SEG1] => LST.ENTRY OF TEMP;
LST.ENTRY OF SEG.TABLE^ [SEG2] => LST.ENTRY OF SEG.TABLE^ [SEG1];
LST.ENTRY OF TEMP => LST.ENTRY OF SEG.TABLE^ [SEG2];
@BOX 4.1
IF SEG1 < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG1, RESET.SEG);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG2, RESET.SEG);
FI
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@END
@TITLE SYSCMD14.6(3,10)
@COL 1S-2T-20N-3T-30N-4R-5F
@COL 6R-7R-8N

@ROW 20-6
@ROW 30-7
@ROW 4-8

@FLOW 1-2NO-20-3NO-30-4-5
@FLOW 2YES-6-8-5
@FLOW 3YES-7-8

@BOX 1.0
READ SEGMENT STATUS (SEG NO)
@BOX 2.0
IS SEGMENT NUMBER ILLEGAL?
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
RETURN STATUS OF SEGMENT
@BOX 5.0
END
@BOX 6.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 7.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 1.1
PROC READ.SEGMENT.STATUS (SEG.NO);
ADDR SEG.VARS C.SEG.VARS;
ADDR LST.TYPE SEG.TABLE;
0 => PW0;
@BOX 2.1
IF SEG.NO < 0
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^;
IF ACCESS = 0
@BOX 4.1
ACCESS & %1F => PW2;
LIMIT OF SST [SSN] => PW1;
IF SEG.NO < NO.OF.LOCAL.SEGS THEN
   PW1 <<- PAGE.SHIFT => PW1;
ELSE
   %60 !> PW2;
FI
DISC.NO OF SST [SSN] => PW3;
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@BOX 7.1
-6 => PW0;
@END
@TITLE SYSCMD14.7(3,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
CREATE X SEGMENT (SIZE)
@BOX 2.0
CREATE SEGMENT ON SYSTEM DISC
[SYSCMD14.22]
@BOX 3.0
END
@BOX 1.1
PROC CREATE.X.SEGMENT (REQ.SIZE);
@BOX 2.1
CREATE.DISC.X.SEGMENT (REQ.SIZE, 0);
@BOX 3.1
END
@END


@TITLE SYSCMD14.8(3,10)

@COL 1S-16R-2R-3T-4T-13R-5R-14R-12N-6F
@COL 7N-8R-9N-10R-11N

@ROW 3-7
@ROW 4-9
@ROW 12-11

@FLOW 1-16-2-3NO-4NO-13-5-14-12-6
@FLOW 3YES-7-8-11-12
@FLOW 4YES-9-10-11

@BOX 1.0
ASSIGN USER SEG (SYS SEG, USER SEG, REQ ACCESS)
@BOX 2.0
LOOK FOR SUITABLE LOCAL SEGMENT
@BOX 3.0
NO SEGMENTS AVAILABLE?
@BOX 4.0
SPECIFIED SEGMENT ALREADY IN USE?
@BOX 5.0
ALLOCATE LOCAL SEGMENT
TABLE ENTRY
@BOX 6.0
END
@BOX 8.0
RETURN FAULT STATUS -2
(NO SEGMENT AVAILABLE)
@BOX 10.0
RETURN FAULT STATUS -1
(SEGMENT ALREADY EXISTS)
@BOX 13.0
CHECKIN
[SYS01]
@BOX 14.0
CHECKOUT
[SYS01]
@BOX 16.0
SET POINTER TO THE
CORRECT SEGMENT TABLE
@BOX 1.1
PROC ASSIGN.USER.SEGMENT (SYS.SEG, USER.SEG, REQ.ACCESS);
INTEGER NO.OF.SEGS;
ADDR [LST.TYPE] SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
@BOX 2.1
IF USER.SEG < 0 OR USER.SEG >= NO.OF.SEGS THEN
   -1 => USER.SEG;
   WHILE 1 +> USER.SEG < NO.OF.SEGS
      AND ACCESS OF SEG.TABLE^ [USER.SEG] /= 0 DO OD
FI
@BOX 3.1
IF USER.SEG >= NO.OF.SEGS
@BOX 4.1
IF ACCESS OF SEG.TABLE^ [USER.SEG] /= 0
@BOX 5.1
1 +> COUNT OF SST [SYS.SEG];
SYS.SEG => SSN OF SEG.TABLE^ [USER.SEG];
%1F &> REQ.ACCESS ! DEFINED => ACCESS OF SEG.TABLE^ [USER.SEG];
SELECT SST [SYS.SEG];
IF STATUS & X.SEG /= 0 THEN
   USER.SEG + FIRST.X.SEG => PW1;
   LIMIT => PW2;
   %60 ! REQ.ACCESS => PW3;
ELSE
   USER.SEG => PW1;
   LIMIT <<- PAGE.SHIFT => PW2;
   REQ.ACCESS => PW3;
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, USER.SEG, RESET.SEG);
FI
@BOX 6.1
END
@BOX 8.1
-2 => PW0;
@BOX 10.1
-1 => PW0;
@BOX 13.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 14.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 16.1
IF STATUS OF SST [SYS.SEG] & X.SEG /= 0 THEN
   ^XST => SEG.TABLE;
   NO.OF.X.SEGS => NO.OF.SEGS;
   -1 => USER.SEG;
ELSE
   ^LST => SEG.TABLE;
   NO.OF.LOCAL.SEGS => NO.OF.SEGS;
FI
@END


@TITLE SYSCMD14.9(3,10)
@COL 1S-2T-4T-9R-12F
@COL 16N-13R-17N-14R-15N

@ROW 2-16
@ROW 4-17

@FLOW 1-2NO-4NO-9-12
@FLOW 2YES-16-13-15-12
@FLOW 4YES-17-14-15

@BOX 1.0
ASSIGN SYS SEGMENT (USER SEG)
@BOX 2.0
IS SEGMENT NUMBER ILLEGAL?
@BOX 4.0
IS SEGMENT UNDEFINED?
@BOX 9.0
REMOVE SEGMENT FROM
LOCAL SEGMENT TABLE
@BOX 12.0
END
@BOX 13.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 14.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 1.1
PROC ASSIGN.SYS.SEGMENT (USER.SEG);
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
@BOX 2.1
IF USER.SEG =< 0 OR USER.SEG = V.STACK.SEG
   OR USER.SEG >= FIRST.X.SEG + NO.OF.X.SEGS
   OR USER.SEG >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 4.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF USER.SEG >= FIRST.X.SEG THEN
   ^XST [USER.SEG - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [USER.SEG] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^;
IF ACCESS = 0
@BOX 9.1
SSN => ASSIGN.SYS.SEGMENT;
0 => LST.ENTRY;
IF USER.SEG < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, USER.SEG, RESET.SEG);
FI
@BOX 12.1
END
@BOX 13.1
-3 => PW0;
@BOX 14.1
-6 => PW0;
@END
@TITLE SYSCMD14.10(3,10)
@COL 1S-6R-10T-2R-8T-9R-4R-7R-5F

@FLOW 1-6-10NO-2-8NO-9-4-7-5
@FLOW 10YES-7
@FLOW 8YES-4
@BOX 1.0
RELEASE SYS SEGMENT (SSN)
@BOX 2.0
ENTER INTERRUPT LEVEL
TO RELEASE CORE PAGES
[SYSINT14.7]
@BOX 4.0
LINK SYSTEM SEGMENT TABLE ENTRY
TO CHAIN OF FREE ENTRIES
@BOX 5.0
END
@BOX 6.0
CHECKIN
[SYS01]
@BOX 7.0
CHECKOUT
[SYS01]
@BOX 8.0
IS SEGMENT NOT PROTECTED?
@BOX 9.0
CLOSE FILE
[SYS16]
@BOX 10.0
IS SEGMENT SHARED?
@BOX 1.1
PROC RELEASE.SYS.SEGMENT (SSN);
INTEGER DISC.NUMBER;
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^RELEASE.PAGES, SSN, 0);
@BOX 4.1
FREE.SST => SST.LINK;
SSN => FREE.SST;
@BOX 5.1
END
@BOX 6.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 7.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 8.1
IF STATUS & PROTECTED = 0
@BOX 9.1
SYS16.CLOSE.FILE (SSN);
@BOX 10.1
SELECT SST [SSN];
IF 1 -> COUNT > 0
@END
@TITLE SYSCMD14.11(3,10)
@COL 1S-3R-4R-5F
@FLOW 1-3-4-5
@BOX 1.0
INIT SEGS (SEG VARS, SPN, STORE LIMIT)
@BOX 3.0
INITIALISE LOCAL AND
MAPPED SEGMENT TABLES
@BOX 4.0
CREATE A SEGMENT ZERO
@BOX 5.0
END
@BOX 1.1
PROC INIT.SEGS (PROC.SEG.VARS, SPN, STORE.LIMIT);
INTEGER SEG, D.ADDR, SYS.SEG;
ADDR TEMP;
SELECT PROC.SEG.VARS^;
@BOX 3.1
FOR SEG < NO.OF.LOCAL.SEGS DO
   0 => LST.ENTRY OF LST [SEG];
OD
FOR SEG < NO.OF.X.SEGS DO
   0 => LST.ENTRY OF XST [SEG];
OD
@BOX 4.1
ALLOCATE.SYS.SEG (0, 0, SEG.SIZE ->> PAGE.SHIFT => TEMP, 0, 0) => SYS.SEG;
IF PW0 = 0 THEN
   1 => COUNT OF SST [SYS.SEG];
   %9E => ACCESS OF LST [0];
   SYS.SEG => SSN OF LST [0];
FI
@BOX 5.1
END
@END
@TITLE SYSCMD14.12(3,10)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
TINI SEGS (SEG VARS)
@BOX 2.0
RELEASE ALLOCATED X SEGMENTS
@BOX 3.0
RELEASE ALLOCATED SEGMENTS
@BOX 4.0
END
@BOX 1.1
PROC TINI.SEGS (PROC.SEG.VARS);
INTEGER SEG;
SELECT PROC.SEG.VARS^;
@BOX 2.1
FOR SEG < NO.OF.X.SEGS DO
   IF ACCESS OF XST [SEG] /= 0 THEN
      RELEASE.SYS.SEGMENT (SSN OF XST [SEG]);
      0 => LST.ENTRY OF XST [SEG];
   FI
OD
@BOX 3.1
FOR SEG < NO.OF.LOCAL.SEGS DO
   IF ACCESS OF LST [SEG] /= 0 THEN
      RELEASE.SYS.SEGMENT (SSN OF LST [SEG]);
      0 => LST.ENTRY OF LST [SEG];
   FI
OD
@BOX 4.1
END
@END



@TITLE SYSCMD14.13(3,10)

@COL 9R
@COL 1S-8T-2R-3T-4R-5R-6F
@COL 7R

@ROW 9-4-7

@FLOW 1-8VALID-2-3NO-4-5-6
@FLOW 3YES-7-5
@FLOW 8INVALID-9-6

@BOX 1.0
ALLOCATE SYS SEG (BACKING STORE ADDR, DISC NUMBER, MAX SIZE, CURRENT SIZE, STATU
S)
@BOX 2.0
CHECKIN
[SYS01]
@BOX 3.0
NO FREE SYSTEM SEGMENT TABLE ENTRIES?
@BOX 4.0
UNLINK AN ENTRY AND INITIALISE IT
@BOX 5.0
CHECKOUT
[SYS01]
@BOX 6.0
END
@BOX 7.0
RETURN FAULT STATUS -7
(INSUFFICIENT RESOURCES)
@BOX 8.0
DISC INVALID?
@BOX 9.0
RETURN FAULT STATUS -9
(INVALID DISC NUMBER)
@BOX 1.1
PROC ALLOCATE.SYS.SEG (BACKING.STORE.ADDR, DISC.NUMBER, MAX.SIZE,
   CURR.SIZE, SEG.STATUS);
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 3.1
IF FREE.SST < 0
@BOX 4.1
SELECT SST [FREE.SST];
FREE.SST => ALLOCATE.SYS.SEG;
IF BACKING.STORE.ADDR /= 0 THEN
   ON.DRUM ! BACKING.STORE.ADDR => SST.PT [FREE.SST];
ELSE
   0 => SST.PT [FREE.SST];
FI
SST.LINK => FREE.SST;
BACKING.STORE.ADDR => DRUM.ADDR;
DISC.NUMBER => DISC.NO;
IF DISC.STATE [DISC.NUMBER] & DISC.VALID = 0 THEN
   -1 => DISC.NO;
FI
MAX.SIZE => LIMIT;
SEG.STATUS => STATUS;
0 => COUNT;
@BOX 5.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 6.1
END
@BOX 7.1
-7 => PW0;
@BOX 8.1
IF DISC.STATE [DISC.NUMBER] & DISC.VALID = 0
@BOX 9.1
-9 => PW0;
@END



@TITLE SYSCMD14.14(3,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MAP (LOCAL SEG, MAPPED SEG, COUNT)
@BOX 2.0
RETURN SEGMENT NUMBER
CURRENTLY MAPPED
@BOX 3.0
END
@BOX 1.1
PROC MAP (LSN, MSN, COUNT);
0 => PW0;
@BOX 2.1
IF LSN >= 0 THEN
   LSN => PW1 => PW6;
ELSE
   MSN => PW1 => PW6;
FI
@BOX 3.1
END
@END
@TITLE SYSCMD14.15(3,10)

@COL 1S-11T-12R-2T-3T-4R-15R-5F
@COL 13N-14R-6N-7R-8N-9R-10N

@ROW 2-6
@ROW 3-8
@ROW 12-14

@FLOW 1-11-12-2NO-3NO-4-15-5
@FLOW 2YES-6-7-10-5
@FLOW 3YES-8-9-10-5
@FLOW 11YES-14-10

@BOX 1.0
COPY BLOCK (SEG1, BLK1, SEG2, BLK2)
@BOX 2.0
ARE SEGMENTS UNDEFINED?
@BOX 3.0
ADDRESSES OUT OF RANGE?
@BOX 4.0
ENTER INTERRUPT LEVEL
TO COPY A BLOCK
[SYSINT14.10]
@BOX 5.0
END
@BOX 7.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 9.0
RETURN FAULT STATUS -8
(ILLEGAL ADDRESS)
@BOX 11.0
ARE SEGMENT NUMBERS ILLEGAL?
@BOX 12.0
SET POINTER TO THE CORRECT
SEGMENT TABLE
@BOX 14.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 15.0
RESET PAGING REGISTERS FOR
LOCAL SEGS
[SYSINT14.8]
@BOX 1.1
PROC COPY.BLOCK (SEG1, BLK1, SEG2, BLK2);
INTEGER SSN1, SSN2;
ADDR SEG.VARS C.SEG.VARS;
ADDR LST.TYPE SEG.TABLE1, SEG.TABLE2;
0 => PW0;
@BOX 2.1
IF ACCESS OF SEG.TABLE1^ & %84 -= %84 /= 0
   OR ACCESS OF SEG.TABLE2^ & %82 -= %82 /= 0
@BOX 3.1
IF BLK1 < 0 OR BLK1 >= LIMIT OF SST [SSN OF SEG.TABLE1^ => SSN1]
   OR BLK2 < 0 OR BLK2 >= LIMIT OF SST [SSN OF SEG.TABLE2^ => SSN2]
@BOX 4.1
SYS13.ENTER.INT.LEVEL (^COPY, SSN1 * X.SEG.SIZE + BLK1,
   SSN2 * X.SEG.SIZE + BLK2);
IF SYS13.PROC.RESULT [SYS13.CURRENT.SPN] /= 0 THEN
   SYS13.ENTER.INT.LEVEL (^SYS10.SET.VM.INT, 0, PAGE.UNAVAILABLE);
FI
@BOX 5.1
END
@BOX 7.1
-6 => PW0;
@BOX 9.1
-8 => PW0;
@BOX 11.1
IF SEG1 < 0 OR SEG2 < 0
   OR SEG1 < FIRST.X.SEG >= NO.OF.LOCAL.SEGS
   OR SEG2 < FIRST.X.SEG >= NO.OF.LOCAL.SEGS
   OR SEG1 >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG2 >= FIRST.X.SEG + NO.OF.X.SEGS
@BOX 12.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1 , 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
IF SEG1 >= FIRST.X.SEG THEN
   ^XST [SEG1 - FIRST.X.SEG] => SEG.TABLE1;
ELSE
   ^LST [SEG1] => SEG.TABLE1;
FI
IF SEG2 >= FIRST.X.SEG THEN
   ^XST [SEG2 - FIRST.X.SEG] => SEG.TABLE2;
ELSE
   ^LST [SEG2] => SEG.TABLE2;
FI
@BOX 14.1
-3 => PW0;
@BOX 15.1
IF SEG1 < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG1,
      RESET.SEG.BLOCK);
FI
IF SEG2 < NO.OF.LOCAL.SEGS THEN
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG2,
      RESET.SEG.BLOCK);
FI
@END


@TITLE SYSCMD14.16(3,10)

@COL 1S-2T-3T-7R-8F
@COL 20N-9R-30N-10R-12N

@ROW 2-20
@ROW 3-30

@FLOW 1-2NO-3NO-7-8
@FLOW 2YES-20-9-12-8
@FLOW 3YES-30-10-12

@BOX 1.0
SECURE SEGMENT (SEG NO)
@BOX 2.0
ILLEGAL SEGMENT NUMBER
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 7.0
ENTER INTERRUPT LEVEL
TO SECURE PAGES OF SEGMENT
[SYSINT14.11]
@BOX 8.0
END
@BOX 9.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 10.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 1.1
PROC SECURE.SEGMENT (SEG.NO);
ADDR SEG.VARS C.SEG.VARS;
ADDR LST.TYPE SEG.TABLE;
0 => PW0;
@BOX 2.1
IF SEG.NO =< 0 OR SEG.NO = V.STACK.SEG
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^
IF ACCESS = 0
@BOX 7.1
SYS13.ENTER.INT.LEVEL (^SECURE.PAGES, SSN, 0);
@BOX 8.1
END
@BOX 9.1
-3 => PW0;
@BOX 10.1
-6 => PW0;
@END
@TITLE SYSCMD14.17(3,10)
@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
CMD MAP (LOCAL SEG, MAPPED SEG)
@BOX 2.0
RETURN SEGMENT NUMBER
CURRENTLY MAPPED
@BOX 3.0
END
@BOX 1.1
PROC CMD.MAP (LSN, MSN);
@BOX 2.1
IF LSN >= 0 THEN
   LSN => PW1 => PW6;
ELSE
   MSN => PW1 => PW6;
FI
@BOX 3.1
END
@END
@TITLE SYSCMD14.18(3,10)



@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
PROTECT (SSN, VALUE)
@BOX 2.0
SET SPECIFIED PROTECTION
FOR SYSTEM SEGMENT
@BOX 3.0
END
@BOX 1.1
PROC PROTECT (SSN, VALUE);
@BOX 2.1
PROTECTED !> STATUS OF SST [SSN];
IF VALUE = 0 THEN
   PROTECTED -=> STATUS OF SST [SSN];
FI
@BOX 3.1
END
@END

@TITLE SYSCMD14.19(3,10)
@COL 1S-2T-20N-3T-30N-4R-5F
@COL 6R-7R-8N

@ROW 20-6
@ROW 30-7
@ROW 4-8

@FLOW 1-2NO-20-3NO-30-4-5
@FLOW 2YES-6-8-5
@FLOW 3YES-7-8

@BOX 1.0
READ SYSTEM SEGMENT STATUS (SEG NO)
@BOX 2.0
IS SEGMENT NUMBER ILLEGAL?
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
RETURN STATUS OF SYSTEM SEGMENT
@BOX 5.0
END
@BOX 6.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 7.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 1.1
PROC READ.SYS.SEGMENT.STATUS (SEG.NO);
ADDR SEG.VARS C.SEG.VARS;
ADDR LST.TYPE SEG.TABLE;
INTEGER SEG.PTR;
0 => PW0;
@BOX 2.1
IF SEG.NO =< 0 OR SEG.NO = V.STACK.SEG
   OR SEG.NO >= FIRST.X.SEG + NO.OF.X.SEGS
   OR SEG.NO >= NO.OF.LOCAL.SEGS < FIRST.X.SEG
@BOX 3.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
IF SEG.NO >= FIRST.X.SEG THEN
   ^XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^LST [SEG.NO] OF C.SEG.VARS^ => SEG.TABLE;
FI
SELECT SEG.TABLE^
IF ACCESS = 0
@BOX 4.1
SELECT SST [SSN];
LIMIT => PW1 => PW4;
DRUM.ADDR => PWW1;
DISC.NO => PW5;
STATUS => PW2;
SSN => PW3;
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@BOX 7.1
-6 => PW0;
@END
@TITLE SYSCMD14.20(3,11)

@COL 1S-2R-3T-4R-5R-6F

@FLOW 1-2-3OK-4-5-6
@FLOW 3FAIL-5

@BOX 1.0
RESERVE SEGMENT (DRUM ADDRESS, DISC NUMBER, DRUM SIZE, STATUS)
@BOX 2.0
RESERVE PAGE TABLE DRUM SPACE
@BOX 3.0
ALLOCATE SYSTEM SEGMENT
AND COPY IN PAGE TABLE
@BOX 4.0
RESERVE DRUM SPACE FOR THE PAGES
@BOX 5.0
RELEASE SYSTEM SEGMENT
@BOX 6.0
END
@BOX 1.1
PROC RESERVE.SEG (D.ADDR, DISC.NUMBER, D.SIZE, STATUS);
INTEGER I, J, SYS.SEG, PT.OFFSET, PT.BLOCK, SSN.0;
ADDR [LOGICAL32] PAGE.TABLE1, PAGE.TABLE2;
ADDR SEG.VARS C.SEG.VARS;
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
@BOX 2.1
SYS03.RESERVE.DRUM.SPACE (DISC.NUMBER, D.ADDR, 1);
@BOX 3.1
IF STATUS & X.SEG /=  0  THEN
   D.SIZE + PTE.PER.PAGE - 1
      / PTE.PER.PAGE =>  D.SIZE;
FI
ALLOCATE.SYS.SEG (D.ADDR, DISC.NUMBER,  D.SIZE, 0, PROTECTED) => SYS.SEG;
SSN OF LST [0] OF C.SEG.VARS^ => SSN.0;
SYS.SEG / PTE.PER.PAGE => PT.OFFSET;
PT.OFFSET * PTE.PER.PAGE -: SYS.SEG => PT.BLOCK;
SYS13.ENTER.INT.LEVEL (^COPY, SSN OF CST [PT.SEG - FIRST.COMMON.SEG + PT.OFFSET]
   * X.SEG.SIZE + PT.BLOCK, SSN.0 * X.SEG.SIZE + RESERVED.BLOCK1);
IF SYS13.PROC.RESULT [SYS13.CURRENT.SPN] /= 0
@BOX 4.1
SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PT.SEG, RESET.SEG);
MAKE (LOGICAL32, PTE.PER.PAGE, RESERVED.BLOCK1 <<- PAGE.SHIFT) => PAGE.TABLE1;
MAKE (LOGICAL32, PTE.PER.PAGE, RESERVED.BLOCK2 <<- PAGE.SHIFT) => PAGE.TABLE2;
FOR I < D.SIZE DO
   IF PAGE.TABLE1^ [I] & PAGE.STATUS = ON.DRUM THEN
      SYS03.RESERVE.DRUM.SPACE (DISC.NUMBER, PAGE.TABLE1^ [I] & PAGE.FIELD, 1);
      IF STATUS & X.SEG /= 0 THEN
         SYS13.ENTER.INT.LEVEL (^COPY, SYS.SEG * X.SEG.SIZE + I,
            SSN.0 * X.SEG.SIZE + RESERVED.BLOCK2);
         IF SYS13.PROC.RESULT [SYS13.CURRENT.SPN] = 0 THEN
            FOR J < PTE.PER.PAGE DO
               IF PAGE.TABLE2^ [J] & PAGE.STATUS = ON.DRUM THEN
                  SYS03.RESERVE.DRUM.SPACE (DISC.NUMBER, PAGE.TABLE2^ [J]
                     & PAGE.FIELD, 1);
               ELSE
                  LOOP2: IF PAGE.TABLE2^ [J] & PAGE.STATUS /= 0, -> LOOP2;
               FI
            OD
         FI
      FI
   ELSE
      LOOP1: IF PAGE.TABLE1^ [I] & PAGE.STATUS /= 0, -> LOOP1;
   FI
OD
@BOX 5.1
SYS13.ENTER.INT.LEVEL (^RELEASE.PAGES, SYS.SEG, 0);
FREE.SST => SST.LINK OF SST [SYS.SEG];
SYS.SEG => FREE.SST;
@BOX 6.1
END
@BOX 7.1
IF X.SEG & STATUS /= 0
@BOX 9.1
SYS03.RESERVE.DRUM.SPACE (DISC.NUMBER, D.ADDR, D.SIZE);
@END
@TITLE SYSCMD14.21(3,10)

@COL 1S-2R-4R-5T-6R-3T-12R-13T-7F
@COL 8R

@ROW 8-3

@FLOW 1-2-4-5NO-6-3-12-13NO-7
@FLOW 3FAIL-7
@FLOW 5YES-8-7
@FLOW 13YES-3

@BOX 1.0
CREATE DISC SEGMENT (SEG NO, SIZE, DISC NO.)
@BOX 2.0
COMPUTE TOTAL SIZE REQUIRED
@BOX 3.0
ALLOCATE SYSTEM SEGMENT
[SYSCMD14.13]
@BOX 4.0
SEARCH LOCAL SEGMENT TABLE
FOR SPACE
@BOX 5.0
NO FREE SEGMENTS?
@BOX 6.0
RESET SEGMENT COUNT
@BOX 7.0
END
@BOX 8.0
RETURN FAULT STATUS -2
(NO SEGMENTS AVAILABLE)
@BOX 12.0
INITIALISE LOCAL SEGMENT TABLE ENTRY
@BOX 13.0
MORE SEGMENTS TO ALLOCATE?
@BOX 1.1
PROC CREATE.DISC.SEGMENT (SEG.NO, REQ.SIZE, DISC.NO);
INTEGER SEGS, FIRST.SEG, SST.ENTRY, SEG.COUNT,
   BACKING.STORE.ADDR, NO.OF.BLOCKS;
ADDR TEMP;
ADDR SEG.VARS C.SEG.VARS;
0 => PW0;
@BOX 2.1
1 +> SEGS.CREATED OF STATS^;
IF REQ.SIZE =< 0 THEN
   SEG.SIZE => REQ.SIZE;
FI
REQ.SIZE - 1 ->> SEG.SHIFT + 1 => SEGS;
REQ.SIZE - 1 ->> PAGE.SHIFT + 1 => REQ.SIZE <<- PAGE.SHIFT => PW2;
@BOX 3.1
IF (SEG.SIZE ->> PAGE.SHIFT => TEMP) => NO.OF.BLOCKS > REQ.SIZE THEN
   REQ.SIZE => NO.OF.BLOCKS;
FI
NO.OF.BLOCKS -> REQ.SIZE;
0 => PW0;
ALLOCATE.SYS.SEG (0, DISC.NO, NO.OF.BLOCKS, 0, 0) => SST.ENTRY;
IF PW0 < 0
@BOX 4.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
IF SEG.NO => FIRST.SEG < 0 THEN
   0 => FIRST.SEG;
FI
0 => SEG.COUNT;
WHILE SEG.COUNT < SEGS AND FIRST.SEG + SEGS =< NO.OF.LOCAL.SEGS DO
   IF ACCESS OF LST [FIRST.SEG + SEG.COUNT] = 0 THEN
      1 +> SEG.COUNT;
   ELSE
      IF SEG.NO < 0 THEN
         SEG.COUNT + 1 +> FIRST.SEG;
         0 => SEG.COUNT;
      ELSE
         SEGS + 1 => SEG.COUNT;
      FI
   FI
OD
@BOX 5.1
IF SEG.COUNT /= SEGS
@BOXBOX 6.1
0 => SEG.COUNT;
@BOX 7.1
END
@BOX 8.1
-2 => PW0;
@BOX 12.1
1 => COUNT OF SST [SST.ENTRY];
%9E => ACCESS OF LST [FIRST.SEG + SEG.COUNT];
%1E => PW3;
SST.ENTRY => SSN OF LST [FIRST.SEG + SEG.COUNT];
FIRST.SEG => PW1;
@BOX 13.1
IF 1 +> SEG.COUNT < SEGS
@END
@TITLE SYSCMD14.22(3,10)

@COL 10R
@COL 1S-11T-2R-3T-5T-6R-7F
@COL 9R

@ROW 2-10
@ROW 5-9

@FLOW 1-11NO-2-3-5-6-7
@FLOW 5FAIL-7
@FLOW 3YES-9-7
@FLOW 11YES-10-7

@BOX 1.0
CREATE DISC X SEGMENT (SIZE, DISC NO.)
@BOX 2.0
COMPUTE TOTAL SIZE REQUIRED
@BOX 3.0
FIND A LOCAL SEGMENT TABLE ENTRY
@BOX 5.0
ALLOCATE SYSTEM SEGMENT
[SYS14.13]
@BOX 6.0
INITIALISE LOCAL SEGMENT TABLE ENTRY
@BOX 7.0
END
@BOX 9.0
RETURN FAULT STATUS -2
(NO SEGMENT AVAILABLE)
@BOX 10.0
CREATE NORMAL SEGMENT
@BOX 11.0
IS NORMAL SEGMENT SUFFICIENT?
@BOX 1.1
PROC CREATE.DISC.X.SEGMENT (REQ.SIZE, DISC.NO);
INTEGER D.ADDR, SYS.SEG, SEG.NO;
ADDR REQ.BYTE.SIZE;
ADDR SEG.VARS C.SEG.VARS;
0 => PW0;
@BOX 2.1
1 +> X.SEGS.CREATED OF STATS^;
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
IF REQ.SIZE < 0 OR
   REQ.SIZE > X.SEG.SIZE THEN
   X.SEG.SIZE => REQ.SIZE;
FI
REQ.SIZE => PW2;
@BOX 3.1
-1 => SEG.NO;
WHILE 1 +> SEG.NO < NO.OF.X.SEGS
   AND ACCESS OF XST [SEG.NO] /= 0 DO OD
IF SEG.NO >= NO.OF.X.SEGS
@BOX 5.1
ALLOCATE.SYS.SEG (0, DISC.NO, REQ.SIZE, 0, X.SEG) => SYS.SEG;
IF PW0 < 0
@BOX 6.1
1 => COUNT OF SST [SYS.SEG];
%9E => ACCESS OF XST [SEG.NO];
%7E => PW3;
SYS.SEG => SSN OF XST [SEG.NO];
SEG.NO + FIRST.X.SEG => PW1;
@BOX 7.1
END
@BOX 9.1
-2 => PW0;
@BOX 10.1
CREATE.DISC.SEGMENT (-1, REQ.BYTE.SIZE, DISC.NO);
@BOX 11.1
IF REQ.SIZE <<- PAGE.SHIFT => REQ.BYTE.SIZE =< SEG.SIZE
@END



