windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/tasking.asm
2020-09-26 16:20:57 +08:00

611 lines
16 KiB
NASM

TITLE TASKING.ASM - WOW Tasking Support
PAGE ,132
;
; WOW v1.0
;
; Copyright (c) 1991, Microsoft Corporation
;
; TASKING.ASM
; WOW Tasking Support on 16 bit side - also see wkman.c
;
; History:
; 23-May-91 Matt Felton (mattfe) Created
; 12-FEB-92 Cleanup
;
.xlist
include kernel.inc
include tdb.inc
include newexe.inc
include wow.inc
include vint.inc
.list
if PMODE32
.386
else
.286
endif
if KDEBUG
externFP OutputDebugString
endif
DataBegin
externB Kernel_InDOS
externB Kernel_flags
externB InScheduler
ifndef WOW
externB fProfileDirty
endif
externW WinFlags
externW cur_drive_owner
externW curTDB
externW Win_PDB
externW LockTDB
externW headTDB
externW hShell
externW pGlobalHeap
externW hExeHead
externW f8087
externD pIsUserIdle
externW wCurTaskSS
externW wCurTaskBP
globalw gwHackpTDB,0
globalw gwHackTaskSS,0
globalw gwHackTaskSP,0
if PMODE32
externW PagingFlags
endif
DataEnd
ifdef WOW
externFP ExitKernelThunk
externFP WowInitTask
externFP Yield
externFP WOW16CallNewTaskRet
externFP WowKillTask
externFP WOW16DoneBoot
externFP WOWGetCurrentDirectory
externFP ExitCall
externFP WowSyncTask
endif
sBegin CODE
assumes cs,CODE
assumes ds,NOTHING
assumes es,NOTHING
ife PMODE
externNP patch_cached_p
endif
externNP LoadSegment
externNP DeleteTask
externNP InsertTask
if PMODE32
externNP ShrinkHeap
endif
ifdef WOW
externNP Int21Handler
endif
if SDEBUG
externNP DebugSwitchOut
externNP DebugSwitchIn
endif
;-----------------------------------------------------------------------;
; StartWOWTask ;
; ;
; Start a WOW 32 Task ;
; ;
; Arguments: ;
; Parmw1 -> TDB Of New Task ;
; Parmw2 New Task SS ;
; Parmw3 New Task SP ;
; Returns: ;
; AX - TRUE/FALSE if we we able to create a new WOW task ;
; Error Returns: ;
; none ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; BX,CX,DX ;
; Calls: ;
; See Notes ;
; History: ;
; ;
; Fre 24-May-1991 14:30 -by- Matthew A. Felton [mattfe] ;
; Created ;
;-----------------------------------------------------------------------;
; The 16-Bit Kernel has created the new task and its ready to go
; 1. Temporarily Switch to New Task Stack S2
; 2. Fake Far Return from Thunk to point to StartW16Task
; 3. Thunk to WOW32 - This will create a new Thread and call Win32 InitTask()
; Note InitTask() will not return from the non-preemptive scheduler until
; This thread does a Yield.
; 4. When the thunk returns is jmps to WOW16TaskStarted on S2 leaving
; S2 ready for the new task when it returns
; 5. Restore S1 - Original Task Stack
; 6. Return Back to LoadModule who will Yield and start T2 going.
assumes ds, nothing
assumes es, nothing
cProc StartWOWTask,<PUBLIC,FAR>
parmW pTDB
parmW wTaskSS
parmW wTaskSP
cBegin
SetKernelDS ds
mov es,pTDB ; Get New Task TDB, will use later
push curTDB ; Save our TDB
push bp ; save BP (we don't exit wow16cal directly)
mov di,ss ; Save Current Task Stack
mov cx,sp ; di=ss cx=sp
; switch to new task stack temporarily
FCLI ; Disable Ints Till We get Back
; To presever new fram
mov si,wTaskSP ; Grab this before SS goes away
mov ss,wTaskSS ; Switch to new task stack.
mov sp,si ;
mov curTDB,es ; Set curTDB to new task
;
pushf
pop ax
or ax,0200h ; Re-enable interrupts
push ax
push es ; hTask
mov es, es:[TDB_pModule] ; exehdr
mov ax, es:[ne_expver]
mov dx, es:[ne_flags]
and dx, NEWINPROT ; prop. font bit
push es ; hModule
push es ; Pointer to module name
push es:ne_restab
push es ; Pointer to module path
push word ptr es:ne_crc+2
push dx ; expwinver. argument for WOWINITTASK
push ax
mov es, curTDB ; resotre es, just being safe
; thunk to wow32 to create a thread and task
push cs ; Fake Out FAR Return to StartW16Task
push offset StartW16Task
jmp WowInitTask ; Start Up the W32 Thread
public WOW16TaskStarted
WOW16TaskStarted:
mov ss,di ; Restore Calling Task Stack
mov sp,cx
pop bp
pop curTDB ; Restore real CurTDB
FSTI ; OK we look like old task
cEnd
;
; First code executed By New Task - Setup Registers and Go
;
StartW16Task:
add sp,+12
pop ax ; Flags
mov bp,sp
xchg ax,[bp+20] ; Put flags down & pick up cs
xchg ax,[bp+18] ; Put cs down & pick up ip
xchg ax,[bp+16] ; Put ip down & pick up bp
mov bp,ax
dec bp
pop dx
pop bx
pop es
pop cx
pop ax
pop di
pop si
pop ds
call SyncTask
iret ; App Code Starts From Here
; ExitKernel
;
; Enter When the 16 bit Kernel is going away -- never returns.
; In WOW this is a register-args wrapper for the stack-args
; thunk ExitKernelThunk.
public ExitKernel
ExitKernel:
cCall ExitKernelThunk, <ax>
INT3_NEVER ; ExitKernel never returns.
; BootSchedule
;
; Entered When Bogus Boot Task goes Away - treated same as task exit.
public BootSchedule
BootSchedule:
CheckKernelDS DS ; Make Sure we Address Kernel DS
mov [curTDB],0 ; Make No Task the Current Task
jmp WOW16DONEBOOT
; ExitSchedule
;
; We get here when a 16 bit task has exited - go kill this task
; Win32 non-preemptive scheduler will wake someone else to run.
public ExitSchedule
ExitSchedule:
CheckKernelDS DS ; Make Sure we Address Kernel DS
mov ax,[LockTDB] ; If I am the locked TDB then clear flag
cmp ax,[curTDB]
jnz @f
mov [LockTDB],0
@@:
mov [curTDB],0 ; Make No Task the Current Task
if PMODE32
call ShrinkHeap
endif; PMODE32
jmp WowKillTask ; Go Kill Myself (NEVER RETURNS)
;-----------------------------------------------------------------------;
; SwitchTask - This is NOT a subroutine DO NOT CALL IT
;
; This routine does a Win 3.1 compatible task switch.
;
; Arguments:
; AX == Next Tasks TDB pointer
; Returns:
; nothing
; Error Returns:
; nothing
; Registers Preserved:
;
; Registers Destroyed:
;
; Calls:
; SaveState
; RestoreState
;
; History:
; 22-May-91 Matt Felton (MattFe) Created
; Using idea's from Win 3.1 Schedule.Asm
;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
public SwitchTask
SwitchTask:
CheckKernelDS ds
ReSetKernelDS ds
inc InScheduler ; set flag for INT 24...
cmp curTDB,0 ; Previous Task Gone Away ?
jnz @f ; No ->
; Yes
mov di,ax ; DI = New TDB
mov ds,ax ; DS = New TDB
jmps dont_save_state ; Get Set for this new guy
@@:
push ax ; Save Next Tasks TDB pointer
; COMPAT 22-May-91 Mattfe, Idle callout for funky screen drivers is done by
; the Windows scheduler - that will not happen either from WOW. INT 28
; and Win386 1689 int2f call
; There was PokeAtSegments code which during idle time brought back segments !
; Do Debuggers Care that the stack frame of registers looks like a Windows stack frame
; when we do the debugger callout ? - check with someone in CVW land.
mov es,curTDB ; ES = Previous Task TDB
mov ax,es ; Don't SS,SP For DEAD Task
or ax,ax
jz @F
mov ax,wCurTaskSS ; FAKE Out TDB_taskSS,SP so that
mov es:[TDB_taskSS],ax ; The Old Task Task_BP looks right
mov ax,wCurTaskBP
sub ax,(Task_BP-Task_DX)
mov es:[TDB_taskSP],ax
@@:
pop ds ; DS = Next Task TDB
UnSetKernelDS ds
if KDEBUG
; Assertion Check TDB_taskSS == SS for current Task
mov ax,ds:[TDB_taskSS]
mov di,ss
cmp di,ax
jz @F
; int 3
@@:
endif; KDEBUG
mov di,ds ; DI = destination task
xor si,si ; SI is an argument to RestoreState
mov ax,es ; NOTE TDB_SS,SP Are note Correct
or ax,ax ; might affect debugger compatability.
jz short dont_save_state
cmp es:[TDB_sig],TDB_SIGNATURE
jnz short dont_save_state
mov si,es ; SI = Old Task
cCall SaveState,<si>
if SDEBUG
push ds
mov ds,ax
call DebugSwitchOut ; Note Stack Frame is not Compatible
pop ds ; Do we care ?
endif
dont_save_state:
SetKernelDS es
mov curTDB,di
mov ax, ds:[TDB_PDB] ; Set our idea of the PDB
mov Win_PDB, ax
SetKernelDS es
cmp di,0 ; the first task, will never get 0
jz dont_restore_state
ife PMODE
call RestoreState
endif
or Kernel_flags,kf_restore_CtrlC OR kf_restore_disk
if SDEBUG
call DebugSwitchIn
endif
dont_restore_state:
; Switch to new task stack.
mov curTDB,di
dec InScheduler ; reset flag for INT 24
SetKernelDS ds ; Set the Kernel DS again
;the word at [vf_wES] is a selector that's about to be popped into
;the ES in WOW16CallNewTaskRet. this selector could be the TDB of
;a task that just died, in which case it's invalid. so let's
;shove something in there that won't cause a GP when we do the POP ES.
;
; In some cases we are switching tasks while returning to a callback.
; When this happens our stack is a CBVDMFRAME instead of a VDMFRAME.
; We only want to shove a safe ES,FS,GS value when it's a VDMFRAME and
; we're returning from an API call rather than calling back to
; 16-bit code.
;
; Regardless of which frame we're using, ss:sp points to wRetID.
mov bx, sp
cmp WORD PTR ss:[bx], RET_DEBUGRETURN ; if (wRetID > RET_DEBUGRETURN)
ja dont_stuff_regs ; goto dont_stuff_regs
sub bx,vf_wTDB + 2 ;bx is now start of VDMFRAME struct
mov ss:[bx+vf_wES],es ;put something safe in there
;Win31 does not save fs, gs over task switches, so we zero them out here
mov word ptr ss:[bx+vf_wFS],0 ;put something safe in there
mov word ptr ss:[bx+vf_wGS],0 ;put something safe in there
dont_stuff_regs:
if KDEBUG
mov bx, sp
cmp WORD PTR ss:[bx], RET_TASKSTARTED
jne @f
INT3_NEVER ; We need to stuff ES for RET_TASKSTARTED
; if we hit this breakpoint.
@@:
endif
; Hung App Support
; If the new task is the one we want to kill then force it to exit
mov bx,curTDB ; if ( curTDB == LockTDB )
cmp bx,LockTDB
jnz SW_DontKillIt
mov ax,4CFFH ; YES -> Exit
DOSCALL
INT3_NEVER
SW_DontKillIt:
jmp WOW16CallNewTaskRet ; Continue with the new task.
;-----------------------------------------------------------------------;
; SaveState ;
; ;
; Saves the state of the current MS-DOS process. This means the per ;
; task interrupt vectors, the drive and directory, EEMS land if any, ;
; and old app stuff if any. ;
; ;
; Arguments: ;
; parmW destination ;
; ;
; Returns: ;
; DS returned in AX. ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Mon 07-Aug-1989 21:53:42 -by- David N. Weise [davidw] ;
; Removed the WinOldApp support. ;
; ;
; Tue Feb 03, 1987 08:21:53p -by- David N. Weise [davidw] ;
; Got rid of the rest of the DOS version dependencies. ;
; ;
; Thu Jan 22, 1987 03:15:15a -by- David N. Weise [davidw] ;
; Took out the saving of the ^C state, DTA address, and ErrorMode. ;
; ;
; Sun Jan 04, 1987 04:40:44p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc SaveState,<PUBLIC,NEAR>,<si,di,ds>
parmW destination
cBegin
cld
ife PMODE
SaveTaskInts destination
endif
SetKernelDS
mov ax,f8087
UnSetKernelDS
mov ds,destination
or ax,ax
if 0
jz short no_fstcw
.8087
fstcw ds:[TDB_FCW]
endif
no_fstcw:
test ds:[TDB_Drive],10000000b; if hi bit set....
jnz short ss_ret ; ...no need to get dir
mov ah,19h
DOSCALL
mov dl,al
inc dl
or al,10000000b
mov ds:[TDB_Drive],al ; save it (A=0, B=1, etc.)
mov si,TDB_LFNDirectory
mov byte ptr [si],'\' ; set "\"
inc si
; get Long path
cCall WowGetCurrentDirectory,<80h, ds, si>
or dx, dx
jz short ss_ret
mov byte ptr [si-1],0 ; indicate error with null byte
ss_ret: mov ax,ds
cEnd
;-----------------------------------------------------------------------;
; RestoreState ;
; ;
; Restores the MS-DOS interrupt vectors in real mode. ;
; ;
; Arguments: ;
; none ;
; Returns: ;
; none ;
; Error Returns: ;
; none ;
; Registers Preserved: ;
; BX,CX,DX,DI,SI,DS,ES ;
; Registers Destroyed: ;
; AX ;
; Calls: ;
; nothing ;
; History: ;
; ;
; Mon 07-Aug-1989 21:53:42 -by- David N. Weise [davidw] ;
; Removed the WinOldApp support. ;
; ;
; Tue Feb 03, 1987 08:21:53p -by- David N. Weise [davidw] ;
; Got rid of the rest of the DOS version dependencies. ;
; ;
; Thu Jan 22, 1987 03:15:15a -by- David N. Weise [davidw] ;
; Took out the restoring of the ^C state, DTA address, and ErrorMode. ;
; ;
; Sun Jan 04, 1987 04:45:31p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
ife PMODE
assumes ds, nothing
assumes es, nothing
cProc RestoreState,<PUBLIC,NEAR>
cBegin nogen
push di
push si
push ds
push es
cld
RestTaskInts di ; restore DOS interrupts
pop es
pop ds
pop si
pop di
ret
cEnd nogen
endif ; PMODE
; SyncTask
;
; Enter: when new task starts
; check if the new task is blocked by appshelp
cProc SyncTask,<PUBLIC,NEAR> <ax,bx,cx,dx,di,si,es,ds>
cBegin
STL:
cCall WowSyncTask
cmp ax, 0
je @F
jg STL
call ExitCall
@@:
cEnd
sEnd CODE
end