        TITLE CRIT - Critical Section Routines
        NAME  CRIT

IF 1
__TONYI__1= 1;          ; JCXZ hacks...
__TONYI__2= 1;          ; Fake int prototype
ENDIF

;-------------------------- *** TONYI *** ---------------------------------
; There are measurable across the board speed gains to be had by making
; this stuff faster.  One of the key problems is in the testing of the
; "redir_patch" flag.  The old way pushed the flags, did a compare, and
; then used the POPFF macro to put the flags back.  The POPFF macro is
; rather expensive.  It involves a jump, a call, a push and an IRET.
; This *seemed* like the only way out, since the test of the flag *DOES*
; need to be performed, *AND* the flags can't be destroyed....
;                  ----------------------------------
; HOWEVER! there *IS* a better way...that avoids the POPFF macro and still
; doesn't hit the flags.  There is ONE instruction in the 8088 which WILL
; do a conditional jump without a prior compare or test of some sort, and
; which doesn't hit any flags...JCXZ!!!  We'll put it to use here, and
; speed up the redir_patch testing by over 50% on all CPU's!
;
; As a bonus, the code is smaller too...all the POPFF expansions disappear.
;-------------------------- *** TONYI *** ---------------------------------
; NOTE: There are massive wins here to be had under Windows *IFF* we can
;       figure out a way to safely fake the Int 2A's.  Currently though
;       dumb ass Windows DOES NOT hook out the Int 2A properly when it
;       comes up and leaves it aimed at an IRET in the VDM's.  This is a
;       *BIG* problem.  It means we can't fake the int, we gotta do a 
;       very expensive real one.  There's no other way to flag the critsec.
;-------------------------- *** TONYI *** ---------------------------------


;
;       IBM Corporation
;       Copyright (C) IBM Corporation 1991-1992
;       All Rights Reserved.
;
;**     CRIT.ASM - Critical Section Routines
;
;       Critical section handlers
;
;       Modification history:
;
;           Created: ARR 30 March 1983

        .xlist
        .xcref
        include version.inc
        include dosseg.inc
        INCLUDE DOSSYM.INC
        include int2a.inc
        include vector.inc
        include bugtyp.inc
        .cref
        .list

        I_need  User_In_AX,WORD
        i_need  CurrentPDB,WORD
ifdef __TONYI__2
	I_need  IsWin386,BYTE
endif
;
;SR; This variable is set when the redir installs itself
;
        I_need  redir_patch,BYTE

DOSCODE SEGMENT
        ASSUME  SS:NOTHING,CS:DOSCODE

        allow_getdseg

        Break   <Critical section handlers>

;
;   Each handler must leave everything untouched; including flags!
;

;;; *** TONYI *** --- I don't think the comment below applies anymore?!?!?
;;; VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;   Sleaze for time savings:  first instruction is a return.  This is patched
;   by the sharer to be a PUSH AX to complete the correct routines.


Procedure   EcritDisk,NEAR
        public  EcritMem
        public  EcritSFT
ECritMEM    LABEL   NEAR
ECritSFT    LABEL   NEAR

;
;SR; Check if critical section is to be entered
;
IFDEF __TONYI__1
        IF1
        %out    TONYI jcxz hack for EcritMem is active
        ENDIF
        push    cx                      ; Save CX
        mov     ch, 0                   ; No flags
        mov     cl, ss:[redir_patch]    ;  get hit by
        jcxz    Common_POP_CX_RET       ;   any of
        pop     cx
ELSE
        pushf
        cmp     ss:[redir_patch],0
        jz      @f
        popff
ENDIF

        PUSH    AX
if      DEBUG
        SAVE    <ds>
        GETDSEG DS
        fmt     TypSect,LevReq,<"PDB $x entering DISK">,<CurrentPDB>
        RESTORE <ds>
    ASSUME DS:nothing
endif

ifdef __TONYI__2
        MOV     AX,8000h+critDisk	; "enter" Crit-disk

CritHackPoint label near
	public	CritHackPoint		; These will be zapped to :

	push	cx			;       int   int_ibm
	mov	ch, 0			;       pop   ax
	mov	cl, ss:[IsWin386]	;       ret
	jcxz	FastV86Way		; on 8088's and 286's at init time.

SlowWinWay:
	pop	cx			; Do it the hard way to avoid
        INT     int_ibm			; damn Windows bug in hooking Int 2A
        POP     AX			;
        return				;

FastV86Way:
	push	es			; CX is already pushed!
	mov	cx, 0			; No XOR!!! It hits flags
	mov	es, cx			; ES --> IVT
	pushf				;       Fake up a software
	call	dword ptr es:[(int_ibm * 4)] ;  interrupt with PUSHF/CALLF
	pop	es			;
	pop	cx			;
        pop	ax			;
        return
else
        MOV     AX,8000h+critDisk
        INT     int_ibm
        POP     AX
        return
endif


IFDEF __TONYI__1
Common_POP_CX_RET:
        pop     cx
        ret
ELSE
@@:
        popff
        ret
ENDIF
EndProc EcritDisk


Procedure   LcritDisk,NEAR
        public  LcritMem
        public  LcritSFT
LCritMEM    LABEL   NEAR
LCritSFT    LABEL   NEAR
;
;SR; Check if critical section is to be entered
;
IFDEF __TONYI__1
        IF1
        %out    TONYI jcxz hack for LcritDisk is active
        ENDIF
        push    cx                      ; Save CX
        mov     ch, 0                   ; No flags
        mov     cl, ss:[redir_patch]    ;  get hit by
        jcxz    Common_POP_CX_RET       ;   any of
        pop     cx
ELSE
        pushf
        cmp     ss:[redir_patch],0
        jz      @f
        popff
ENDIF

        PUSH    AX
if      DEBUG
        SAVE    <ds>
        GETDSEG DS
        fmt     TypSect,LevReq,<"PDB $x leaving DISK">,<CurrentPDB>
        RESTORE <ds>
    ASSUME DS:nothing
endif
        MOV     AX,8100h+critDisk
ifdef __TONYI__2
	jmp	CritHackPoint
else
        INT     int_ibm
        POP     AX
        return
endif

IFDEF __TONYI__1
; Tail merged...
ELSE
@@:
        popff
        ret
ENDIF
EndProc LcritDisk


Procedure   EcritDevice,NEAR
;
;SR; Check if critical section is to be entered
;
IFDEF __TONYI__1
        IF1
        %out    TONYI jcxz hack for EcritDevice is active
        ENDIF
        push    cx                      ; Save CX
        mov     ch, 0                   ; No flags
        mov     cl, ss:[redir_patch]    ;  get hit by
        jcxz    Common_POP_CX_RET       ;   any of
        pop     cx
ELSE
        pushf
        cmp     ss:[redir_patch],0
        jz      @f
        popff
ENDIF

        PUSH    AX
if      DEBUG
        SAVE    <ds>
        GETDSEG DS
        fmt     TypSect,LevReq,<"PDB $x entering DEV">,<CurrentPDB>
        RESTORE <ds>
    ASSUME DS:nothing
endif

        MOV     AX,8000h+critDevice
ifdef __TONYI__2
	jmp	CritHackPoint
else
        INT     int_ibm
        POP     AX
        return
endif

IFDEF __TONYI__1
; Tail merged...
ELSE
@@:
        popff
        ret
ENDIF
EndProc EcritDevice

Procedure   LcritDevice,NEAR
;
;SR; Check if critical section is to be entered
;
IFDEF __TONYI__1
        IF1
        %out    TONYI jcxz hack for LcritDevice is active
        ENDIF
        push    cx                      ; Save CX
        mov     ch, 0                   ; No flags
        mov     cl, ss:[redir_patch]    ;  get hit by
        jcxz    Common_POP_CX_RET       ;   any of
        pop     cx
ELSE
        pushf
        cmp     ss:[redir_patch],0
        jz      @f
        popff
ENDIF

        PUSH    AX
if      DEBUG
        SAVE    <ds>
        GETDSEG DS
        fmt     TypSect,LevReq,<"PDB $x leaving DEV">,<CurrentPDB>
        RESTORE <ds>
    ASSUME DS:nothing
endif
        MOV     AX,8100h+critDevice
ifdef __TONYI__2
	jmp	CritHackPoint
else
        INT     int_ibm
        POP     AX
        return
endif

IFDEF __TONYI__1
; Tail merged...
ELSE
@@:
        popff
        ret
ENDIF
EndProc LcritDevice

DOSCODE ENDS
        END
