PROGRAM $M0
B16
1000 VALUE TOTMEMLEN
TOTMEMLEN BYTE VCTR MEMORY
: T-1 D -1 ;
: *4 SHL SHL ;
: &0FF 0FF & ;
: <= 1+ < ;
: >= 1- > ;
[20 WORD VCTR CHAN] [каналы. Начиная с 5-го]
VAR NCHAN [Номер текущего канала]
: !NCHAN ! NCHAN ;
5 VALUE NBASECH [Первый не базовый канал]
: GETDATA NCHAN 10 * + CHDATA ;
: PUTDATA NCHAN 10 * + ! CHDATA ;
[Размер заголовка блока в байтах]
FIX VAR HSIZE 10 ! HSIZE
: HSIZE+ HSIZE + ;
[Pred, Next, BusyLen, Len]
1 *4 VALUE ctfPREDADDR
[$M4] [как самодостаточный]
0 VALUE ctLOWCH [Нижний канал.]
[0=Оперативная/1=Дисковая память/2=Журнал/-1=свободен]
1 VALUE ctTEKADR [Логический адрес внутри участка (по данным)]
2 VALUE ctBUSYLEN [Длина фрагмента, занятая данными]
3 VALUE ctLEN [Максимальная допустимая длина данных фрагмента]
4 VALUE ctTEKADR0 [=TEKADR, когда TEKADR стоит на нулевом байте данных фрагм]
5 VALUE ctNEXTADDR [Адрес начала заголовка следующего фрагмента (пф)]
6 VALUE ctPREDADDR [Адрес начала заголовка предыдущего фрагмента (пф)]
7 VALUE ctSYNCADDR [Адрес начала заголовка фрагмента (пф)]
8 VALUE ctCHGCTX [признак изменения контекста]
9 VALUE ct1STLONG [Первое число в канале]
[в начальном блоке в начальном слове данных лежит адрес начала данных]
: LOWCH ctLOWCH GETDATA ; : !LOWCH ctLOWCH PUTDATA ;
: TEKADR ctTEKADR GETDATA ; : !TEKADR ctTEKADR PUTDATA ;
: TEKADR0 ctTEKADR0 GETDATA ; : !TEKADR0 ctTEKADR0 PUTDATA ;
: TEKADR++ TEKADR 1+ !TEKADR ; : !+TEKADR TEKADR + !TEKADR ;
: BUSYLEN ctBUSYLEN GETDATA ; : !BUSYLEN ctBUSYLEN PUTDATA ;
: LEN ctLEN GETDATA ; : !LEN ctLEN PUTDATA ;
: NEXTADDR ctNEXTADDR GETDATA ; : !NEXTADDR ctNEXTADDR PUTDATA ;
: PREDADDR ctPREDADDR GETDATA ; : !PREDADDR ctPREDADDR PUTDATA ;
: SYNCADDR ctSYNCADDR GETDATA ; : !SYNCADDR ctSYNCADDR PUTDATA ;
: CHGCTX ctCHGCTX GETDATA ; : !CHGCTX ctCHGCTX PUTDATA ;
: FSTLONG ct1STLONG GETDATA ; : !FSTLONG ct1STLONG PUTDATA ;
TRAP NOMEMORY NOMEMORY#
: NOMEMORY# ."
No free memory" ;
TRAP OUTDATA OUTDATA#
: OUTDATA# ."
Out of data. " ;
TRAP OUTMEM OUTMEM#
: OUTMEM# ."
Out of memory. " ;
TRAP UNKCH UNKCH#
: UNKCH# ."
Unknown primitive channel:" NCHAN .D CR ;
TRAP O_NOTFND NOTFND#
: NOTFND# ."
Object not found. OID=" . CR ;
[*** Информация по каналу ***]
: IC CR
." NCHAN=" NCHAN .D SP ." LOWCH=" LOWCH .D CR
."SYNCADDR=" SYNCADDR .D SP ."PREDADDR=" PREDADDR .D SP ."NEXTADDR="
NEXTADDR .D CR
." BUSYLEN=" BUSYLEN .D SP ." LEN=" LEN .D CR
." TEKADR0=" TEKADR0 .D SP ." TEKADR=" TEKADR .D CR ;
CHANNEL DATACH "DATA." CONNECT DATACH
Менеджер виртуальной памяти
PROGRAM $M2
B16 [физическая организация памяти]
[вычисление физического адреса и номера базового канала]
:: : POSIX [addr(i)] NCHAN C NBASECH < BR+ LEAVE [addr nchan] D
GOTO DELTA2 S( NCHAN ) TOLOW POSIX [addr(i-1)] ;
:: : TOLOW LOWCH !NCHAN ;
[Пересчет адреса в адрес нижнего уровня: TEKADR(i) -> TEKADR(i-1)]
:: : DELTA2 SYNCADDR HSIZE + TEKADR TEKADR0 - + ;
:: : IBS EON OUTDATA OUTDATA# LAST?
TEKADR POSIX TEKADR++ S( NCHAN ) !NCHAN BSGOTO
NCHAN BR 0 IBS0 1 IBS1 [2 IBS2] ELSE UNKCH ;
:: : OBS EON OUTDATA OUTDATA# LAST?
TEKADR POSIX TEKADR++ S( NCHAN ) !NCHAN BSGOTO
NCHAN BR 0 OBS0 1 OBS1 [2 OBS2] ELSE UNKCH ;
: LAST? TEKADR BUSYLEN TEKADR0 + = IF0 LEAVE NEXTBLK ;
[переход для базового канала ]
: BSGOTO [ADDR] NCHAN BR 0 BSGOTO0 1 BSGOTO1 [2 BSGOTO2] ELSE UNKCH ;
: BSGOTO0 !TEKADR ;
: BSGOTO1 C !TEKADR HSIZE+ SPOS DATACH ;
[ : BSGOTO2 C !TEKADR HSIZE+ SPOS JOURCH ;]
0 %IF
: ADDR [PARAGRAF OFFSET] + [address] ; [Сейчас пгф=1 байту]
[Для файлов можно сделать неск. файлов и распределить по ним пространство]
%FI
: IBS0 TEKADR HSIZE+ MEMORY &0FF TEKADR++ ;
: IBS1 IB DATACH &0FF TEKADR++ ;
[: IBS2 IB JOURCH &0FF TEKADR++ ;]
: OBS0 &0FF TEKADR HSIZE+ ! MEMORY TEKADR++ ;
: OBS1 &0FF OB DATACH TEKADR++ ; [Запись байта]
[: OBS2 &0FF OB JOURCH TEKADR++ ;] [Запись байта]
:: : GOTO NCHAN NBASECH < BR+ BSGOTO VGOTO ;
: VGOTO TEKADR - @GOTO ;
[Переход по смещению]
:: : @GOTO C BRS @GOTO- D @GOTO+ ;
: @GOTO+ DO @GOTO1+ ;
: @GOTO- NEG DO @GOTO1- ;
: @GOTO1+
EON OUTDATA OUTDATA#
TEKADR TEKADR0 BUSYLEN + =
IF+ NEXTBLK TEKADR 1+ !TEKADR ;
: @GOTO1-
EON OUTDATA OUTDATA#
TEKADR TEKADR0 =
IF+ PREDBLK TEKADR 1- !TEKADR ;
: NEXTBLK CHGCTX IF+ SCTX NEXTADDR NOEXIST? !SYNCADDR RELCTX
TEKADR !TEKADR0 ;
: NOEXIST? [ADDR] C -1 = IF+ OUTDATA [ADDR] ;
[Pred, Next, BusyLen, Len]
:: : LCTX' [UPCH] PUSH TEKADR ILS ILS ILS ILS POP
NCHAN E2 !NCHAN !LOWCH !LEN !BUSYLEN !NEXTADDR !PREDADDR !SYNCADDR
0 !CHGCTX ;
[Грузить параметры канала]
:: : LCTX [newch] LCTX' 0 !TEKADR 0 !TEKADR0 ;
: RELCTX TEKADR0 TEKADR NCHAN SYNCADDR TOLOW GOTO LCTX !TEKADR !TEKADR0 ;
: PREDBLK CHGCTX IF+ SCTX PREDADDR NOEXIST? !SYNCADDR RELCTX
TEKADR BUSYLEN - !TEKADR0 ;
: IBSC [CHAN] S( NCHAN ) !NCHAN IBS ;
: ILSC S( NCHAN ) !NCHAN ILS ;
: OBSC [N CHAN] S( NCHAN ) !NCHAN OBS ;
: IOBSCC [SRC DST] C2 IBSC C2 OBSC ;
: DO_IOBSCC [SRC_CH DST_CH N] S( NCHAN )
C3 !NCHAN 0 GOTO DO IOBSCC [SRC DST] ;
: IWS IBS IBS SWB &0 ;
: ILS IWS IWS SETHI ; [SWW &0]
: OWS C OBS SWB OBS ;
: OLS C OWS SWW OWS ;
[Перейти к конечному блоку]
: GOTOENDBK NEXTADDR -1 = EX+ BUSYLEN TEKADR0 +
NEXTADDR !SYNCADDR RELCTX C !TEKADR0 !TEKADR ;
: GOBOTTOM RP GOTOENDBK BUSYLEN TEKADR0 + GOTO ;
: LENVMEM GOBOTTOM TEKADR [LEN] ; [длина виртуальной памяти]
: LASTADDR SYNCADDR LEN + HSIZE+ ;
: OBS-0 NCHAN BR 0 OBS00 1 OBS01 [2 OBS02] ELSE OBS0N ;
: OBS00 0 OBS0 ; : OBS01 0 OBS1 ; [: OBS02 0 OBS2 ;] : OBS0N 0 OBS ;
[Спецификация: Размер увеличивается на N байт. Если это невозможно,
возникает исключительная ситуация NOMEMORY.
После работы мы стоим в том же канале в начале выделенного пространства. ]
: UPSIZE [N] GOBOTTOM TEKADR E2 UPSIZE' GOTO [] ;
: UPSIZE' [N] GOBOTTOM LEN BUSYLEN - CALCOST [HARD SOFT] UPSIZEI
C BR0 D UPSIZEO ;
: CALCOST [N FREE] C2C2 <= BR+ COST1 COST2 [HARD SOFT] ;
: COST1 [N FREE] T0 E2 [0 N] ;
: COST2 [N FREE] C PUSH - POP [N-FREE FREE] ;
: UPSIZEI [N_SOFT] BUSYLEN + !BUSYLEN 1 !CHGCTX SCTX ;
: UPSIZEO [N_HARD] NCHAN BR 0 USO0 1 USO1 2 USO1 ELSE USON ;
: USO1 C GOBOTTOM TEKADR E2 DO OBS-0 [!TEKADR] BSGOTO
C BUSYLEN + !BUSYLEN LEN + !LEN 1 !CHGCTX SCTX ;
: USO0 NOMEMORY [Сюда можно вставить упаковку] ;
[Спецификация: увеличение размера (жестко, т.е. за счет нижнего уровня)]
: USON [N] SYNCADDR LASTADDR USON1 RELCTX [>] UPSIZE' ;
: USON1 S( NCHAN ) TOLOW BUSYLEN = BR+ USON_ADD USON_NEW ;
[Расширение увеличением длины фрагмента]
: USON_ADD C2 [N SYNCADDR N] UPSIZE' C BUSYLEN E2 - HSIZE - E2
[N LEN SYNCADDR] 3 *4 + GOTO OLS [N] [UPSIZEI] ;
[Расширение созданием нового фрагмента]
: USON_NEW C2 [N SYNCADDR N] [GOBOTTOM] C HSIZE+ UPSIZE'
[N SYNCADDR N] C2 -1 0 C4 TEKADR PUSH WRITECTX D 4+ GOTO POP OLS [N] ;
: WRITECTX [PRED NEXT BUSY LEN] C4 OLS C3 OLS C2 OLS C OLS DD DD ;
FIX VAR UPCONST 10 ! UPCONST [Этому числу байт кратно увеличение]
[Увеличение размера нижнего уровня]
[увеличение физического размера этого уровня]
: SCTX CHGCTX IF0 LEAVE 0 !CHGCTX NCHAN BR 0 NOP 1 SCTX1 [2 SCTX2]
3 NOP 4 NOP ELSE SCTXN ;
: SCTXN TEKADR NCHAN LEN BUSYLEN NEXTADDR
PREDADDR SYNCADDR TOLOW GOTO 4 DO OLS !NCHAN GOTO ;
: SAVEALL NOP ; [СОХРАНИТЬ ВЕСЬ КАНАЛ НА ПЕРВИЧНОМ УСТРОЙСТВЕ (ИСТОЧНИКЕ)]
: SCTX1 POS DATACH 8 SPOS DATACH BUSYLEN OL DATACH LEN OL DATACH SPOS DATACH ;
[
: SCTX2 POS JOURCH 8 SPOS JOURCH BUSYLEN OL JOURCH LEN OL JOURCH SPOS JOURCH ;
]
[Новая виртуальная память]
0 %IF
: NEWVM [N] TEKADR C2 HSIZE+ UPSIZE GOTO -1 -1 C3 C WRITECTX D ;
%FI
: NEWVM [N] C HSIZE+ UPSIZE TEKADR PUSH -1 -1 0 C4 WRITECTX DO OBS-0
POP [SYNCADR] ;
: END? NEXTADDR -1 = TEKADR BUSYLEN TEKADR0 + = & ;
: NEWVM1 [N] C HSIZE+ UPSIZE TEKADR PUSH -1 -1 E3 C WRITECTX WRI_DATA
POP [SYNCADR] ;
: LOADCH0 0 !NCHAN 0 !LOWCH 0 !TEKADR 0 !BUSYLEN
TOTMEMLEN !LEN 0 !TEKADR0 0 !SYNCADDR -1 !NEXTADDR -1 !PREDADDR ;
[ДЛЯ БАЗОВЫХ КАНАЛОВ LOWCH=NCHAN]
Дата: 2019-05-28, просмотров: 234.