@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             SYS141
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS141
~S1~M~OSYS IMPLEMENTATION DESCRIPTION~
~
~M~O~GSection 14  Version 1~G~
~S1~OSection 14.1 Virtual Store Manager (Paged version using PARS)~
~S1~O1. General Description~
~BThis module is responsible for managing the
virtual stores of processes, mapping the virtual stores
on to the real store, and organising the
transfer of pages between core and drum.
This particular version provides a paged segmented virtual store for each proces
s.
The upper half of the virtual store is common to all processes, and the translat
ion
from virtual to real addresses is performed by page address registers (PARs).
~BThis module consists of a page rejection process which is activated
whenever insufficient free space is available in core, a number of command
procedures, which allow a user to manipulate his virtual store,
interrupt level interface procedures, which may be called to lock blocks of the
virtual
store in core and subsequently release them, the store rejection procedure
which is called to trigger the page rejection process, and interrupt routines fo
r servicing virtual
store interrupts (when a virtual address cannot be translated by the
ideal hardware) and validate fail interrupts (generated by a validate instructio
n
to check the access permission associated with a particular virtual address).
~S1~O2. Interfaces
Other modules used~
   Section 2 (Core Manager)~
   Section 3 (Drum Manager)~
   Section 10 (Virtual Machine Interrupts)~
   Section 16 (File Manager)~
   Section 21 (Performance Monitoring)~
Hardware registers used~
   V.NEQ.ACCESS~
   V.VAL.ACCESS~
   V.NEQ.SEG~
   V.NEQ.BLK~
   V.PAR~
   V.PAR.NO~
   V.SEARCH.PROC~
   V.SEARCH.SEG~
   V.SEARCH.BLK~
   V.SEARCH.MASK~
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~
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)~
   CHANGE.X.SIZE (SEG NO, NEW SIZE)~
   SECURE.SEGMENT (SEG NO)~
Command level interface procedures~
   ASSIGN.USER.SEGMENT (SSN, SEG NO, REQD ACCESS)~
   ASSIGN.SYS.SEGMENT (SEG NO) SSN~
   INIT.SEGS (SPN, STORE LIMIT)~
   TINI.SEGS (SPN)~
   READ.SYS.SEGMENT.STATUS (SEG)~
   PROTECT (SSN, VALUE)~
Data types~
   SEG.VARS~
Configuration parameters~
   SEG.SIZE~
   PAGE.SIZE~
   FREE.LIMIT~
   NO.OF.PAGES~
   NO.OF.LOCAL.SEGS~
   NO.OF.COMMON.SEGS~
   NO.OF.MAPPED.SEGS~
   NO.OF.SYS.SEGS~
~S1~O2.1 Hardware Interface
~BTranslation from virtual to real addresses is performed by a set of page
address registers called the V.PARs. There is one V.PAR for each page of real
store, and each takes the following form:~
~3
~T# 9 17
~Q5
~
##~O                                 ~O~
##~O| | PROC | SEG | BLOCK | ACCESS |~O~
##~  |~
#lockout -~
~0
~
On every store access, the required virtual address is compared with every
V.PAR (in parallel). The page address register corresponding to the required
PROC/SEG/BLOCK indicates the page of store required. if the lockout bit is set
to 1, the V.PAR will not signal equivalence. The access field in each page addre
ss
register indicates the type of access which is permitted to the page. It is
interpreted in the following way:~
~3
~T# 7
~
~Q10
~
~
# ACCESS                                                 ~
#~O         ~O~
#~O| | | | |~O~
# | | | |~
# | | | |~
# | | |  --- Obey permission (for instructions)~
# | |  ----- Write permission (for operands)~
# |  ------- Read permission (for operands)~
#  --------- User permission (non-privilege access allowed)~
~0
~
~BSegment numbers above a hardware dependent limit (NO.OF.LOCAL.SEGS) are
assumed to be common segments, accessible to all processes. For virtual addresse
s
within the common area, the process field in the pars are not significant,
and so is ignored by the address translation hardware when checking the V.PARs
for equivalence. For "local" segments, where the segment number is below this
limit, the process field for comparison with the pars is taken from the hardware
register V.PROCESS.NUMBER (as described in section 13, the process manager).
~BIf the required page is not in store, none of the pars can give equivalence,
and so a process based virtual store interrupt is generated. The failing
address is set in the register V.NEQ.SEG and V.NEQ.BLK. The type of access
is also set in a register, V.NEQ.ACCESS, encoded in the same way as the access
field in the pars. An additional bit indicates if the pars detected an access
violation.
~BThe ideal machine also has facilities for searching the V.PARs looking for
a particular combination of PROC/SEG/BLOCK. The required address is loaded
into the registers V.SEARCH.PROC, V.SEARCH.SEG and V.SEARCH.BLK respectively.
The search is initiated by writing to the register V.SEARCH.MASK. This has
the following format:~
~3
~T# 12
~
~Q8
~
#~O                ~O~
#~O|     | | | | | ~O~
#       | | | |~
#       | | |  - SEARCH FOR MATCH ON BLOCK~
#       | |  --- SEARCH FOR MATCH ON SEG~
#       |  ----- SEARCH FOR MATCH ON PROC~
#        ------- CONTINUE SEARCH~
~0
~
Writing to the bottom 3 bits of this register initiates a search of
the V.PARs. the field for PROC/SEG/BLOCK are ignored in the search, if
the corresponding bits in V.SEARCH.MASK are not set, and the lockout bit is
disregarded. The first page to be found corresponding to the required
PROC/SEG/BLOCK combination has its page number returned in V.PAR.NO.
To continue the search the same pattern with the CONTINUE.SEARCH bits set
is written to V.SEARCH.MASK. When there are no more pages with the required
address characteristics in the real store, V.PAR.NO is set to NO.OF.PAGES
(i.e. the size of real store).
~BThe ideal hardware is also equipped with a special instruction for checking
the access permission and validity of a particular virtual address. This instruc
tion,
the VALIDATE instruction, forces a search of the V.PARs looking for an equivalen
ce
with the virtual address specified as the operand. The access permission in the
corresponding V.PAR is set in the register V.VAL.ACCESS. If no par matches the
specified virtual address, a process based validate fail interrupt is generated.
The register V.VAL.ACCESS is dumped in the process register block on entry to
interrupt level, and restored on leaving interrupt level.
~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) 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.~
~
~
~
7) 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.~
~
~
~
8) 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.~
~
~
~
9) 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.~
~
~
~
10) 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.~
~
~
~
11) SEG.SIZE~
~BThe maximum size in bytes of an accessible segment.~
~
~
~
12) SEG.SHIFT~
~BLog base 2 of SEG.SIZE.~
~
~
~
13) 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.~
~
~
~
14) PAGE.SHIFT~
~BLog base 2 of PAGE.SIZE.~
~
~
~
15) FREE.LIMIT~
~BThe number of pages freed by the page rejection process. Rejection
ceases when a total of FREE.LIMIT pages are available.~
~
~
~
16) NO.OF.PAGES~
~BThe size of the core store in PAGE.SIZE units.~
~
~
~
17) NO.OF.LOCAL.SEGS~
~BThe number of segments which each process can own
privately.~
~
~
~
18) NO.OF.MAPPED.SEGS~
~BThe number of directly addressible segments.~
~
~
~
19) NO.OF.COMMON.SEGS~
~BThe number of segments common to all processes.~
~
~
~
20) NO.OF.SYS.SEGS~
~BThe maximum number of segments which may
exist in the system at any one time.~
~
~
~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 start the rejection process. Rejection then continue until a
sufficient number of pages have been freed.
~BPages are selected for rejection by a cyclic scan of all store pages, ignoring
those which are already free, are locked in, or have been accessed
since they were last considered for rejection.
~S1~O3.2 Data Structures~
~3
~T# 20
~
~
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.~
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.~
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~IInformation required to define the state of a system segment.~
   :LIMIT~IThe size of the segment (in pages).~
   :DRUM.ADDR~IThe backing store address to which the page table is to be reject
ed.~
   :CURRENT.SIZE~IThe block number of the last valid block on the backing store.
~
   :STATUS~IAdditional information about a segment indicating whether it is a fi
le.~
   :COUNT~IA count indicating the number of users sharing a segment.~
   :SST.LINK~IA linked list of free SST entries (see FREE.SST).~
IN.USE~IA bit map indexed by page number indicating which core pages are in use.
~
FREE.SST~IHead of the list of free SST entries.~
~0
~
~S1~O3.3 Special Notes~
~BThe page size is assumed to be the same as the block size on the drum.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                SYS141
~V9 -1
~F
@TITLE SYS14(1,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 CORE REJECT
   INT11 SECURE PAGES
   CMD1  CREATE SEGMENT
   CMD2  RELEASE SEGMENT
   CMD3  CHANGE SIZE
   CMD4  CHANGE ACCESS
   CMD5  INTERCHANGE
   CMD6  READ SEGMENT STATUS
   CMD7  CREATE X SEGMENT
   CMD8  ASSIGN USER SEGMENT
   CMD9  ASSIGN SYS SEGMENT
   CMD10 RELEASE SYS SEGMENT
   CMD11 INIT SEGS
   CMD12 TINI SEGS
   CMD13 ALLOCATE SYS SEG
   CMD14 MAP
   CMD15 COPY BLOCK
   CMD16 SECURE SEGMENT
   CMD17 CMD MAP
   CMD19 PROTECT
   CMD20 READ SYS SEGMENT STATUS
   CMD21 PASS SEGMENT
   CMD22 CHANGE COMMON SEGMENT
@BOX 6.0
END
@BOX 1.1
#SYS14/1
MODULE SYS14 (VIRTUAL.STORE.INTERRUPT, VALIDATE.FAIL.INTERRUPT, CORE.REJECT, GET
.BLOCK, REL.BLOCK,
   UPDATE.BLOCK, STORE.REJECTION, MAP.ADDRESS, CREATE.SEGMENT, RELEASE.SEGMENT,
   CHANGE.SIZE, CHANGE.ACCESS, INTERCHANGE, MAP, CMD.MAP, ALLOCATE.SYS.SEG, PROT
ECT,
   READ.SEGMENT.STATUS, CREATE.X.SEGMENT, ASSIGN.USER.SEGMENT, ASSIGN.SYS.SEGMEN
T,
   RELEASE.SYS.SEGMENT, COPY.BLOCK, INIT.SEGS, TINI.SEGS, SST, CST, LST.TYPE, SS
T.TYPE,
   SEG.VARS, CMT.TYPE, CMT, SECURE.SEGMENT, READ.SYS.SEGMENT.STATUS, RESERVE.SEG
, STATS.TYPE,
   PASS.SEGMENT, CHANGE.COMMON.SEGMENT);
@BOX 2.1
TYPE LST.TYPE IS
   LOGICAL8 ACCESS, SSN
OR
   LOGICAL16 LST.ENTRY;
TYPE SST.TYPE IS
   INTEGER LIMIT
   LOGICAL8 STATUS, COUNT
OR
   INTEGER SST.LINK;
TYPE CMT.TYPE IS
   LOGICAL16 SSN, BLOCK
OR
   LOGICAL32 ENTRY;
TYPE SEG.VARS IS
   LST.TYPE [NO.OF.X.SEGS] XST
   LST.TYPE [NO.OF.LOCAL.SEGS] LST
   INTEGER PROCESS.NUMBER, SEG.NO1, BLK1, SEG.NO2, BLK2;
TYPE STATS.TYPE IS
   INTEGER SEGS.CREATED, X.SEGS.CREATED;
@BOX 3.1
*GLOBAL 5;
LITERAL/INTEGER ACCESS.VIOLATION = %10, ACCESS.FAULT = 8, SEG.UNDEFINED = %10,
   SEG.OVERFLOW = %20, PAGE.UNAVAILABLE = 4, FREE.LIMIT = 4,
   DEFINED = %80, PROTECTED = 1, TRANSFER.FAIL = %1401,
   PSB.SEARCH = 0, PS.SEARCH = 1, P.SEARCH = 3, PS.CONT.SEARCH = 9,
   INVALID.PAR = -1, SST.PROC = %F0, DUMMY.SEG = %FE;
LOGICAL REJECTION.HALT;
INTEGER FREE.SST, WORDS.PER.PAGE, NO.OF.SEGS;
INTEGER [SYS01.NO.OF.ACTIVITIES] HFP;
CMT.TYPE [SYS02.NO.OF.PAGES] CMT;
SST.TYPE [NO.OF.SYS.SEGS] SST;
LST.TYPE [NO.OF.COMMON.SEGS] CST;
ADDR STATS.TYPE STATS;
@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;
NO.OF.COMMON.SEGS + NO.OF.LOCAL.SEGS => NO.OF.SEGS;
MAKE (STATS.TYPE, 0, SYS21.GET.STATS (14)) => STATS;
END
@BOX 6.1
*END
@END
@TITLE SYS14/1(1,9)

@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.PAR [], V.PAR.NO, V.PROCESS.NUMBER, V.STACK.SEG, V.NEQ.SEG, V.NE
Q.ACCESS,
   V.NEQ.BLK, V.SEARCH.PROC, V.SEARCH.SEG, V.SEARCH.BLK, V.SEARCH.MASK;
IMPORT LITERAL SEG.SIZE, X.SEG.SIZE, SEG.SHIFT, PAGE.SIZE, PAGE.SHIFT, LOCKED.SI
ZE,
   PROC.FIELD, SEG.FIELD, BLK.FIELD, ACCESS.FIELD, LOCKOUT, ALTERED, REFERENCED,
   PROC.FIELD.SHIFT, SEG.FIELD.SHIFT, BLK.FIELD.SHIFT, ACCESS.FIELD.SHIFT, NO.OF
.LOCAL.SEGS,
   NO.OF.COMMON.SEGS, NO.OF.SYS.SEGS, NO.OF.X.SEGS, FIRST.COMMON.SEG, FIRST.X.SE
G,
   NO.OF.INITIAL.SEGS, REG.DUMP.SIZE, DUMPED.V.VAL.ACCESS.REG.NO, X.SEG,
   REAL.STORE.SEGMENT;
@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 ();
IMPORT LITERAL SYS02.NO.OF.PAGES.BIT.VEC.SIZE;
PSPEC SYS02.OBTAIN.PAGE (INTEGER) / INTEGER;
PSPEC SYS02.RELEASE.PAGE (INTEGER, INTEGER);
IMPORT LITERAL SYS02.NO.OF.PAGES;
INTEGER16 [SYS02.NO.OF.PAGES] LOCKIN;
PSPEC SYS03.TRANSFER.DRUM.SEGMENT.PAGES (INTEGER, INTEGER,
   INTEGER, INTEGER, INTEGER) / INTEGER;
PSPEC SYS03.OPEN.DRUM.SEGMENT (INTEGER, LOGICAL32, INTEGER);
PSPEC SYS03.CLOSE.DRUM.SEGMENT (INTEGER);
PSPEC SYS03.CHANGE.DRUM.SEGMENT.SIZE (INTEGER, INTEGER);
PSPEC SYS03.READ.DRUM.SEGMENT.ADDR (INTEGER) / LOGICAL32;
PSPEC SYS03.PROTECT.DRUM.SEGMENT (INTEGER, INTEGER);
PSPEC SYS03.SECURE.DRUM.SEGMENT (INTEGER);
PSPEC SYS06.READ.SUSP.REASON (INTEGER) / LOGICAL;
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) / INTEGER;
PSPEC SYS13.INT.GET.PRB (INTEGER) / INTEGER;
PSPEC SYS13.CHECK.REQUEST (LOGICAL, LOGICAL);
PSPEC SYS13.CHECK.PRIV ();
PSPEC SYS16.CLOSE.FILE (INTEGER);
PSPEC SYS21.GET.STATS (INTEGER) / INTEGER;
ADDR PW0, PW1, PW2, PW3, PW4, PW5, PW6;
LOGICAL64 PWW1;
@END


@TITLE SYS14/2(1,9)

@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;
   #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
*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;
LSPEC COPY.BLOCK (INTEGER, INTEGER, INTEGER, INTEGER);
LSPEC SECURE.SEGMENT (INTEGER);
PSPEC PROTECT (INTEGER, INTEGER);
PSPEC READ.SYS.SEGMENT.STATUS (INTEGER);
LSPEC PASS.SEGMENT (INTEGER, INTEGER, INTEGER, INTEGER);
LSPEC CHANGE.COMMON.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
*CODE 19;
PSPEC INIT.SEGS (ADDR SEG.VARS, INTEGER, INTEGER);
   #SYSCMD14.11
PSPEC TINI.SEGS (ADDR SEG.VARS);
   #SYSCMD14.12
@END
@TITLE SYSINT14.1(1,9)

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

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

@FLOW 1-2NO-20-3-4DEFINED-5NO-6-7-8-9
@FLOW 20YES-12
@FLOW 2YES-10-11-16-8
@FLOW 4UNDEFINED-12-13-16
@FLOW 5YES-14-15-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 BLOCK
[SYSINT14.3]
@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 20.0
IS SEGMENT OUT OF RANGE
@BOX 1.1
PROC VIRTUAL.STORE.INTERRUPT;
INTEGER PAGE.NO;
ADDR LST.TYPE SEG.TABLE;
ADDR SEG.VARS C.SEG.VARS;
@BOX 2.1
IF V.NEQ.ACCESS & ACCESS.VIOLATION /= 0
@BOX 3.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 4.1
IF ACCESS & DEFINED = 0
@BOX 5.1
IF LIMIT OF SST [SSN] =< V.NEQ.BLK
@BOX 6.1
GET.BLOCK (V.NEQ.SEG, V.NEQ.BLK) ->> PAGE.SHIFT => PAGE.NO;
@BOX 7.1
1 -> LOCKIN [PAGE.NO];
@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 20.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.2(1,9)

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

@ROW 5-7

@FLOW 1-2-3DEFINED-4NO-5-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 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];
@END


@TITLE SYSINT14.3(1,11)
@COL 16N-17T-20R
@COL 1S-2R-10T-22N-3R-4T-5R-6R-8R-9R-12R-14R-15F
@COL 11R

@ROW 16-22
@ROW 17-5

@FLOW 1-2-10NO-22-3-4-5-6-8-9-12-14-15
@FLOW 4IN CORE-17-20-15
@FLOW 17LOCKED OUT-16-22
@FLOW 10YES-11-6

@BOX 1.0
GET BLOCK (SEG, BLOCK)
@BOX 2.0
GET PROCESS NUMBER
@BOX 3.0
SEARCH PARS
@BOX 4.0
IS BLOCK IN CORE?
@BOX 5.0
SET POINTER TO REQUIRED
SEGMENT TABLE ENTRY
@BOX 6.0
OBTAIN PAGE OF CORE
@BOX 8.0
MARK PAGE LOCKED OUT
@BOX 9.0
PUT VIRTUAL ADDRESS AND
ACCESS PERMISSION IN PAR
@BOX 10.0
X-SEGMENT?
@BOX 11.0
GET XST ENTRY
@BOX 12.0
REQUEST DRUM TRANSFER
[SYS03]
@BOX 14.0
FREE ALL ACTIVITIES HALTED
FOR THIS PAGE
@BOX 15.0
END
@BOX 17.0
IS PAGE LOCKED OUT
@BOX 20.0
MARK BLOCK LOCKED IN
@BOX 1.1
PROC GET.BLOCK (SEG.NO, BLOCK.NO);
INTEGER PROC.NO, PAGE.NO, TEMP, SYS.SEG, I, BSA;
LOGICAL ACCESS;
ADDR [LOGICAL] CLEAR.PAGE;
ADDR SEG.VARS C.SEG.VARS;
@BOX 2.1
MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
IF SYS01.INT.ACTIVITIES ! SYS01.PZ.ACTIVITY
   & SYS01.CURRENT.ACTIVITY.BIT /= 0 THEN
   0 => PROC.NO;
ELSE
   PROCESS.NUMBER OF C.SEG.VARS^ => PROC.NO;
FI
@BOX 3.1
PROC.NO => V.SEARCH.PROC;
SEG.NO => V.SEARCH.SEG;
BLOCK.NO => V.SEARCH.BLK;
PSB.SEARCH => V.SEARCH.MASK;
@BOX 4.1
IF V.PAR.NO => PAGE.NO < SYS02.NO.OF.PAGES
@BOX 5.1
IF SEG.NO < NO.OF.LOCAL.SEGS THEN
   SSN OF LST [SEG.NO] OF C.SEG.VARS^ => SYS.SEG;
   ACCESS OF LST [SEG.NO] OF C.SEG.VARS^ => ACCESS;
ELSE
   SSN OF CST [SEG.NO - FIRST.COMMON.SEG] => SYS.SEG;
   ACCESS OF CST [SEG.NO - FIRST.COMMON.SEG] => ACCESS;
FI
@BOX 6.1
SYS02.OBTAIN.PAGE (1) => PAGE.NO;
1 => LOCKIN [PAGE.NO];
@BOX 8.1
SYS.SEG => SSN OF CMT [PAGE.NO];
BLOCK.NO => BLOCK OF CMT [PAGE.NO];
@BOX 9.1
IF STATUS OF SST [SYS.SEG] & X.SEG = 0 THEN
   %F &> ACCESS;
   PROC.NO <<- PROC.FIELD.SHIFT ! (SEG.NO <<- SEG.FIELD.SHIFT)
      ! (BLOCK.NO <<- BLK.FIELD.SHIFT) ! (ACCESS <<- ACCESS.FIELD.SHIFT)
      => V.PAR [PAGE.NO];
ELSE
   7 &> ACCESS;
   REAL.STORE.SEGMENT <<- SEG.FIELD.SHIFT + (PAGE.NO
      <<- BLK.FIELD.SHIFT) ! (ACCESS <<- ACCESS.FIELD.SHIFT)
      => V.PAR [PAGE.NO];
FI
@BOX 10.1
IF SEG.NO >= FIRST.X.SEG < FIRST.X.SEG + NO.OF.X.SEGS
@BOX 11.1
SSN OF XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => SYS.SEG;
ACCESS OF XST [SEG.NO - FIRST.X.SEG] OF C.SEG.VARS^ => ACCESS;
@BOX 12.1
LOCKOUT !> V.PAR [PAGE.NO];
IF SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SYS.SEG, BLOCK.NO,
   PAGE.NO, 1, 0) /= 0 THEN
   IF PROC.NO = 0 THEN
      SYS12.SYSTEM.ERROR (TRANSFER.FAIL);
   ELSE
      SYS10.SET.VM.INT (0, PAGE.UNAVAILABLE);
   FI
FI
LOCKOUT -=> V.PAR [PAGE.NO];
@BOX 14.1
FOR TEMP < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [TEMP] = PAGE.NO THEN
      0 => HFP [TEMP];
      SYS01.FREE (BIT (TEMP), SYS01.PAGING.HALT);
   FI
OD
@BOX 15.1
PAGE.NO <<- PAGE.SHIFT => GET.BLOCK;
END
@BOX 17.1
IF CHECK.LOCKOUT (PAGE.NO) /= 0
@BOX 20.1
1 +> LOCKIN [PAGE.NO];
@END


@TITLE SYSINT14.4(1,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
REL BLOCK (CORE ADDR)
@BOX 2.0
RELEASE THE BLOCK
FOR THE BLOCK
@BOX 3.0
END
@BOX 1.1
PROC REL.BLOCK (CORE.ADDR);
INTEGER PAGE;
@BOX 2.1
SELECT CMT [CORE.ADDR ->> PAGE.SHIFT => PAGE];
IF STATUS OF SST [SSN] & X.SEG /= 0 THEN
   0 => ENTRY;
   1  => LOCKIN [PAGE];
   SYS02.RELEASE.PAGE (PAGE, 1);
ELSE
   1 -> LOCKIN [PAGE];
FI
@BOX 3.1
END
@END


@TITLE SYSINT14.5(1,9)

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

@ROW 3-7

@FLOW 1-2X SEG-3-6
@FLOW 2-7-6

@BOX 1.0
UPDATE BLOCK (CORE ADDR)
@BOX 2.0
X SEGMENT?
@BOX 3.0
TRANSFER BLOCK
[SYS03]
@BOX 6.0
END
@BOX 7.0
MARK BLOCK ALTERED
@BOX 1.1
PROC UPDATE.BLOCK (CORE.ADDR);
INTEGER PAGE;
@BOX 2.1
SELECT CMT [CORE.ADDR ->> PAGE.SHIFT => PAGE];
IF X.SEG & STATUS OF SST [SSN] = 0
@BOX 3.1
SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SSN, BLOCK, PAGE, 1, 1);
@BOX 6.1
END
@BOX 7.1
ALTERED !> V.PAR [PAGE];
@BOX 10.1
IF CHECK.LOCKOUT (PAGE) /= 0
@BOX 7.1
ALTERED !> V.PAR [PAGE];
@END


@TITLE SYSINT14.6(1,9)

@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(1,11)

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

@ROW 6-10

@FLOW 1-4-5-6NO-7-8-9-3-4
@FLOW 5-10-13
@FLOW 6-3
@FLOW 7LOCKED OUT-4

@BOX 1.0
RELEASE PAGES (SEG, NEW SIZE)
@BOX 3.0
MOVE TO NEXT PAGE
@BOX 4.0
SEARCH FOR PAGES
OF THIS SEGMENT
@BOX 5.0
NO PAGES LEFT?
@BOX 6.0
IS PAGE WITHIN NEW SIZE?
@BOX 7.0
IS PAGE LOCKED OUT?
@BOX 8.0
MARK PARS INVALID
@BOX 9.0
RELEASE PAGE
[SYS02]
@BOX 10.0
RESET CACHES
@BOX 13.0
END
@BOX 1.1
PROC RELEASE.PAGES (SEG, NEW.SIZE);
INTEGER PROC.NO, PAGE.NO;
-1 => PROC.NO;
0 => PAGE.NO;
@BOX 3.1
1 +> PAGE.NO;
@BOX 4.1
WHILE PAGE.NO < SYS02.NO.OF.PAGES
   AND SSN OF CMT [PAGE.NO] /= SEG DO
   1 +> PAGE.NO;
OD
@BOX 5.1
IF PAGE.NO >= SYS02.NO.OF.PAGES
@BOX 6.1
IF BLOCK OF CMT [PAGE.NO] < NEW.SIZE
@BOX 7.1
IF CHECK.LOCKOUT (PAGE.NO) /= 0
@BOX 8.1
V.PAR [PAGE.NO] ->> PROC.FIELD.SHIFT => PROC.NO;
INVALID.PAR => V.PAR [PAGE.NO];
@BOX 9.1
1 => LOCKIN [PAGE.NO];
0 => ENTRY OF CMT [PAGE.NO];
SYS02.RELEASE.PAGE (PAGE.NO, 1);
@BOX 10.1
PROC.NO => V.SEARCH.PROC;
P.SEARCH => V.SEARCH.MASK;
@BOX 13.1
END
@BOX 17.1
SELECT SST [SEG];
IF NEW.SIZE < CURRENT.SIZE THEN
   NEW.SIZE => CURRENT.SIZE;
FI
@END

@TITLE SYSINT14.8(1,11)

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

@ROW 5-7


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

@BOX 1.0
RESET PAGING REGISTERS (PROC/SEG1, PROC/SEG2)
@BOX 2.0
GET REQUIRED PROCESS AND
SEGMENT NUMBERS
@BOX 3.0
SEARCH PARS FOR PAGES
OF PROC/SEG1
@BOX 4.0
NO PAGES LEFT?
@BOX 5.0
CHANGE PAR TO PROC/SEG2 AND
RESET ACCESS IF REQUIRED
@BOX 6.0
CONTINUE SEARCH OF PARS
@BOX 7.0
END
@BOX 1.1
PROC RESET.PAGING.REGISTERS (PROC.SEG1, PROC.SEG2);
INTEGER PROC1, PROC2, SEG1, SEG2;
LOGICAL8 ACC;
ADDR SEG.VARS C.SEG.VARS;
@BOX 2.1
PROC.SEG1 / NO.OF.SEGS => PROC1;
PROC.SEG2 / NO.OF.SEGS => PROC2;
PROC1 * NO.OF.SEGS -: PROC.SEG1 => SEG1;
PROC2 * NO.OF.SEGS -: PROC.SEG2 => SEG2;
IF PROC2 /= SST.PROC THEN
   MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   ACCESS OF LST [SEG2] OF C.SEG.VARS^ & %F <<- ACCESS.FIELD.SHIFT => ACC;
FI
@BOX 3.1
PROC1 => V.SEARCH.PROC;
SEG1 => V.SEARCH.SEG;
PS.SEARCH => V.SEARCH.MASK;
@BOX 4.1
IF V.PAR.NO >= SYS02.NO.OF.PAGES
@BOX 5.1
PROC.FIELD ! SEG.FIELD & V.PAR [V.PAR.NO] -=> V.PAR [V.PAR.NO];
PROC2 <<- PROC.FIELD.SHIFT ! (SEG2 <<- SEG.FIELD.SHIFT) !> V.PAR [V.PAR.NO];
IF PROC2 /= SST.PROC THEN
   V.PAR [V.PAR.NO] & ACCESS.FIELD -= ACC -=> V.PAR [V.PAR.NO];
FI
@BOX 6.1
PROC1 => V.SEARCH.PROC;
SEG1 => V.SEARCH.SEG;
PS.CONT.SEARCH => V.SEARCH.MASK;
@BOX 7.1
END
@END


@TITLE SYSINT14.9(1,11)

@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);
INTEGER SEG, BLOCK, DISP, PAGE.NO;
@BOX 2.1
CORE.ADDR ->> PAGE.SHIFT => PAGE.NO <<- PAGE.SHIFT -: CORE.ADDR => DISP;
MAKE (LOGICAL8, 1, SEG.FIELD ! BLK.FIELD & V.PAR [PAGE.NO] <<- 2 + DISP) => MAP.
ADDRESS;
@BOX 3.1
END
@END


@TITLE SYSINT14.10(1,11)
@COL 11T-12R-13R
@COL 1S-2R-3T-4T-5T-6T-7R-8R-9R-10F
@COL 14T-15R-16R-17N
@ROW 4-14
@ROW 11-5
@ROW 7-16
@FLOW 1-2-3NO-4-5OK-6OK-7-8-9-10
@FLOW 4-11OK-12-13-9
@FLOW 11FAIL-9
@FLOW 3YES-14OK-15-16-17-9
@FLOW 6FAIL-16
@FLOW 14FAIL-17
@FLOW 5FAIL-9
@BOX 1.0
COPY (DUMMY, DUMMY)
@BOX 2.0
MAP SEGMENT
VARIABLES
@BOX 3.0
IS SECOND SEGMENT
AN X-SEGMENT?
@BOX 4.0
IS FIRST SEGMENT
AN X-SEGMENT
@BOX 5.0
GET FIRST BLOCK
[SYSINT14.14]
@BOX 6.0
GET SECOND BLOCK
[SYSINT14.14]
@BOX 7.0
STORE TO STORE
COPY
@BOX 8.0
UPDATE AND
RELEASE BLOCKS
@BOX 9.0
RETURN STATUS
@BOX 10.0
END
@BOX 11.0
GET SECOND BLOCK
[SYSINT14.14]
@BOX 12.0
WRITE TO BLOCK
FROM SEGMENT ON DISC
[SYS03]
@BOX 13.0
UPDATE AND
RELEASE BLOCK
@BOX 14.0
GET FIRST BLOCK
[SYSINT14.14]
@BOX 15.0
WRITE BLOCK TO
SECOND SEGMENT ON
DISC
[SYS03]
@BOX 16.0
RELEASE FIRST BLOCK
@BOX 1.1
PROC COPY (DUMMY1, DUMMY2);
INTEGER SPN, TEMP, STATUS;
INTEGER32 PAGE1, PAGE2;
ADDR [LOGICAL] BLOCK1, BLOCK2;
ADDR SEG.VARS C.SEG.VARS;
SYS13.CURRENT.SPN => SPN;
-1 => STATUS;
@BOX 2.1
MAKE (SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
@BOX 3.1
IF SEG.NO2 >= NO.OF.LOCAL.SEGS
@BOX 4.1
IF SEG.NO1 >= NO.OF.LOCAL.SEGS
@BOX 5.1
IF GET.BLOCK (SEG.NO1, BLK1) => PAGE1 < 0
@BOX 6.1
IF GET.BLOCK ( SEG.NO2, BLK2) => PAGE2 < 0
@BOX 7.1
MAKE (LOGICAL, WORDS.PER.PAGE, BYTE (MAP.ADDRESS (PAGE1, 0))) => BLOCK1;
MAKE (LOGICAL, WORDS.PER.PAGE, BYTE (MAP.ADDRESS (PAGE2, 0))) => BLOCK2;
PROCESS.NUMBER => V.PROCESS.NUMBER;
FOR TEMP < WORDS.PER.PAGE DO
   BLOCK1^ [TEMP] => BLOCK2^ [TEMP];
OD
0 => V.PROCESS.NUMBER;
0 => STATUS;
@BOX 8.1
UPDATE.BLOCK (PAGE2);
1 -> LOCKIN [PAGE1 ->> PAGE.SHIFT];
1 -> LOCKIN [PAGE2 ->> PAGE.SHIFT];
@BOX 9.1
STATUS => SYS13.PROC.RESULT [SPN];
@BOX 10.1
END
@BOX 11.1
IF GET.BLOCK (SEG.NO2, BLK2) => PAGE2 < 0
@BOX 12.1
SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SSN OF XST [SEG.NO1 - FIRST.X.SEG],
   BLK1, PAGE2 ->> PAGE.SHIFT, 1, 0)
      => STATUS;
@BOX 13.1
IF STATUS = 0 THEN
   UPDATE.BLOCK (PAGE.2);
FI
1 -> LOCKIN [PAGE.2 ->> PAGE.SHIFT];
@BOX 14.1
IF GET.BLOCK (SEG.NO1, BLK1) => PAGE1 < 0
@BOX 15.1
SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SSN OF XST [SEG.NO2 - FIRST.X.SEG],
   BLK2, PAGE1 ->> PAGE.SHIFT, 1, 1)
      => STATUS;
@BOX 16.1
REL.BLOCK (PAGE.1);

@END
@TITLE SYSINT14.11(1,11)

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

@ROW 21-25
@ROW 20-17
@ROW 3-18
@ROW 16-22

@FLOW 1-20-2-26-3-5-21-6NO-22-7ALTERED-8-9-10-11-12-13-14-17-20
@FLOW 2-18-19-17
@FLOW 5LOCKED IN-26
@FLOW 21LOCKED OUT-26
@FLOW 6-16-25-26
@FLOW 7-12

@BOX 1.0
CORE REJECT
@BOX 2.0
SUFFICIENT SPACE AVAILABLE?
@BOX 3.0
INCREMENT INDEX INTO PARS
(CYCLICALLY)
@BOX 5.0
IS PAGE LOCKED IN?
@BOX 6.0
HAS PAGE BEEN REFERENCED?
@BOX 7.0
IS PAGE MARK ALTERED?
@BOX 8.0
MARK PAGE LOCKED OUT
@BOX 9.0
REQUEST DRUM TRANSFER
[SYS03]
@BOX 10.0
REMOVE LOCKOUT STATUS ON THE PAGE
@BOX 11.0
FREE ALL ACTIVITY HALTED
FOR THE PAGE
@BOX 12.0
MARK PAR INVALID
@BOX 13.0
RELEASE PAGE
[SYS02]
@BOX 14.0
FREE ALL ACTIVITY HALTED FOR SPACE
@BOX 15.0
END
@BOX 16.0
CLEAR REFERENCED BIT
@BOX 18.0
CLEAR SOFTWARE INTERRUPT
FOR CURRENT ACTIVITY
@BOX 19.0
CALL LOW LEVEL SCHEDULER
(NEXT ACTIVITY)
@BOX 21.0
IS PAGE LOCKED OUT?
@BOX 1.1
PROC CORE.REJECT;
INTEGER PAGE.NO, TEMP, COUNT, PROC.NO, SEG.NO,
   BLOCK.NO;
-1 => COUNT => PAGE.NO;
@BOX 2.1
IF 1 +> COUNT > FREE.LIMIT
@BOX 3.1
IF 1 +> PAGE.NO >= SYS02.NO.OF.PAGES THEN
   LOCKED.SIZE => PAGE.NO;
FI
@BOX 5.1
IF LOCKIN [PAGE.NO] /= 0
@BOX 6.1
IF REFERENCED & V.PAR [PAGE.NO] /= 0
@BOX 7.1
IF ALTERED & V.PAR [PAGE.NO] = 0
@BOX 8.1
LOCKOUT !> V.PAR [PAGE.NO];
@BOX 9.1
SELECT CMT [PAGE.NO];
SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SSN, BLOCK, PAGE.NO, 1, 1);
@BOX 10.1
LOCKOUT -=> V.PAR [PAGE.NO];
@BOX 11.1
FOR TEMP < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [TEMP] = PAGE.NO THEN
      0 => HFP [TEMP];
      SYS01.FREE (BIT (TEMP), SYS01.PAGING.HALT);
   FI
OD
@BOX 12.1
V.PAR [PAGE.NO] & PROC.FIELD ->> PROC.FIELD.SHIFT => PROC.NO;
V.PAR [PAGE.NO] & SEG.FIELD ->> SEG.FIELD.SHIFT => SEG.NO;
V.PAR [PAGE.NO] & BLK.FIELD ->> BLK.FIELD.SHIFT => BLOCK.NO;
INVALID.PAR => V.PAR [PAGE.NO];
@BOX 13.1
1 => LOCKIN [PAGE.NO];
0 => ENTRY OF CMT [PAGE.NO];
SYS02.RELEASE.PAGE (PAGE.NO, 1);
PROC.NO => V.SEARCH.PROC;
SEG.NO => V.SEARCH.SEG;
BLOCK.NO => V.SEARCH.BLK;
PSB.SEARCH => V.SEARCH.MASK;
@BOX 14.1
SYS01.FREE (REJECTION.HALT, SYS01.PAGING.HALT);
0 => REJECTION.HALT;
@BOX 15.1
END
@BOX 16.1
REFERENCED -=> V.PAR [PAGE.NO];
@BOX 18.1
SYS01.CLEAR.INTERRUPT ();
@BOX 19.1
SYS01.NEXT.ACTIVITY ();
-1 => COUNT;
@BOX 21.1
IF LOCKOUT & V.PAR [PAGE.NO] /= 0
@END
@TITLE SYSINT14.12(1,11)

@COL 1S-4R-5T-6T-7R-8R-9R-10R-11R
@COL 15F

@ROW 6-15

@FLOW 1-4-5-6-7-8-9-10-11-5
@FLOW 6LOCKED OUT-4
@FLOW 5-15

@BOX 1.0
SECURE PAGES (SEG, INIT VALUE)
@BOX 4.0
SEARCH PARS FOR PAGES
OF THE SEGMENT
@BOX 5.0
NO PAGES LEFT?
@BOX 6.0
IS PAGE LOCKED OUT?
@BOX 7.0
MARK PAGE AS LOCKED OUT
@BOX 8.0
REQUEST DRUM TRANSFER
[SYS03]
@BOX 9.0
REMOVE LOCKOUT STATUS ON THE PAGE
@BOX 10.0
FREE ALL ACTIVITIES HALTED
FOR THE PAGE
@BOX 11.0
CONTINUE SEARCH OF PARS
@BOX 15.0
END
@BOX 1.1
PROC SECURE.PAGES (SEG, DUMMY);
INTEGER PAGE.NO, PTR, PROC.NO;
SYS13.CURRENT.SPN => PROC.NO;
@BOX 4.1
PROC.NO => V.SEARCH.PROC;
SEG => V.SEARCH.SEG;
PS.SEARCH => V.SEARCH.MASK;
@BOX 5.1
IF V.PAR.NO => PAGE.NO >= SYS02.NO.OF.PAGES
@BOX 6.1
IF CHECK.LOCKOUT (PAGE.NO) /= 0
@BOX 7.1
LOCKOUT !> V.PAR [PAGE.NO];
@BOX 8.1
SELECT CMT [PAGE.NO];
SYS03.TRANSFER.DRUM.SEGMENT.PAGES (SSN, BLOCK, PAGE.NO, 1, 1);
@BOX 9.1
LOCKOUT -=> V.PAR [PAGE.NO];
@BOX 10.1
FOR PTR < SYS01.NO.OF.ACTIVITIES DO
   IF HFP [PTR] = PAGE.NO THEN
      0 => HFP [PAGE.NO];
      SYS01.FREE (BIT (PTR), SYS01.PAGING.HALT);
   FI
OD
@BOX 11.1
PAGE.NO => V.PAR.NO;
PROC.NO => V.SEARCH.PROC;
SEG => V.SEARCH.SEG;
PS.CONT.SEARCH => V.SEARCH.MASK;
@BOX 15.1
END
@END


@TITLE SYSINT14.13(1,9)

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

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

@BOX 1.0
CHECK LOCKOUT (PAGE NO)
@BOX 2.0
PAGE NOT LOCKED OUT
@BOX 3.0
MARK PROCESS HALTED FOR PAGING
@BOX 4.0
HALT PROCESS
@BOX 5.0
END
@BOX 1.1
PROC CHECK.LOCKOUT (PAGE.NO);
0 => CHECK.LOCKOUT;
@BOX 2.1
IF LOCKOUT & V.PAR [PAGE.NO] = 0
@BOX 3.1
PAGE.NO => 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 SYSCMD14.1(1,11)

@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 SEGMENT (SEG NO, SIZE)
@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
@BOX 12.0
INITIALISE LOCAL SEGMENT TABLE ENTRY
@BOX 13.0
MORE SEGMENTS TO ALLOCATE?
@BOX 1.1
PROC CREATE.SEGMENT (SEG.NO, REQ.SIZE);
INTEGER SEGS, FIRST.SEG, SST.ENTRY, SEG.COUNT,
   NO.OF.BLOCKS;
ADDR TEMP;
ADDR SEG.VARS C.SEG.VARS;
0 => PW0;
@BOX 2.1
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, 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
IF SEG.NO < 0 THEN
   -2 => PW0;
ELSE
   -1 => PW0;
FI
@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;
1 +> SEGS.CREATED OF STATS^;
@BOX 13.1
IF 1 +> SEG.COUNT < SEGS
@END
@TITLE SYSCMD14.2(1,11)

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

@ROW 2-20
@ROW 3-30

@FLOW 1-2NO-3NO-7-4-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 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 7.1
SSN => SYS.SEG;
0 => LST.ENTRY;
0 => COUNT OF SST [SYS.SEG];
@BOX 8.1
END
@BOX 9.1
-3 => PW0;
@BOX 10.1
-6 => PW0;
@END
@TITLE SYSCMD14.3(1,11)
@COL 1S-5T-7T-3T-9T-2N-25T-10T-11T-12R-15R-16F
@COL 6N-18R-8N-19R-4N-17R-21N-20R-24N

@ROW 2-20
@ROW 3-4
@ROW 5-6
@ROW 7-8
@ROW 9-21
@ROW 12-24

@FLOW 1-5NO-7NO-3NO-9NO-2-25-10-11-12-15-16
@FLOW 10-16
@FLOW 25-15
@FLOW 11-15
@FLOW 3YES-4-17-24-16
@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 10.0
CHANGE SIZE ON DRUM
[SYS03]
@BOX 11.0
X SEGMENT?
@BOX 12.0
ENTER INTERRUPT LEVEL
TO RELEASE CORE PAGES
[SYSINT14.7]
@BOX 15.0
INSERT NEW SIZE IN
SYSTEM SEGMENT TABLE
@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 1.1
PROC CHANGE.SIZE (SEG.NO, REQ.SIZE);
INTEGER NEW.SIZE, PAGE.PNO, SEGMENT.SIZE;
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 => 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 10.1
SYS03.CHANGE.DRUM.SEGMENT.SIZE (SSN, REQ.SIZE);
IF PW0 < 0
@BOX 11.1
IF X.SEG & STATUS /= 0 OR REQ.SIZE > LIMIT
@BOX 12.1
SYS13.ENTER.INT.LEVEL (^RELEASE.PAGES, SSN, REQ.SIZE);
@BOX 15.1
NEW.SIZE => PW1;
REQ.SIZE => LIMIT;
@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
@END
@TITLE SYSCMD14.4(1,9)
@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
   V.PROCESS.NUMBER * NO.OF.SEGS +> SEG.NO;
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SEG.NO, SEG.NO);
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(1,11)
@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 7.0
INTERCHANGE SEGMENT
TABLE ENTRIES
@BOX 1.1
PROC INTERCHANGE (SEG1, SEG2);
INTEGER PROC.SHIFTED;
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
   V.PROCESS.NUMBER * NO.OF.SEGS => PROC.SHIFTED;
   SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> SEG1,
      DUMMY.SEG + PROC.SHIFTED);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> SEG2, SEG1);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, DUMMY.SEG + PROC.SHIFTED, SEG
2);
   SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
FI
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@END
@TITLE SYSCMD14.6(1,9)
@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
0 => PW3;
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@BOX 7.1
-6 => PW0;
@END
@TITLE SYSCMD14.7(1,11)

@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 X SEGMENT (SIZE)
@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.X.SEGMENT (REQ.SIZE);
INTEGER 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, 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.SEGMENT (-1, REQ.BYTE.SIZE);
@BOX 11.1
IF REQ.SIZE <<- PAGE.SHIFT => REQ.BYTE.SIZE =< SEG.SIZE
@END


@TITLE SYSCMD14.8(1,11)

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

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

@FLOW 1-17NO-16-2-3NO-4NO-13-5-14-12-6
@FLOW 17YES-18-11
@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 17.0
ALREADY A USER SEGMENT?
@BOX 18.0
RETURN FAULT STATUS -44
(EXCUSIVE ACCESS DEADLOCK)
@BOX 1.1
PROC ASSIGN.USER.SEGMENT (SYS.SEG, USER.SEG, REQ.ACCESS);
INTEGER TOTAL.SEGS, TEMP;
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 >= TOTAL.SEGS THEN
   -1 => USER.SEG;
   WHILE 1 +> USER.SEG < TOTAL.SEGS
      AND ACCESS OF SEG.TABLE^ [USER.SEG] /= 0 DO OD
FI
@BOX 3.1
IF USER.SEG >= TOTAL.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;
   %40 ! REQ.ACCESS => PW3;
   V.PROCESS.NUMBER * NO.OF.SEGS +> USER.SEG;
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, SYS.SEG / NO.OF.LOCAL.SEGS =>
      TEMP + SST.PROC * NO.OF.SEGS + (TEMP * NO.OF.LOCAL.SEGS -: SYS.SEG),
      USER.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 => TOTAL.SEGS;
   -1 => USER.SEG;
ELSE
   ^LST => SEG.TABLE;
   NO.OF.LOCAL.SEGS => TOTAL.SEGS;
FI
@BOX 17.1
IF COUNT OF SST [SYS.SEG] /= 0
@BOX 18.1
-44 => PW0;
@END


@TITLE SYSCMD14.9(1,9)
@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);
INTEGER SYS.SEG, TEMP;
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 => SYS.SEG;
0 => LST.ENTRY;
0 => COUNT OF SST [SYS.SEG];
IF USER.SEG < NO.OF.LOCAL.SEGS THEN
   V.PROCESS.NUMBER * NO.OF.SEGS +> USER.SEG;
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, USER.SEG, SYS.SEG /
      NO.OF.LOCAL.SEGS => TEMP + SST.PROC * NO.OF.SEGS +
      (TEMP * NO.OF.LOCAL.SEGS -: SYS.SEG));
FI
SYS.SEG => ASSIGN.SYS.SEGMENT;
@BOX 12.1
END
@BOX 13.1
-3 => PW0;
@BOX 14.1
-6 => PW0;
@END
@TITLE SYSCMD14.10(1,11)
@COL 1S-6R-10T-11T-2R-8T-9R-4R-12R-7R-5F

@FLOW 1-6-10NO-11NO-2-8NO-9-4-12-7-5
@FLOW 10YES-7
@FLOW 11YES-8
@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 11.0
X SEGMENT?
@BOX 12.0
CLOSE DRUM SEGMENT
[SYS03]
@BOX 1.1
PROC RELEASE.SYS.SEGMENT (SSN);
@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 COUNT /= 0
@BOX 11.1
IF X.SEG & STATUS /= 0
@BOX 12.1
SYS03.CLOSE.DRUM.SEGMENT (SSN);
@END
@TITLE SYSCMD14.11(1,11)
@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;
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
SPN => PROCESS.NUMBER;
@BOX 4.1
0 => PW0;
IF PW0 = 0 THEN
   ALLOCATE.SYS.SEG (0, SEG.SIZE ->> PAGE.SHIFT, 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
FI
@BOX 5.1
END
@END
@TITLE SYSCMD14.12(1,11)

@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
      0 => COUNT OF SST [SSN OF XST [SEG]];
      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
      0 => COUNT OF SST [SSN OF LST [SEG]];
      RELEASE.SYS.SEGMENT (SSN OF LST [SEG]);
      0 => LST.ENTRY OF LST [SEG];
   FI
OD
@BOX 4.1
END
@END



@TITLE SYSCMD14.13(1,11)

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

@ROW 4-7

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

@BOX 1.0
ALLOCATE SYS SEG (BACKING STORE ADDR, MAX SIZE, CURRENT SIZE, STATUS)
@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
OPEN DRUM SEGMENT
[SYS03]
@BOX 1.1
PROC ALLOCATE.SYS.SEG (BACKING.STORE.ADDR, 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;
SST.LINK => FREE.SST;
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
SYS03.OPEN.DRUM.SEGMENT (FREE.SST,
   BACKING.STORE.ADDR, MAX.SIZE)
IF PW0 /= 0
@END



@TITLE SYSCMD14.14(1,9)

@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(1,9)

@COL 1S-11T-12R-2T-3T-4R-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-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 1.1
PROC COPY.BLOCK (SEG1, BLOCK1, SEG2, BLOCK2);
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 BLOCK1 => BLK1 < 0 OR BLK1 >= LIMIT OF SST [SSN OF SEG.TABLE1^]
   OR BLOCK2 => BLK2 < 0 OR BLK2 >= LIMIT OF SST [SSN OF SEG.TABLE2^]
@BOX 4.1
SYS13.ENTER.INT.LEVEL (^COPY, 0, 0);
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 => SEG.NO1 >= FIRST.X.SEG THEN
   ^XST [SEG1 - FIRST.X.SEG] => SEG.TABLE1;
ELSE
   ^LST [SEG1] => SEG.TABLE1;
FI
IF SEG2 => SEG.NO2 >= FIRST.X.SEG THEN
   ^XST [SEG2 - FIRST.X.SEG] => SEG.TABLE2;
ELSE
   ^LST [SEG2] => SEG.TABLE2;
FI
@BOX 14.1
-3 => PW0;
@END


@TITLE SYSCMD14.16(1,9)

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

@ROW 2-20
@ROW 3-30

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

@BOX 1.0
SECURE SEGMENT (SEG NO)
@BOX 2.0
ILLEGAL SEGMENT NUMBER
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
X SEGMENT?
@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 11.0
SECURE DRUM SEGMENT
[SYS03]
@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 4.1
IF SEG.NO >= FIRST.X.SEG
@BOX 7.1
SYS13.ENTER.INT.LEVEL (^SECURE.PAGES, SEG.NO, 0);
@BOX 8.1
END
@BOX 9.1
-3 => PW0;
@BOX 10.1
-6 => PW0;
@BOX 11.1
SYS03.SECURE.DRUM.SEGMENT (SSN);
@END
@TITLE SYSCMD14.17(1,9)
@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(5,11)



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

@FLOW 1-2-4-3

@BOX 1.0
PROTECT (SSN, VALUE)
@BOX 2.0
SET SPECIFIED PROTECTION
FOR SYSTEM SEGMENT
@BOX 3.0
END
@BOX 4.0
PROTECT DRUM SEGMENT
[SYS03]
@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
@BOX 4.1
SYS03.PROTECT.DRUM.SEGMENT (SSN, VALUE);
@END

@TITLE SYSCMD14.19(5,11)
@COL 1S-2T-20N-3T-30R-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 30.0
DETERMINE BACKING STORE
ADDRESS
[SYS03]
@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 30.1
SYS03.READ.DRUM.SEGMENT.ADDR (SSN)
   => PWW1;
@BOX 4.1
SELECT SST [SSN];
LIMIT => PW1 => PW4;
STATUS => PW2;
SSN => PW3;
0 => PW5;
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@BOX 7.1
-6 => PW0;
@END
@TITLE SYSCMD14.20(5,11)
@COL 1S-2T-3T-13N-4T-5R-6T-16N-7T-8R-9R-10R-11N-12F
@COL 14R-15R-17R-18R-19N
@ROW 13-14
@ROW 5-15
@ROW 16-17
@ROW 8-18
@ROW 11-19
@FLOW 1-2OK-3NO-13-4NO-5-6NO-16-7NO-8-9-10-11-12
@FLOW 2FAIL-11
@FLOW 3YES-14-19-11
@FLOW 4YES-15-19
@FLOW 6YES-17-19
@FLOW 7YES-18-19
@BOX 1.0
PASS SEGMENT (SEGMENT1, SEGMENT2, SPN, PID)
@BOX 2.0
CHECK PASSING PROCESS
IS SUPERVISOR OF RECEIVING
PROCESS
[SYS13]
@BOX 3.0
ARE SEGMENT NUMBERS
ILLEGAL?
@BOX 4.0
IS FIRST SEGMENT
UNDEFINED?
@BOX 5.0
CHECKIN
[SYS01]
@BOX 6.0
IS RECEIVING PROCESS
FREE TO RUN?
@BOX 7.0
IS SECOND SEGMENT
ALREADY DEFINED?
@BOX 8.0
PASS SEGMENT
TABLE ENTRY
@BOX 9.0
RESET PAGING REGISTERS
[SYSINT14.8]
@BOX 10.0
CHECKOUT
[SYS01]
@BOX 12.0
END
@BOX 14.0
RETURN FAULT STATUS -3
(ILLEGAL SEGMENT NUMBER)
@BOX 15.0
RETURN FAULT STATUS -6
(SEGMENT DOES NOT EXIST)
@BOX 17.0
RETURN FAULT STATUS -26
(PROCESS NOT IN REQUIRED STATE)
@BOX 18.0
RETURN FAULT STATUS -1
(SEGMENT ALREADY EXISTS)
@BOX 1.1
PROC PASS.SEGMENT (SEG1, SEG2, SPN, PID);
INTEGER PROC.SHIFTED;
ADDR LST.TYPE SEG.TABLE1, SEG.TABLE2;
ADDR SEG.VARS SEG.VARS1, SEG.VARS2;
@BOX 2.1
SYS13.CHECK.REQUEST (SPN, PID);
IF PW0 /= 0
@BOX 3.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 4.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14))
   => SEG.VARS1;
IF SEG1 >= FIRST.X.SEG THEN
   ^XST [SEG1 - FIRST.X.SEG] OF SEG.VARS1^
   => SEG.TABLE1;
ELSE
   ^LST [SEG1] OF SEG.VARS1^
   => SEG.TABLE1;
FI
IF ACCESS OF SEG.TABLE1^ & %80 = 0
@BOX 5.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 6.1
IF SYS06.READ.SUSP.REASON (SPN) = 0
@BOX 7.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (SPN ->> 9, 14))
   => SEG.VARS2;
IF SEG2 >= FIRST.X.SEG THEN
   ^XST [SEG2 - FIRST.X.SEG] OF SEG.VARS2^
   => SEG.TABLE2;
ELSE
   ^LST [SEG2] OF SEG.VARS2^
   => SEG.TABLE2;
FI
IF ACCESS OF SEG.TABLE2^ & %80 /= 0
@BOX 8.1
LST.ENTRY OF SEG.TABLE1^ => LST.ENTRY OF SEG.TABLE2^;
0 => LST.ENTRY OF SEG.TABLE1^;
@BOX 9.1
IF SEG1 < NO.OF.LOCAL.SEGS THEN
   V.PROCESS.NUMBER * NO.OF.SEGS => PROC.SHIFTED;
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> SEG1,
      DUMMY.SEG + PROC.SHIFTED);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> SEG2, SEG1);
   SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, DUMMY.SEG + PROC.SHIFTED, SEG
2);
FI
@BOX 10.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 12.1
END
@BOX 14.1
-3 => PW0;
@BOX 15.1
-6 => PW0;
@BOX 17.1
-26 => PW0;
@BOX 18.1
-1 => PW0;
@END

@TITLE SYSCMD14.21(5,11)
@COL 1S-3T-2T-7R-4R-5F
@COL 6R

@ROW 7-6

@FLOW 1-3OK-2NO-7-4-5
@FLOW 2YES-6-5
@FLOW 3FAIL-5
@BOX 1.0
CHANGE COMMON SEGMENT (LOCAL SEG, COMMON SEG)
@BOX 2.0
ARE SEGMENT NUMBERS ILLEGAL?
@BOX 3.0
CHECK PROCESS IS PRIVILEGED
[SYS13]
@BOX 7.0
INTERCHANGE SEGMENT TABLE
ENTRIES
@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 CHANGE.COMMON.SEGMENT (LOCAL.SEG, COMMON.SEG);
INTEGER PROC.SHIFTED;
ADDR SEG.VARS C.SEG.VARS;
LST.TYPE TEMP;
0 => PW0;
@BOX 2.1
FIRST.COMMON.SEG -> COMMON.SEG;
IF LOCAL.SEG =< 0 OR COMMON.SEG =< 0
   OR LOCAL.SEG = V.STACK.SEG
   OR LOCAL.SEG >= NO.OF.LOCAL.SEGS
   OR COMMON.SEG >= NO.OF.COMMON.SEGS
@BOX 3.1
SYS13.CHECK.PRIV ();
IF PW0 /= 0
@BOX 7.1
MAKE (SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
LST.ENTRY OF LST [LOCAL.SEG] => LST.ENTRY OF TEMP;
LST.ENTRY OF CST [COMMON.SEG] => LST.ENTRY OF LST [LOCAL.SEG];
LST.ENTRY OF TEMP => LST.ENTRY OF CST [COMMON.SEG];
@BOX 4.1
V.PROCESS.NUMBER * NO.OF.SEGS => PROC.SHIFTED;
SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> LOCAL.SEG,
   DUMMY.SEG + PROC.SHIFTED);
SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, PROC.SHIFTED +> COMMON.SEG,
    LOCAL.SEG);
SYS13.ENTER.INT.LEVEL (^RESET.PAGING.REGISTERS, DUMMY.SEG + PROC.SHIFTED,
    COMMON.SEG);
@BOX 5.1
END
@BOX 6.1
-3 => PW0;
@END

