📄 gshare.asm
字号:
; WE HAVE: (from IBMDOS) | WE NEED: (for Clr_Block)
; (AX) = 0 - lock all | (BX) = 0 lock all operations
; = 1 - lock write | = 1 lock write operations
; (CX) = the number of lock ranges | (CX:DX) = offset of area
; (DS:DX) = pointer to the range list | (SI:AX) = length of area
; (ES:DI) = SFT address | (ES:DI) = SFT address
;; PUSH CX ; count = start_count ;AN000;
;; PUSH DX ; save pointer to range list ;AN000;
MOV BP,DX ; save current index into list ;AN000;
;; MOV BX,AX ; SET UP TYPE OF LOCK ;AN000;
call Clr_List ; call Clr_List to process the list ;AN000;
;; $ENDIF ; ;AN000;
; $ELSE ; NOT VALID
JMP SHORT $$EN6
$$IF6:
STC ; ;AN000;
; $ENDIF ; VALID/INVALID ;AN000;
$$EN6:
; $IF C ; if carry is set ;AN000;
JNC $$IF9
MOV AX,error_lock_violation ; load error condition ;AN000;
; $ENDIF ; carry not set ;AN000;
$$IF9:
LeaveCrit critShare ; ;AN000;
ret ; return - all set ;AN000;
EndProc clr_mult_block
BREAK <Clr_List - Clear a list of user specified locks>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Clr_List - Clear a list of user specified locks
;
; FUNCTION: Clr_List makes multiple calls to Clr_Block to clear
; multiple lock ranges of a file. An error is returned
; if any lock range does not exactly match. Ranges of
; Locks are then set via Set_Mult_Block.
;
;
; INPUT: (BX) = 0 lock all operations
; = 1 lock write operations
; (CX:DX) = offset of area
; (SI:AX) = length of area
; (ES:DI) = SFT address
; (SS:SP+2)= original index \ see FRAME struc
; (SS:SP+4)= original count /
;
; OUTPUT: Lock records removed for all blocks specified
; Stack cleard on return
;
; REGISTERS USED: ALL but DS
; (NOT RESTORED)
;
; LINKAGE: IBMDOS Jump Table
;
; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block
; REFERENCES:
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT: (ax) = error code
; ('error_lock_violation' if conflicting locks)
;
; CHANGE 04/15/87 - First release
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Clr_List
;
; search till count = 0
; set up for call
; call clr_Block
; exit if c
; clear_count = start_count - current_count
; loop till clear_count = 0
; set up for call
; call Set_Block
; end loop
; set error status
; orelse
; endloop
; set successful status
; endsrch
; return
;
; END Clr_List
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Clr_List,NEAR
;; $do ;an000;while cx not = 0
;; cmp cx,00 ;an000;at end?
;; $leave e ;an000;yes
;; push cx ;an000;save cx - our counter
;; push di ;an000;save di - our SFT pointer
call load_regs ;an000;set up for clr_block call
;; push bp ; save pointer to range entry ;AN000;
call clr_block ;an000;remove the lock
;; pop bp ; recover pointer to range entry ;AN000;
;; pop di ;an000;restore our SFT pointer
;; pop cx ;an000;restore cx - our counter
;; $leave c ;an000;leave on error
;; dec cx ;an000;decrease counter
;; $enddo ;an000;
;; $if c ;an000;an error occurred
;; push bp ;an000;save bp
;; mov bp,sp ;an000;get sp
;; mov dx,[bp].parm_1 ;an000;recover original index
;; mov ax,[bp].Parm_2 ; original count ;AN000;
;; pop bp
;; SUB AX,CX ; how many did we do? ;AN000;
;; MOV CX,AX ; set up the loop ;AN000;
;; MOV BP,DX ; save the index ;AN000;
;; $DO ; ;AN000;
;; cmp cx,00 ;an000;at end?
;; $leave e ;an000;yes
;; push cx ;an000;save cx - our counter
;; push di ;an000;save di - our SFT pointer
;; call load_regs ;an000;set up for set_block call
;; call set_block ;an000;reset the locks
;; pop di ;an000;restore our SFT pointer
;; pop cx ;an000;restore cx - our counter
;; $leave c ;an000;leave on error
;; dec cx ;an000;decrease counter
;; $enddo ;an000;
;; stc ;an000;signal an error
;; $else ;an000;
;; clc ;an000;signal no error
;; $endif ;an000;
;; ret 4 ; return (clear Parm_1 & Parm_2) ;AN000;
ret ; return (clear Parm_1 & Parm_2) ;AC006;
EndProc Clr_List
BREAK <Set_Block - Try to set a lock>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Set_Block - set byte range lock on a file
;
; FUNCTION: Set_Block sets a lock on a specified range of a file. An
; error is returned if the lock conflicts with another.
; Locks are cleared via clr_block.
;
; INPUT: (ES:DI) = SFT address
; (CX:DX) = offset of area
; (SI:AX) = length of area
; (BX) = 0 lock all operations
; = 1 lock write operations
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = DOSData
;
; OUTPUT: Lock records removed for all blocks specified
;
; REGISTERS USED: ALL but DS, BP
; (NOT RESTORED)
;
; LINKAGE: Invoked by: Set_Mult_Block
;
; EXTERNAL Invoke: CLP (SLE), OFL
; REFERENCES:
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT:
;
; CHANGE 04/15/87 - lock only write support
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Set_Block
;
; if a valid SFT and
; invoke CLP
; if no lock conflicts and
; invoke OFL
; if empty lock record available
; store SFT pointer
; store lock range
; add RLR to the chain
; store PROC_ID
; store rlr_type
; set successful return status
; else
; set error return status
; endif
; return
;
; END Set_Block
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Set_Block,NEAR
ASSUME ES:NOTHING,DS:NOTHING
Context DS
push bp ; preserve (bp) ;AN000;
push ds ; preserve (ds)
;; push bx ; preserve (bx) ;AN000;
cmp es:[di].sf_mft,ZERO
; $if nz,and ; if file is SHARED and ;AC000;
JZ $$IF11
push di
call clp ; do common setup code
ASSUME DS:NOTHING
pop bp
; $if nc,and ; if no (lock conflict) error and ;AC000;
JC $$IF11
; Its ok to set this lock. Get a free block and fill it in
; (es:bp) = sft
; (ds:si) = pointer to name record
; (ax:bx) = fba lock area
; (cx:dx) = lba lock area
; (ds:di) = pointer to pointer to previous lock
; (TOS) = saved (bx)
; (TOS+1) = saved (ds)
; (TOS+2) = saved (bp)
call OFL ; (ds:di) = pointer to new, orphan lock record
; $if nc ; if space available ;AC000;
;SR;
; We have to return out_of_buffer error code in case no more locks can be
;allocated. The old code was returning a lock violation for this case also.
;
JC out_of_space
mov WORD PTR [di].rlr_sptr,bp ; store SFT offset
mov WORD PTR [di].rlr_sptr+2,es ; store SFT offset
mov [di].rlr_fba+2,ax
mov [di].rlr_fba,bx ; store lock range
mov [di].rlr_lba+2,cx
mov [di].rlr_lba,dx
; add to front of chain
;
; (ds:si) = fwa MFT name record
mov ax,[si].mft_lptr
mov [di].rlr_next,ax
mov [si].mft_lptr,di
;
; Set process ID of lock
;
mov ax,proc_id
mov [di].rlr_pid,ax
;
;; pop bx ; recover lock type ;AN000;
;; push bx ; restore the stack ;AN000;
;; mov [di].rlr_type,bx ; set the rlr_type field ;AN000;
clc ; we finished OK
; $else ; ;AC000;
JMP SHORT $$EN11
;SR;
;We have to return a separate error code if we run out of space for locks
;
out_of_space:
mov ax,error_sharing_buffer_exceeded
jmp short $$EN11
$$IF11:
mov ax,error_lock_violation
stc
; $endif ; ;AC000;
$$EN11:
;; pop bx ; ;AN000;
pop ds
pop bp ; ;AC000;
ret ; return - all set
EndProc Set_Block
BREAK <Clr_Block - Try to clear a lock>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Clr_Block - clear byte range lock on a file
;
; FUNCTION: Clr_Block clears a lock on a specified range of a file.
; Locks are set via set_block.
;
; INPUT: (ES:DI) = SFT address
; (CX:DX) = offset of area
; (SI:AX) = length of area
; (BX) = 0 lock all operations
; = 1 lock write operations
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = DOSData
;
; OUTPUT: Lock record removed for block specified.
;
; REGISTERS USED: ALL but DS
; (NOT RESTORED)
;
; LINKAGE: Invoked by: Clr_Mult_Block
;
; EXTERNAL Invoke: CLP (SLE), OFL
; REFERENCES:
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT: (ax) = error code
; ('error_lock_violation' if conflicting locks or
; range does not exactly match previous lock)
;
; CHANGE 04/15/87 - lock only write support
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Clr_Block
;
; if file is SHARED and
; if lock is valid and
; if SFT matches and
; if PROC_ID matches
; if lock_reqest = lock_type
; unchain the lock
; put defunct lock on free chain
; clear error status
; else
; set error status
; endif
; else
; flush the stack
; set error status
; endif
; if error
; load return code
; endif
; return
;
; END Clr_Block
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Clr_Block,NEAR
ASSUME ES:NOTHING,DS:NOTHING
Context DS
push ds
;; push bx ; save type of operation ;AN000;
cmp es:[di].sf_mft,ZERO
; $if nz,and ; if file is SHARED and ;AC000;
JZ $$IF14
push di
call clp ; do common setup code
ASSUME DS:NOTHING
pop bp ; ES:BP points to sft.
;; pop bx ; recover the type of operation ;AN000;
; $if c,and ; if lock exists and ;AC000;
JNC $$IF14
; $if z,and ; if range given correctly and ;AC000;
JNZ $$IF14
;
; We've got the lock
;
; (ds:di) = address of pointer (offset) to previous lock record
; (es:BP) = sft address
;
; Now comes the tricky part. Is the lock for us? Does the lock match the SFT
; that was given us? If not, then error.
;
mov si,[di] ; (DS:SI) = address of lock record
cmp word ptr [si].rlr_sptr,bp
; $if z,and ; if SFT matches and ;AC000;
JNZ $$IF14
mov bp,es
cmp word ptr [si].rlr_sptr+2,bp
; $if z,and ; (check both words of SFT pointer) ;AC000;
JNZ $$IF14
mov bp,proc_id
cmp [si].rlr_pid,bp
;; $if z,and ; if PROC_ID matches ;AC000;
; $if z ; if PROC_ID matches ;AC006;
JNZ $$IF14
;
; Make sure that the type of request and the lock type match
;
;; cmp bx,lock_all ; ;AN000;
;; $IF E,OR ; if unlocking all or ;AN000;
;; mov bp,[si].rlr_type ; get lock type ;AN000;
;; cmp bp,rlr_lall ; is it lock all? ;AN000;
;; $IF NE ; if not a LOCK ALL lock ;AN000;
;
; The locks match the proper open invocation. Unchain the lock
;
mov ax,[si].rlr_next
mov [di],ax ; chain it out
; put defunct lock record on the free chain
;
; (ds:si) = address of freed lock rec
mov ax,Frelock
mov [si].rlr_next,ax
mov Frelock,si
clc
; $else ; we have an error ;AC000;
JMP SHORT $$EN14
$$IF14:
stc
; $endif ; Endif - an error ;AC000;
$$EN14:
; $if c ; If an error was found ;AC000;
JNC $$IF17
mov ax,error_lock_violation
; $endif ; Endif - an error was found ;AC000;
$$IF17:
pop ds ; restore DS
ret
EndProc Clr_Block
BREAK <CLP - Common Lock Preamble>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: CLP - Common Lock Preamble
;
; FUNCTION: This routine contains a common code fragment for set_block
; and clr_block.
;
; INPUT: (ES:DI) = SFT address
; (CX:DX) = offset of area
; (SI:AX) = length of area
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = (DS) = DOSData
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -