⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gshare2.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:

					;---------------------------------------
					; (SI) points to a free block.
					;    We coalesce it by changing the size.
					;---------------------------------------
   cmp	si,di
   jz	gcm15				; do NOT coalesce a block with itself
   add	[di].mft_len,cx 		; coalesce
gcm15:
   add	si,cx				; skip the empty one
   JMP	SHORT gcm1
					;---------------------------------------
					; (SI) points to a non-free,
					;	non-last block.
					; (DI) points to the beginning of a
					;	 free block.
					;
					; We move the non-free block down over
					;   the free block
					;---------------------------------------
gcm2: cmp si,di
   jnz	gcm3				; have to copy

					;---------------------------------------
					; SI = DI => we are at a boundary
					;	     between allocated blocks.
					;	     We do no copying.
					;---------------------------------------
   add	si,cx
   mov	di,si				; no emptys yet... no need to copy
   JMP	SHORT gcm1
					;---------------------------------------
					; CX is length of allocated block.
					;      - Move it
					;---------------------------------------

gcm3: mov bx,di 			; (DS:BX) = new home for this record
   mov	ax,ds
   mov	es,ax
   rep	movsb
					;---------------------------------------
					; We've moved the record, now fix up
					;  the pointers in the SFT chain
					;
					;  (si) = address of next record
					;  (di) = address of next free byte
					;  (bx) = address of record in its new home
					;  (TOS) = needed space
					;---------------------------------------
   push di
   push ds
   lds	di,[bx].mft_sptr		; (ds:di) = chain of SFT
gcm4: or di,di
   jz	gcm5				; no more SFT
   mov	[di].sf_mft,bx			; install new MFT position
   lds	di,[di].sf_chain		; link to next
   JMP	gcm4				; fix next SFT

gcm5: pop ds
   pop	di
					;---------------------------------------
					; (DI) points to beginning of
					;	new free record (moved)
					; (SI) points to next record
					;
					; Make sure that the (DI) record
					;  has correct format
					;---------------------------------------

   mov	[di].mft_flag,MFLG_FRE		; indicate free record
   mov	[di].mft_len,si 		; calculate correct length
   sub	[di].mft_len,di
					;---------------------------------------
					; MFT now has correct record structure.
					;  Go find more free blocks
					;---------------------------------------
   JMP	SHORT gcm1
					;---------------------------------------
					; We have scanned the entire table,
					;  compacting all empty records together.
					;
					;   (di) = first free byte in table
					;   (si) = address of END record
					;   (TOS) = size needed
					;
					; Be extra careful!!!
					;---------------------------------------
gcm10: mov ax,si
   sub	ax,di				; (ax) = free space
   pop	bx				; (bx) = space wanted
   sub	ax,bx

   ret

   EndProc GCM

   BREAK <RMN - Remove MFT Name record>

;******************* START OF SPECIFICATIONS ***********************************
;
;	RMN - Remove MFT Name record
;
;	RMN removes a name record from the MFT list.  The record is marked
;	free and all free space is coalesced.
;
;	ENTRY	(DS:BX) = FBA MFT name record
;	EXIT	to INTERR if lock and SFT chains are not empty
;	USES	ALL
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure RMN,NEAR

   mov	si,bx
   mov	ax,word ptr [si].mft_sptr
   or	ax,word ptr [si].mft_lptr
   jnz	RMNIER1 			; not clean - internal error
   mov	si,bx				; (ds:si) = fwa name record

   mov	[si].mft_flag,MFLG_FRE		; mark free

   call mrg				; coalesce all free space

   ret

RMNIER1:push ax
   off	ax,RmnErr1

RMNIER: call INTERR			; internal error


   EndProc RMN

   Break <MRG - merge all free space>

;******************* START OF SPECIFICATIONS ***********************************
;
;   MRG - merge all free space
;
;   MRG - walk through mft merging adjacent free space.
;
;   Inputs:	ds = CS
;   Outputs:	none (all free space coalesced)
;   Registers Revised: none
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure MRG,near

   assume ds:nothing,es:nothing

   push si
   push bx

   off	si,mft				; start at beginning
mrg1: mov bx,[si].mft_len		; get length
   cmp	[si].mft_flag,MFLG_FRE		; is record free?
   jl	mrg9				; done.
   jz	mrg2				; yes, try to merge with next
mrg15: add si,bx			; advance to next
   jmp	mrg1
					;---------------------------------------
					; (si) points to free record.
					;  - See if next is free
					;---------------------------------------
mrg2: cmp [bx][si].mft_flag,MFLG_FRE
   jnz	mrg15				; not free, go scan again
   mov	bx,[bx][si].mft_len		; get length of next guy
   add	[si].mft_len,bx 		; increase our length
   jmp	mrg1				; and check again
mrg9: pop bx
   pop	si

   ret

   EndProc MRG

   BREAK <RSC - Remove SFT from SFT chain>

;******************* START OF SPECIFICATIONS ***********************************
;
;	RSC - Remove SFT from SFT chain
;
;	RSC removes a given SFT from its chain.  The caller must insure that
;	any locks have been cleared and that the SFT is indeed free.  The
;	sf_mft field is zeroed to indicate that this SFT is no longer chained.
;
;	NOTE - RSC does NOT remove the name record if this was the last SFT on
;		it.  The caller must check for this and remove it, if
;		necessary.
;
;	ENTRY	(ES:DI) = SFT address
;	EXIT	(DS:BX) = FBA name record for this SFT
;		'Z' set if this is the last SFT
;	USES	ALL
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure RSC,NEAR

   push cs
   pop	ds

   mov	ax,es				; easy spot for compare
   mov	bx,es:[di].sf_mft
   lea	si,[bx].mft_sptr-sf_chain	; ds:[si].sf_chain point to prev link
rsc1: or si,si
   jz	rscier
   cmp	word ptr [si].sf_chain,di
   jnz	rsc15
   cmp	word ptr [si].sf_chain+2,ax
   jz	rsc2
rsc15: lds si,[si].sf_chain
   jmp	rsc1
					;---------------------------------------
					; (es:di) is sft
					; (ds:si) is prev sft link
					;---------------------------------------
rsc2: mov ax,word ptr es:[di].sf_chain
   mov	word ptr ds:[si].sf_chain,ax
   mov	ax,word ptr es:[di].sf_chain+2
   mov	word ptr ds:[si].sf_chain+2,ax

   push cs
   pop	ds
   xor	bx,bx
   xchg bx,es:[di].sf_MFT		; (DS:bx) = MFT address
					;    and 0 MFT pointer (show free)
   cmp	word ptr [bx].mft_sptr,0	; set z flag if no more sft

   ret

rscier: push ax
   off	ax,RscErr

   call interr


   EndProc RSC

   BREAK <SLE - Scan for Lock Entry>

;******************* START OF SPECIFICATIONS ***********************************
;
;	SLE - Scan for Lock Entry
;
;	SLE scans a lock list looking for a lock range that overlaps the
;	caller-supplied range.	SLE indicates:
;
;		no overlap
;		partial overlay
;		1-to-1 match
;
;	ENTRY	(AX:BX) = FBA of area
;		(CX:DX) = LBA of area
;		(DS:SI) = address of name record
;		(DI)	= 0 to ignore locks by User_ID Proc_ID ThisSFT
;			= 1 to consider all locks
;	EXIT	'C' clear if no overlap
;		  AX,BX,CX,DX preserved
;		'C' set if overlap
;		  (di) = address of pointer to found record
;			 (i.e., DS:((di)) = address of lock record)
;		  'Z' set if 1-to-1 match
;	USES	ALL but (ds), (es) (also see EXIT)
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure SLE,NEAR

   push es
   and	di,di
   pushf				; Z set to ignore own locks
   lea	di,[si].mft_lptr		; (ds:di) = addr of ptr to lock record
   mov	si,[di] 			; (ds:si) = address of 1st lock record

					;---------------------------------------
					; check out next lock
					;
					; (ds:si) = address of next lock record
					; (ds:di) = address of pointer to next
					;	     lock record
					; (TOS)   = flags (Z set to ignore
					;	      own locks)
					; (TOS+1) = Saved ES
					;---------------------------------------
sle1: and si,si
   jz	sle9				; list exhaused, ergo no overlap
   popf 				;
   pushf
   jnz	sle2				; am to check all locks

					;---------------------------------------
					; am to ignore own locks...
					;  check the user and proc IDs on this one
					;---------------------------------------

;dcl - this code used to compare the process id in the sft pointed to by the
;  lock.  now we compare the lock process id to the current process id.  this
;  allows a child process to lock an area and then do i/o with it.  before,
;  the child could lock it, but then could not access it


   mov	bp,[si].rlr_pid 		;dcl
   cmp	bp,Proc_id			;dcl
   jnz	sce1$5				;dcl
   les	si,[si].rlr_sptr		; (si) = sft address		;dcl
   mov	bp,es:[si].sf_UID		;dcl
   cmp	bp,User_ID			;dcl
   jnz	sce1$5				; doesn't belong to user        ;dcl
   mov	bp,es				;dcl
   cmp	bp,WORD PTR ThisSFT+2
   jnz	sce1$5
   cmp	si,WORD PTR ThisSFT
sce1$5: mov si,[di]			; (ds:si) = address of next lock record
   jz	sle3				; owned by user - ignore

sle2: mov bp,dx
   sub	bp,[si].rlr_fba 		; compare proposed last to first of record
   mov	bp,cx
   sbb	bp,[si].rlr_fba+2
   jc	sle3				; proposed is above current
   mov	bp,[si].rlr_lba
   sub	bp,bx				; compare proposed first to last of record
   mov	bp,[si].rlr_lba+2
   sbb	bp,ax
   jnc	sle5				; we have a hit

					;---------------------------------------
					; This entry is harmless...
					;    chain to the next one
					;---------------------------------------
   ERRNZ rlr_next

sle3: mov di,si 			; save addr of pointer to next
   mov	si,[di]
   JMP	SHORT sle1
					;---------------------------------------
					; We have an overlap.
					;  - See if its an exact match
					;
					; (ds:di) = address of pointer
					;	    (offset only) to the lock record
					; (ds:si) = address of lock record
					; (TOS) = flags ('Z' set if to ignore
					;	  own locks)
					; (TOS+1) = saved (es)
					;---------------------------------------

sle5: xor ax,[si].rlr_fba+2		; require a 4-word match
   xor	bx,[si].rlr_fba
   xor	cx,[si].rlr_lba+2
   xor	dx,[si].rlr_lba
   or	ax,bx
   or	ax,cx
   or	ax,dx				; 'Z' set if exact match
   stc					; flag an overlap
   mov	ax,error_lock_violation
sle9: pop bp				; discard flags (pushf)
   pop	es				; restore (es)

					;---------------------------------------
					; (ds:si) = address of lock record
					;	    for Chk_Block
					;---------------------------------------
   ret

   EndProc SLE

   BREAK <OFL - obtain free lock-record>

;******************* START OF SPECIFICATIONS ***********************************
;
;	OFL - obtain free lock-record
;
;	OFL returns a free lock-record, if one can be had.
;
;	ENTRY	(DS) = MFT Segment
;	EXIT	'C' clear if OK
;		  (DI) = FBA lock record
;		'C' set if no space
;		  (ax) = error code
;	USES	DI, FLAGS
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure OFL,NEAR

   mov	di,Frelock
   and	di,di

;  $if	nz				; if something there
   JZ $$IF1

       push [di].rlr_next
       pop  Frelock			; chain off of the list
					; exit with 'C' clear

;  $else				; none on free list
   JMP SHORT $$EN1
$$IF1:

       mov  ax,error_sharing_buffer_exceeded ; None on free list, give up until
       stc				;  garbage collector is ready

;  $endif
$$EN1:

   ret

   EndProc OFL

   Break <CPS - close process SFT>

;******************* START OF SPECIFICATIONS ***********************************
;
;   CPS - close process SFT.
;
;	During maintenance, it is necessary to close a
;	file given ONLY the SFT.  This necessitates walking all PDB's JFN
;	tables looking for the SFN.  The difficult part is in generating the
;	SFN from the SFT.  This is done by enumerating SFT's and comparing for
;	the correct SFT.  Finding all PDBs is easy:  walk arena and check
;	owner fields
;
;   Inputs:	ThisSFT points to SFT of interest
;   Outputs:	Handle is closed on user
;   Registers Revised: none
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure CPS,NEAR

   ASSUME DS:NOTHING,ES:NOTHING

   SaveReg <DS,SI,ES,DI,AX,BX,CX>

   lds	si,ThisSFT
   xor	bx,bx
cps01:

   CallInstall SFFromSFN,multDOS,22,bx,bx

   jc	cps31				; no more SFN's.  Must be FCB.

   CallInstall PointComp,multDOS,20

   jz	cps02				; found matching SFN, go scan.
   inc	bx				; did not match, go back for more
   jmp	cps01
					;---------------------------------------
					; BL is the sfn we want to find.  Walk
					;  the memory arena enumerating all PDB's
					;  and zap the handle tables for the
					;  specified sfn.
					;---------------------------------------
cps02:
   mov	al,bl
   mov	ds,Arena_Head			; get first arena pointer

					;---------------------------------------
					; DS:[0] is the arena header.
					; AL is sfn to be closed
					;---------------------------------------
cps1:
   mov	cx,ds:[arena_owner]
   mov	bx,ds
   inc	bx				; is the owner the same as the current
   cmp	cx,bx				; block?
   jnz	cps2				; no, go skip some more...

					;---------------------------------------
					; CX:0 is the correct pointer to a PDB.
					;---------------------------------------
   push ds
   mov	ds,cx
					;---------------------------------------
					; Given a PDB at DS:0, scan his handle
					;  table and then loop through the next
					;  PDB link.
					;---------------------------------------
cps15:
   call CPJ				; free for this PDB
   lds	cx,DS:[PDB_Next_PDB]		; advance to next
   cmp	cx,-1
   jnz	cps15				; there is another link to process
   pop	ds
					;---------------------------------------
					; We have processed the current
					;  allocation block pointed to by DS.
					;  DS:[0] is the allocation block
					;---------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -