@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             SYS111
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS111
~M~OSYS IMPLEMENTATION DESCRIPTION
~
~M~OSection 11 Version 1
~S1~OSection 11.1 Virtual Machine Timer
~S1~O1. General Description
~BThis module services the virtual machine timer interrupt
generated at the end of the process' time slice, and maintains
all of the process-based timers. It is responsible for trapping a process
which overruns either its total CPU time allocation or its local
timer limit, and for triggering the process scheduler on each timer interrupt
to inform that rescheduling is necessary.
~S1~O2. Interfaces
~
~T^ 4
Other modules used~
^Section 06 (Process Scheduler)~
^Section 10 (Virtual Machine Interrupts)~
^Section 13 (Process Management)~
Hardware registers used~
^V.VM.TIMER~
Command level interface procedures~
^INIT.TIMER (SPN, LIMIT)~
^READ.PROC.TIMER(SPN)CPU.USED~
Organisational Commands~
^SET.TIMER (TIME)~
^READ.TIMER ()~
Data types~
   TIMER.VARS~
Configuration parameters~
   TRAPPING.CPU~
   ABORT.CPU~
   INITIAL.TIMER~
~S1~O2.1 Hardware Interface
~BThe virtual machine timer is controlled by a register V.VM.Timer,
which measures the time (milliseconds) available in the current time slice.
It is set when the process is scheduled and is decremented  on a short, fixed ti
me basis,
provided the process is running at user or command level.
When it falls to zero, a process-based interrupt is either generated
or remains pending until the process next returns to user mode.
~BV.VM.TIMER is preserved in the Process Register Block
 on entry to interrupt mode and is reloaded on exit. This implies that
the time spent in interrupt mode is not accounted to the user.
~BThe register V.VM.TIMER is accessed indirectly
via the dumped copy in the Process Register Block.
~S1~O2.2 Software Interface
~
1) INIT.TIMER (SPN, LIMIT)
~BThis procedure is used to initialise the timers for a newly created
process. LIMIT is the maximum amount of CPU time to be allocated to
the process, and should normally include a standard amount (TRAPPING.CPU
+ ABORT.CPU) for use should it be necessary to trap the process
for exceeding its CPU allocation.
~S12) TIMER.VARS
~BThis data type defines the structure of the timer data area in
the Process Register Block. It is only used by the Process Manager,
in declaring the structure of the Process Register Block.
~S13) TRAPPING.CPU
~BThis literal specifies the amount of a process' total CPU allocation
which is reserved by INIT.TIMER for use in trapping a process for
exceeding its CPU allocation.
~S14) ABORT.CPU
~BThis literal specifies the amount of a process' total CPU allocation
reserved by INIT.TIMER for use in aborting a process in the event of
its using up all of its CPU allocation including that set aside for
trapping.
~S15) INITIAL.TIMER
~BThis literal specifies the value of the time slice quantum, in milliseconds.
~S16) READ.PROC.TIMER(SPN)CPU USED
~BThis procedure returns the CPU time used by the specified process.
~P
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BThere are two software timers associated with every process: the CPU
balance and the local timer. The CPU balance is an absolute limit
on the total CPU time available to the process; it is set initially
by INIT.TIMER and cannot subsequently be reset by the process. Once
its CPU balance is exhausted, the process will be aborted.
~BThe local timer is under the control of the process through the organisational
commands SET.TIMER and READ.TIMER. It can be set to any value less than
or equal to the remaining CPU balance, and a process based interrupt
is generated when it falls to zero. On the occurrence of this interrupt,
any units remaining in the CPU balance are transferred automatically
to the local timer.
~S1~O3.2 Data Structures
~
~T% 15
~
TIMER.VARS~Ia field in the process register block containing the timer variables
for the process.~
CPU.LIMIT~Ithe CPU limit for the process (fixed) - in TIMER.VARS.~
CPU.BALANCE~Ithe remaining CPU balance for the process - in TIMER.VARS.~
LOCAL.TIMER~Ithe local timer for the process - in TIMER.VARS.~
EXTRA.CPU~Ithe allocation set aside for trapping the process - in TIMER.VARS.~
TIME.REQUESTED~Ivalue set in local.timer by SET.TIMER() - in TIMER.VARS.~
~S1~O3.3 Special Notes
~BNone
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H                SYS111
~V9 -1
~F
@TITLE SYS11(1,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
VIRTUAL MACHINE TIMER
@BOX 4.0
PROCEDURES IN MODULE:
   INT1 VIRTUAL MACHINE TIMER INTERRUPT
   INT2 ALLOCATE TIME SLICE
   CMD1 INITIALISE TIMER
   CMD2 SET TIMER
   CMD3 READ TIMER
   CMD4 READ PROC TIMER
@BOX 6.0
END
@BOX 1.1
#SYS11/1
MODULE SYS11 (VM.TIMER.INTERRUPT, INIT.TIMER,
   SET.TIMER, READ.TIMER, READ.PROC.TIMER,
   ALLOCATE.TIMESLICE, TIMER.VARS);
@BOX 2.1
TYPE TIMER.VARS IS
   INTEGER32 CPU.LIMIT, CPU.BALANCE, LOCAL.TIMER, EXTRA.CPU, TIME.REQUESTED;
@BOX 3.1
*GLOBAL 5;
INTEGER INITIAL.TMR;
INTEGER32 MS.ABORT.CPU;
@BOX 4.1
::*INIT %6000;
*CODE 2;
PSPEC VM.TIMER.INTERRUPT ();
PSPEC ALLOCATE.TIMESLICE (INTEGER, INTEGER);
   #SYSINT11.1
   #SYSINT11.2
::*INIT %7000;
*CODE 19;
PSPEC INIT.TIMER (ADDR TIMER.VARS, INTEGER);
PSPEC READ.PROC.TIMER (INTEGER) / INTEGER;
   #SYSCMD11.1
   #SYSCMD11.4
*CODE 21;
LSPEC SET.TIMER (INTEGER32);
LSPEC READ.TIMER ();
   #SYSCMD11.2
   #SYSCMD11.3
@BOX 5.1
*CODE 7;
INITIAL.TIMER => INITIAL.TMR;
1000 * ABORT.CPU => MS.ABORT.CPU;
SYS23.NOTE.OP.PARAM (%1101, ^INITIAL.TMR);
@BOX 6.1
*END
@END
@TITLE SYS11/1(1,11)
@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS06 PROCESS SCHEDULER
SYS10 VIRTUAL MACHINE INTERRUPTS
SYS13 PROCESS MANAGER
@BOX 1.1
:: EXTERNAL ENVIRONMENT
@BOX 2.1
IMPORT LITERAL INITIAL.TIMER, ABORT.CPU, TRAPPING.CPU, CPU.RUNOUT,
   DEFAULT.CPU, DUMPED.V.VM.TIMER.REG.NO, REG.DUMP.SIZE;
@BOX 4.1
PSPEC SYS06.TIMESLICE.END ();
PSPEC SYS10.SET.VM.INT (INTEGER, LOGICAL);
PSPEC SYS13.INT.GET.PRB (INTEGER) / ADDR;
PSPEC SYS13.GET.ACTIVITY.PRB (INTEGER, INTEGER) / ADDR;
PSPEC SYS13.GET.PRB (INTEGER, INTEGER) / ADDR;
PSPEC SYS23.NOTE.OP.PARAM (INTEGER, ADDR INTEGER);
ADDR PW0, PW1, PW2, PW3, PW4;
@END
@TITLE SYSINT11.1(1,11)
@COL 1S-15R-3T-4T-5N-6T-7R-8N-9R-11F
@COL 12R-13R-14N
@ROW 8-14
@ROW 5-12
@ROW 7-13
@FLOW 1-15-3NO-4NO-5-6NO-7-8-9-11
@FLOW 3YES-8
@FLOW 4YES-12-14-8
@FLOW 6YES-13-14
@BOX 1.0
VIRTUAL MACHINE TIMER INTERRUPT
@BOX 3.0
IS LOCAL TIMER POSITIVE?
@BOX 4.0
IS CPU BALANCE POSITIVE?
@BOX 6.0
HAS EXTRA CPU BEEN ALLOCATED?
@BOX 7.0
ALLOCATE EXTRA CPU TIME
AND TRAP THE PROCESS
[SYS10]
@BOX 9.0
TIME SLICE END
[SYS06]
@BOX 11.0
END
@BOX 12.0
ALLOCATE REMAINING CPU TIME
AND TRAP THE PROCESS [SYS10]
@BOX 13.0
ALLOCATE ABORT CPU TIME
AND ABORT THE PROCESS
[SYS10]
@BOX 15.0
SELECT CURRENT PRB
[SYS13]
@BOX 1.1
PROC VM.TIMER.INTERRUPT;
ADDR TIMER.VARS C.TIMER.VARS;
@BOX 3.1
IF LOCAL.TIMER > 0
@BOX 4.1
IF CPU.BALANCE > 0
@BOX 6.1
IF EXTRA.CPU = 0
@BOX 7.1
EXTRA.CPU +> LOCAL.TIMER;
0 => EXTRA.CPU;
SYS10.SET.VM.INT (1, CPU.RUNOUT);
@BOX 9.1
SYS06.TIMESLICE.END ();
@BOX 11.1
END
@BOX 12.1
CPU.BALANCE => LOCAL.TIMER => TIME.REQUESTED;
0 => CPU.BALANCE;
SYS10.SET.VM.INT (2, LOCAL.TIMER);
@BOX 13.1
MS.ABORT.CPU => LOCAL.TIMER;
SYS10.SET.VM.INT (-1, CPU.RUNOUT);
@BOX 15.1
MAKE (TIMER.VARS, 0, SYS13.INT.GET.PRB (11)) => C.TIMER.VARS;
SELECT C.TIMER.VARS^;
@END
@TITLE SYSINT11.2(1.11)

@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
ALLOCATE TIME SLICE (ACTIVITY, TIME)
@BOX 2.0
SELECT PRB
@BOX 3.0
UPDATE LOCAL TIMER AND
SET VM TIMER
@BOX 4.0
END
@BOX 1.1
PROC ALLOCATE.TIMESLICE (ACTIVITY, TIME);
ADDR [LOGICAL] REG.DUMP;
ADDR TIMER.VARS C.TIMER.VARS;
INTEGER TEMP;
@BOX 2.1
MAKE (TIMER.VARS, 0, SYS13.GET.ACTIVITY.PRB (ACTIVITY, 11)) => C.TIMER.VARS;
MAKE (LOGICAL, REG.DUMP.SIZE, SYS13.GET.ACTIVITY.PRB (ACTIVITY, 13)) => REG.DUMP
;
SELECT C.TIMER.VARS^;
@BOX 3.1
INITIAL.TMR *> TIME;
REG.DUMP^ [DUMPED.V.VM.TIMER.REG.NO] => TEMP;
TEMP +> LOCAL.TIMER;
IF TIME > LOCAL.TIMER THEN
   LOCAL.TIMER => TIME
FI
TIME => REG.DUMP^ [DUMPED.V.VM.TIMER.REG.NO];
TIME -> LOCAL.TIMER;
@BOX 4.1
END
@END

@TITLE SYSCMD11.1(1,11)
@COL 1S-4R-2R-3F
@FLOW 1-4-2-3
@BOX 1.0
INITIALISE TIMER (PROCESS NO, LIMIT)
@BOX 2.0
SET VALUES OF LOCAL TIMER,
CPU LIMIT AND BALANCE
@BOX 3.0
END
@BOX 4.0
SELECT PRB
[SYS13]
@BOX 1.1
PROC INIT.TIMER (C.TIMER.VARS, LIMIT);
@BOX 2.1
(IF LIMIT =< 0 THEN DEFAULT.CPU ELSE LIMIT) * 1000 => CPU.LIMIT;
0 => CPU.BALANCE;
1000 * TRAPPING.CPU => EXTRA.CPU;
CPU.LIMIT - EXTRA.CPU - MS.ABORT.CPU => LOCAL.TIMER => TIME.REQUESTED;
@BOX 3.1
END
@BOX 4.1
SELECT C.TIMER.VARS^;
@END
@TITLE SYSCMD11.2(1,11)
@COL 1S-4R-2R-3F
@FLOW 1-4-2-3
@BOX 1.0
SET TIMER (TIME)
@BOX 2.0
SET LOCAL TIMER TO THE MINIMUM
OF TIME AND CPU BALANCE
@BOX 3.0
END
@BOX 4.0
SELECT CURRENT PRB
[SYS13]
@BOX 1.1
PROC SET.TIMER (TIME);
ADDR TIMER.VARS C.TIMER.VARS;
0 => PW0;
@BOX 2.1
IF LOCAL.TIMER +> CPU.BALANCE < TIME THEN
   CPU.BALANCE => TIME;
FI
TIME => LOCAL.TIMER => TIME.REQUESTED -> CPU.BALANCE;
@BOX 3.1
END
@BOX 4.1
MAKE (TIMER.VARS, 0, SYS13.GET.PRB (-1, 11)) => C.TIMER.VARS;
SELECT C.TIMER.VARS^;
@END
@TITLE SYSCMD11.3(1,11)
@COL 1S-4R-2R-3F
@FLOW 1-4-2-3
@BOX 1.0
READ TIMER
@BOX 2.0
READ VALUES OF CPU LIMIT AND CPU USED
@BOX 3.0
END
@BOX 4.0
SELECT CURRENT PRB
[SYS13]
@BOX 1.1
PROC READ.TIMER;
ADDR TIMER.VARS C.TIMER.VARS;
ADDR [LOGICAL] REG.DUMP;
INTEGER TEMP;
0 => PW0;
@BOX 2.1
REG.DUMP^ [DUMPED.V.VM.TIMER.REG.NO] => TEMP;
CPU.LIMIT - MS.ABORT.CPU - EXTRA.CPU - LOCAL.TIMER - CPU.BALANCE
   - TEMP / 1000 => PW1;
CPU.LIMIT => PW2;
TIME.REQUESTED - LOCAL.TIMER - TEMP => PW3;
TIME.REQUESTED => PW4;
@BOX 3.1
END
@BOX 4.1
MAKE (LOGICAL, REG.DUMP.SIZE, SYS13.GET.PRB (-1, 13)) => REG.DUMP;
MAKE (TIMER.VARS, 0, SYS13.GET.PRB (-1, 11)) => C.TIMER.VARS;
SELECT C.TIMER.VARS^;
@END
@TITLE SYSCMD11.4(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3

@BOX 1.0
READ PROC TIMER (SPN)
@BOX 2.0
RETURN CPU TIME
USED BY THE PROCESS
@BOX 3.0
END
@BOX 1.1
PROC READ.PROC.TIMER (SPN);
ADDR TIMER.VARS C.TIMER.VARS;
@BOX 2.1
MAKE (TIMER.VARS, 0, SYS13.GET.PRB (SPN, 11)) => C.TIMER.VARS;
SELECT C.TIMER.VARS^;
CPU.LIMIT - MS.ABORT.CPU - EXTRA.CPU - LOCAL.TIMER - CPU.BALANCE / 1000
   => READ.PROC.TIMER;
@BOX 3.1
END
@END


