home *** CD-ROM | disk | FTP | other *** search
- title block storage manager
- include asm.inc
-
- public block_alloc
- public block_file_open
- public block_file_read
- public block_free
- public block_read
-
- BLOCK_MAX equ 512
- FIRST_BLOCK equ 08000h ; block handles start at 0x8000
-
- NULL_BLOCK equ 0
- NULL_EMS equ 0
- NULL_ID equ 0
- NULL_SWAP equ 0
-
- OPEN_LINK equ 0FFFFh
-
- block_str struc
- blk_forward dw ? ; forward link for LRU
- blk_backward dw ? ; backward link
- blk_pointer dd ? ; RAM address (or 0 if in EMS or DISK)
- blk_ems_index dw ? ; EMS index
- blk_swap_index dw ? ; swap file index (0 if not swapped)
- blk_file_id dw ? ; file identification (0 if not in file)
- blk_file_index dw ? ; file block index
- blk_file_link dw ? ; blocks for each file form a list
- blk_byte_count dw ? ; (file blocks may be less than 16k)
- block_str ends ; (structure must be even number of bytes)
-
-
- XIB segment word public 'DATA' ; initialize block manager
- XIB ends
- XI segment word public 'DATA'
- dw block_preset
- XI ends
- XIE segment word public 'DATA'
- XIE ends
-
-
- .const
- ertx_block_handle db 'Bad block handle',0
- ertx_empty_file db 'Cannot map empty file',0
- ertx_free_block db 'Cannot free block',0
- ertx_past_eof db 'Block read past EOF',0
- ertx_virtual_full db 'Virtual memory full',0
-
-
- .data?
- block_table dd ? ; array of block structures
-
- ram_front dw ? ; LRU list of RAM blocks
- ram_back dw ?
-
- ems_front dw ? ; LRU list of EMS blocks
- ems_back dw ?
-
- free_front dw ? ; free handle stack
- free_count dw ? ; number of free blocks
-
- file_blocks dw ? ; # of blocks in file (see block_file_open)
-
- .code
- extn abort_if_cf,calloc,clear_strerror,ems_exchange,ems_in,swap_in
- extn ems_out,free,malloc,save_most,set_strerror,swap_out,check_block_file
- extn open_block_file,read_block_file,set_block_handle
-
- page
- ;; access block table
- ;
- ; entry BX block handle
- ; exit DS:SI block table entry for handle
- ; Cf if bad handle
- ; uses AX
- ;
- access_block_table proc
- mov ax,bx
- sub ax,FIRST_BLOCK
- jb abt1 ; if bad handle
- cmp ax,BLOCK_MAX
- jae abt1 ; if bad handle
- mov si,dx
- mov dx,size block_str
- mul dx
- mov dx,si
-
- lds si,block_table[bp]
- add si,ax
- ret
-
- abt1: lea ax,ertx_block_handle ; *Bad block handle*
- jmp set_strerror
- access_block_table endp
-
-
- ;; block alloc
- ;
- ; exit AX block size in bytes
- ; BX block handle
- ; ES:DI block pointer
- ; Cf if no memory
- ;
- block_alloc proc
- pushm si,ds
- call malloc_storage_block
- jc bal2 ; if no memory
-
- call new_block_handle
- jc bal1 ; if no more block handles
- mov wptr blk_pointer[si],di
- mov wptr blk_pointer[si+2],es
-
- call set_mru_ram ; set most recently used
- mov ax,BLOCK_SIZE
- mov blk_byte_count[si],ax
- clc
- jmp bal3
-
- bal1: call free ; here when out of handles, free
- bal2: movx bx,NULL_BLOCK ; storage and return error
- stc
-
- bal3: popm ds,si
- ret
- block_alloc endp
-
-
- ;; block file open
- ;
- ; entry DS:SI file name
- ; exit AX file size in blocks
- ; BX block handle
- ; Cf if file not found or empty
- ;
- block_file_open proc
- pushm cx,dx,di,si,ds
- call check_block_file
- jnc bfo4 ; if existing file
-
- bfo1: call open_block_file
- jc bfo4 ; if file not found
- jcxz bfo7 ; if empty file
-
- cmp cx,free_count[bp]
- ja bfo5 ; if not enough blocks for file
-
- mov file_blocks[bp],cx
- movx cx,0
-
- call new_file_block ; allocate first file block
- jc bfo4
- mov bx,ax
- cmp cx,file_blocks[bp]
- je bfo3 ; if file size <= 16k
-
- bfo2: mov di,si
- call new_file_block
- jc bfo4
- mov blk_file_link[di],si
- cmp cx,file_blocks[bp]
- jb bfo2
-
- call set_block_handle ; save handle in case we open again
-
- bfo3: mov ax,file_blocks[bp] ; return file size (Cf unchanged)
-
- bfo4: popm ds,si,di,dx,cx
- ret
-
- bfo5: lea ax,ertx_virtual_full ; *Virtual memory full*
- bfo6: call set_strerror
- jmp bfo4
- bfo7: lea ax,ertx_empty_file ; *Cannot map empty file*
- jmp bfo6
- block_file_open endp
-
-
- ;; block file read
- ;
- ; entry AX 16k file block number (0..n)
- ; BX block index
- ; exit DS:SI block pointer
- ; AX block size (<16k if last block)
- ; Cf if bad block index or past end of file
- ;
- block_file_read proc
- push cx
- mov cx,ax
- call access_block_table
- jc bfr4
-
- jcxz bfr2 ; if first block
- bfr1: mov si,blk_file_link[si] ; else chase linked list to
- cmp si,OPEN_LINK ; selected blk
- loopne bfr1
- je bfr3 ; if block number too large
-
- bfr2: pop cx
- jmp block_read_primitive
-
- bfr3: lea ax,ertx_past_eof ; *Block read past EOF*
- call set_strerror
- bfr4: pop cx
- ret
- block_file_read endp
-
-
- ;; block free
- ;
- ; entry BX block index
- ; exit Cf if bad index (cannot free file blocks)
- ; uses AX,BX
- ;
- block_free proc
- pushm di,si,ds,es
- call access_block_table
- jc bfe5
-
- cmp blk_file_id[si],NULL_ID ; illegal to free a file block
- jne bfe6 ; if file block
-
- les di,blk_pointer[si]
- mov ax,es
- or ax,di
- jz bfe1 ; if not in RAM
-
- call unlink_ram_list ; unlink block from RAM LRU list
- call free ; free storage
- jmp bfe3
-
- bfe1: mov ax,blk_ems_index[si]
- cmpx ax,NULL_EMS
- je bfe2 ; if not in EMS
-
- call ems_in ; free EMS block (ES:DI==NULL)
- call unlink_ems_list ; unlink block from EMS LRU list
- jmp bfe3
-
- bfe2: mov ax,blk_swap_index[si]
- cmpx ax,NULL_SWAP
- je bfe6 ; if not in swap file (thus error)
-
- call swap_in ; free swap block (ES:DI==NULL)
-
- bfe3: mov bx,size block_str ; clear block table entry and
- bfe4: dec bx ; leave BX==0
- dec bx
- mov wptr [si+bx],ZER0
- jnz bfe4
-
- mov ax,si ; link onto free block stack
- xchg ax,free_front[bp]
- mov blk_backward[si],ax
- inc free_count[bp]
-
- clc
- bfe5: popm es,ds,si,di ; (POP xS could fault in protect mode)
- ret
-
- bfe6: lea ax,ertx_free_block ; *Cannot free block*
- call set_strerror
- jmp bfe5
- block_free endp
-
-
- ;; block preset
- ;
- ; uses AX
- ;
- block_preset proc
- call save_most ; allocate block table
- mov cx,BLOCK_MAX*size block_str
- call calloc ; (must have NULL offset)
- call abort_if_cf
- mov wptr block_table[bp],di
- mov wptr block_table[bp+2],es
-
- mov ax,OPEN_LINK ; build free list
- mov cx,BLOCK_MAX
- mov free_count[bp],cx
- lds si,block_table[bp]
- mov free_front[bp],si
- bps1: lea dx,[si+size block_str]
- mov blk_backward[si],dx
- mov blk_forward[si],ax
- mov blk_file_link[si],ax
- xchg dx,si
- loop bps1
- mov blk_backward[si-size block_str],ax
-
- mov ram_front[bp],ax ;\initialize LRU lists for RAM and EMS
- mov ram_back[bp],ax
- mov ems_front[bp],ax
- mov ems_back[bp],ax
- ret
- block_preset endp
-
-
- ;; block read
- ;
- ; entry BX block index
- ; exit AX block size
- ; DS:SI block pointer
- ; Cf if bad block or no memory
- ;
- block_read proc
- call access_block_table
- jnc block_read_primitive ;\
- ret ;\
- block_read endp
-
-
- ;; block read primitive
- ;
- ; entry DS:SI block table pointer
- ; exit AX block size
- ; DS:SI block pointer
- ; Cf if bad block or no memory
- ;
- block_read_primitive proc
- pushm di,es
- cmp wptr blk_pointer[si+2],NULL_POINTER
- je brp1 ; if block is not in RAM
- call reset_mru_ram ; move to front of LRU list
- jmp brp5
-
- brp1: call malloc_storage_block ; allocate storage for block
- jc brp6 ; if no memory
-
- mov ax,blk_ems_index[si] ; check if block swapped to EMS
- cmpx ax,NULL_EMS
- je brp2 ; if not in EMS
-
- call ems_in ; else swap block in from EMS
- jc brp8 ; if unexpected EMS error
-
- call unlink_ems_list ; delete from EMS LRU list
- mov blk_ems_index[si],NULL_EMS
- jmp brp4
-
- brp2: cmp blk_file_id[si],NULL_ID ; check if file block
- je brp3 ; if not
-
- push bx ; else read block from file
- mov bx,blk_file_id[si]
- mov ax,blk_file_index[si]
- call read_block_file
- pop bx
- jc brp8 ; if error reading file
- mov blk_byte_count[si],ax
- jmp brp4 ; else read OK
-
- brp3: mov ax,blk_swap_index[si] ; check if block swapped out
- cmpx ax,NULL_SWAP
- je brp7 ; if not swapped - bad block handle
- call swap_in
- jc brp8 ; if error swapping block in
- mov blk_swap_index[si],NULL_SWAP
-
- brp4: mov wptr blk_pointer[si],di ; save RAM pointer in block table
- mov wptr blk_pointer[si+2],es
- call set_mru_ram ; move to front of LRU list
-
- brp5: mov ax,blk_byte_count[si] ; return RAM pointer and byte count
- lds si,blk_pointer[si]
- clc
- brp6: popm es,di
- ret
-
- brp7: lea ax,ertx_block_handle ; *Bad block handle*
- call set_strerror
-
- brp8: call free
- stc
- jmp brp6
- block_read_primitive endp
-
-
- ;; free ram block
- ;
- ; exit Cf if no RAM free
- ; uses AX
- ;
- free_ram_block proc
- call save_most
- call get_lru_ram ; get least recently used memory block
- jc frb4 ; if no blocks on LRU list
-
- les di,blk_pointer[si] ; else file block, swap to EMS
- call ems_out
- jc frb2 ; if unable to swap to EMS
- mov blk_ems_index[si],ax ; else save EMS page index
- call set_mru_ems
-
- frb1: call free ; free storage
- jc frb4 ; if unexpected error
- mov wptr blk_pointer[si],di ; (free returns with ES:DI==NULL)
- mov wptr blk_pointer[si+2],es
- jmp frb4
-
- frb2: call clear_strerror ; here when EMS is full
- cmp blk_file_id[si],NULL_ID ; is block file or storage?
- jne frb1 ; if file block - just free its ram
-
- mov bx,si ; try exchanging RAM block & LRU EMS
- call get_lru_ems
- jc frb3 ; if no EMS (SI still -> RAM block)
- mov ax,blk_ems_index[si]
- call ems_exchange ; (ES:DI still points to RAM block)
- jc frb4 ; if exchange failed (serious error)
-
- movx ax,NULL_EMS ; exchange EMS index and RAM pointers
- xchg ax,blk_ems_index[si] ; for exchanged blocks
- mov blk_ems_index[bx],ax
- mov wptr blk_pointer[bx],NULL_POINTER
- mov wptr blk_pointer[bx+2],NULL_POINTER
- mov wptr blk_pointer[si],di
- mov wptr blk_pointer[si+2],es
-
- xchg bx,si ; set most recently used EMS block
- call set_mru_ems
- xchg bx,si
-
- frb3: call swap_out ; write block to swap file
- mov blk_swap_index[si],ax ; set swap index (or 0 if failure)
- jnc frb1 ; if swapped OK
-
- call set_lru_ram ; swap failed, re-link RAM block
- movx bx,NULL_BLOCK
- stc
-
- frb4: ret
- free_ram_block endp
-
-
- ;; get lru ems
- ;
- ; exit DS:SI least recently used block in EMS
- ; Cf if no blocks in EMS (SI unchanged)
- ; uses AX
- ;
- get_lru_ems proc
- mov ax,OPEN_LINK
- cmp ax,ems_back[bp]
- je gle2 ;\ if no EMS blocks
-
- lds si,block_table[bp]
- mov si,ems_back[bp]
- cmp si,ems_front[bp]
- je gle1 ; if only one EMS block
-
- push bx
- mov bx,blk_forward[si]
- mov blk_backward[bx],ax
- mov ems_back[bp],bx
- pop bx
- clc
- ret
-
- gle1: mov ems_front[bp],ax
- mov ems_back[bp],ax
- ret ; (Cf==0)
-
- gle2: stc
- ret
- get_lru_ems endp
-
-
- ;; get lru ram
- ;
- ; exit DS:SI least recently used block in RAM
- ; Cf if no unlocked blocks in RAM
- ; uses AX
- ;
- get_lru_ram proc
- mov ax,OPEN_LINK
- lds si,block_table[bp]
- mov si,ram_back[bp]
- cmp si,ax
- je glr2 ; if no RAM blocks
- cmp si,ram_front[bp]
- je glr1 ; if only one RAM block
-
- push bx
- mov bx,blk_forward[si]
- mov blk_backward[bx],ax
- mov ram_back[bp],bx
- pop bx
- clc
- ret
-
- glr1: mov ram_front[bp],ax
- mov ram_back[bp],ax
- ret ; (Cf==0)
-
- glr2: stc
- ret
- get_lru_ram endp
-
-
- ;; malloc storage block
- ;
- ; exit ES:DI storage block
- ; Cf if unable to allocate storage
- ; uses AX
- ;
- malloc_storage_block proc
- push cx
- mov cx,BLOCK_SIZE ; allocate block of memory
- call malloc
- jnc msb1 ; if OK
-
- call clear_strerror ; clear malloc error
- call free_ram_block ; swap to EMS or disk to free ram
- jc msb1 ; if too many locked blocks
-
- call malloc ; try malloc one more time
-
- msb1: pop cx
- ret
- malloc_storage_block endp
-
-
- ;; new block handle
- ;
- ; exit BX block handle
- ; DS:SI block table entry
- ; Cf if no free handles
- ; uses AX
- ;
- new_block_handle proc
- lds si,block_table[bp] ; get first block from free list
- mov si,free_front[bp]
- cmp si,OPEN_LINK
- je nbh1 ; if no more handles
- mov ax,blk_backward[si]
- mov free_front[bp],ax
- dec free_count[bp]
-
- push dx ; compute handle from table offset
- mov ax,si
- movx dx,0
- mov bx,size block_str
- div bx
- add ax,FIRST_BLOCK
- mov bx,ax
- pop dx
- ret
-
- nbh1: lea ax,ertx_virtual_full ; *Virtual memory full*
- jmp set_strerror
- new_block_handle endp
-
-
- ;; new file block
- ;
- ; entry CX block number
- ; DX file id
- ; exit AX block handle
- ; CX +1
- ; DS:SI block table entry
- ; Cf if no more blocks
- ;
- new_file_block proc
- push bx
- call new_block_handle ; allocate block
- jc nfb1 ; if no more blocks
-
- mov blk_file_id[si],dx ; set file id and block number
- mov blk_file_index[si],cx
- inc cx
-
- mov ax,OPEN_LINK ; reset links
- mov blk_file_link[si],ax
- mov blk_forward[si],ax
- mov blk_backward[si],ax
-
- mov ax,bx ;\
- nfb1: pop bx
- ret
- new_file_block endp
-
-
- ;; reset mru ram
- ;
- ; entry DS:SI most recently used table entry
- ; uses AX
- ;
- reset_mru_ram proc
- cmp si,ram_front[bp]
- je rmr4 ; if already most recently used
-
- push bx
- cmp si,ram_back[bp]
- je rmr1 ; if least recently used
-
- mov ax,blk_forward[si] ; delete from middle of LRU list
- mov bx,blk_backward[si]
- mov blk_forward[bx],ax
- xchg ax,bx
- mov blk_backward[bx],ax
- jmp rmr2
-
- rmr1: call get_lru_ram ; delete from back of LRU list
- jc rmr3 ; if internal error
- rmr2: call set_mru_ram
- clc
- rmr3: pop bx
- rmr4: ret
- reset_mru_ram endp
-
-
- ;; set lru ram
- ;
- ; entry DS:SI least recently used table entry
- ; uses AX,BX
- ;
- set_lru_ram proc
- mov ax,OPEN_LINK ; check for empty list
- mov bx,si
- xchg bx,ram_back[bp]
- cmp bx,ax
- je slr1 ; if empty list
-
- mov blk_backward[si],ax ; else link onto back of list
- mov blk_forward[si],bx
- mov blk_backward[bx],si
- ret
-
- slr1: mov ram_front[bp],si ; create list with one element
- mov blk_forward[si],ax
- mov blk_backward[si],ax
- ret
- set_lru_ram endp
-
-
- ;; set mru ems
- ;
- ; entry DS:SI most recently used table entry
- ; uses AX
- ;
- set_mru_ems proc
- push bx
- mov ax,OPEN_LINK ; check for empty list
- mov bx,si
- xchg bx,ems_front[bp]
- cmp bx,ax
- je sme1 ; if empty list
-
- mov blk_forward[si],ax ; else link onto front of list
- mov blk_backward[si],bx
- mov blk_forward[bx],si
- pop bx
- ret
-
- sme1: mov ems_back[bp],si ; create list with one element
- mov blk_forward[si],ax
- mov blk_backward[si],ax
- pop bx
- ret
- set_mru_ems endp
-
-
- ;; set mru ram
- ;
- ; entry DS:SI most recently used table entry
- ; uses AX
- ;
- set_mru_ram proc
- push bx
- mov ax,OPEN_LINK ; check for empty list
- mov bx,si
- xchg bx,ram_front[bp]
- cmp bx,ax
- je smr1 ; if empty list
-
- mov blk_forward[si],ax ; else link onto front of list
- mov blk_backward[si],bx
- mov blk_forward[bx],si
- pop bx
- ret
-
- smr1: mov ram_back[bp],si ; create list with one element
- mov blk_forward[si],ax
- mov blk_backward[si],ax
- pop bx
- ret
- set_mru_ram endp
-
-
- ;; unlink ems list
- ;
- ; entry DS:SI block table entry
- ; uses AX
- ;
- unlink_ems_list proc
- cmp si,ems_back[bp]
- je uel1 ; if EMS block is LRU
-
- push bx
- cmp si,ems_front[bp]
- je uel2 ; if EMS block is MRU
-
- mov ax,blk_forward[si] ; delete from middle of LRU list
- mov bx,blk_backward[si]
- mov blk_forward[bx],ax
- xchg ax,bx
- mov blk_backward[bx],ax
- jmp uel3
-
- uel1: jmp get_lru_ems
-
- uel2: mov bx,blk_backward[si] ; delete from front of LRU list
- mov blk_forward[bx],OPEN_LINK
- mov ems_front[bp],bx
-
- uel3: pop bx
- ret
- unlink_ems_list endp
-
-
- ;; unlink ram list
- ;
- ; entry DS:SI block table entry
- ; uses AX
- ;
- unlink_ram_list proc
- cmp si,ram_back[bp]
- je url1 ; if RAM block is LRU
-
- push bx
- cmp si,ram_front[bp]
- je url2 ; if RAM block is MRU
-
- mov ax,blk_forward[si] ; delete from middle of LRU list
- mov bx,blk_backward[si]
- mov blk_forward[bx],ax
- xchg ax,bx
- mov blk_backward[bx],ax
- jmp url3
-
- url1: jmp get_lru_ram
-
- url2: mov bx,blk_backward[si] ; delete from front of LRU list
- mov blk_forward[bx],OPEN_LINK
- mov ram_front[bp],bx
-
- url3: pop bx
- ret
- unlink_ram_list endp
-
- end
-