;       SCCSID = @(#)task.asm   6.6 92/03/18
SCCSID  equ     "@(#)task.asm   6.6 92/03/18"
        PAGE    ,132
TITLE   TASK - OS/2 Task Handling Routines
NAME    TASK

;       IBM/Microsoft Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989
;       Copyright (c) Microsoft Corporation 1987, 1989
;
;       All Rights Reserved
;
;       MODIFICATION HISTORY
;
;       05-Mar-87  IDB  Only put KBD back to Cooked Mode if ending
;                       process left it as RAW (PTM 1420).
;
;       10-May-87  IDB  Thread 1 slot should not be recycled (PTM 4564).
;
;       06-Jun-87  IDB  Set FF_DES in Thread 1's force flags so that
;                       we can tell that thread 1 is dying or already
;                       dead (for PTM 5222).
;
;       16-Jun-87  IDB  Replaced above mechanism by setting PS_XITTH1
;                       in ProcStatus in the PTDA when in w_Exit for
;                       Thread 1.
;
;       27-Jun-87  IDB  Changed w_KillProcess to use command subtrees
;                       (PTM 4909).
;
;       16-Jul-87  IDB  Added order of execution option on w_ExitList
;                       (1.1 DCR 18, PTM 101).
;
;       19-Jul-87  FJD  Added PTrace thread termination handling
;                       (1.1 DPTM 120)
;
;       05-Feb-88  FJD  Recoded CWait (PTM 1677, 1678, 1679)
;
;       13-Jun-88  JSF  Modified w_exit to handle miscellaneous monitor
;                       problems.
;                       (1.2 PTM 958)
;
;       20-Jul-88  CAS  Cleared FF_TRC in w_Exit so that the process
;                       won't get killed before it tries to run exitlist
;
;       09-Mar-94  WDM  Cleared CDS_Handle for process's drive so popup
;                       log can be created OK. D78512
;

INCL_ERROR_H    EQU     1               ; for error.inc  EQUates
INCL_ERROR2_H   EQU     1               ; for error2.inc EQUates

.xlist
.xcref
include fnotask.inc
include dosseg.inc
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include mi.inc
include defdbug.inc
include dossymc.inc
include buffer.inc
include curdir.inc
include bseerr.inc
include filemode.inc
include filesys.inc
include mhandle.inc
include pmode.inc
include sched.inc
include screen.inc
include sft.inc
include sigdef.inc
include tkexport.inc
include proc.inc
include infoseg.inc
include devsym.inc
include ioctl.inc
.cref
.list

CpuMode 386

        ModName task,FNO_TASK_ASM

        ReferFlat       _pPTDACur,DWORD
        ReferFlat       _pTCBCur,DWORD                  ;B731784
        ReferFlat       _Resched,BYTE                   ;B731784
        ReferFlat       _TCResched,BYTE                 ;B731784
        ReferFlat       _ptcbPriQRunner,DWORD           ; fix
        ReferFlat       _ptcbPriQReady,DWORD            ; fix

        ReferGlobal     ConInpDev,DWORD
        ReferGlobal     HDE_Pid,WORD
        ReferGlobal     MUF_Pid,WORD
        ReferGlobal     SISData,BYTE
        ReferGlobal     _Sis2,BYTE
        ReferGlobal     TaskNumber,WORD
        ReferGlobal     CNotifyGlobal_Count,WORD  ;### DCR 1482

        ReferTask       Cons_Loc,BYTE
        ReferTask       CDS_Handle,WORD
        ReferTask       CurrTCB,WORD
        ReferTask       Csid,WORD
        ReferTask       FNotifyLocal_Count,WORD
        ReferTask       KBD_Mode,BYTE
        ReferTask       Pid,WORD
        ReferTask       ProcStatus,BYTE
        ReferTask       ProcType,BYTE
        ReferTask       ptda_child,WORD
        ReferTask       SrchRmp,WORD
        ReferTask       CurrentPDB,WORD

        EXTRN           POST_SIGNAL:near
        EXTRN           ProcessKill:near

        EXTRNFAR        AllocReqPacketWait
        EXTRNFAR        DecVPBRef
        EXTRNFAR        DecVPBSearch
        EXTRNFAR        DevIOCall2
        EXTRNFAR        GetCDS
        EXTRNFAR        DelCDS
        EXTRNFAR        DOS_Abort
        EXTRNFAR        FindExit
        EXTRNFAR        FNotifyExit
        EXTRNFAR        CNotifyExit     ;### DCR 1482
        EXTRNFAR        FreeReqPacket
        EXTRNFAR        FSD_FlushBuf
        EXTRNFAR        RlseBuffr
        EXTRNFAR        SFFromHandle
        EXTRNFAR        w_Close

        EXTRNF32        CWait

;       EXTRN32         _LDRTstnClrSem
;        EXTRN32         _SCHSetState
        EXTRN32         _TKUpdateState
        EXTRN32         _TKTidTo_pTCB
        EXTRN32         VDMMKILLVDM

        FARCODE HIGH3
HIGH3CODE    SEGMENT

BREAK   <ProcessTerminate - Terminate a process (non-scheduler stuff)>
;***EP  ProcessTerminate - Terminate a process (non-scheduler stuff)
;
;       ProcessTerminate is the common code for various forms
;       of process terminations.
;
;       ENTRY   None
;       EXIT    Does not return

ptie:   InternalError <ProcessTerminate: ptda_child>

    ASSUME      DS:NOTHING, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:TASKAREA
Procedure ProcessTerminate,far16
        DBPRT   2,4,<ProcessTerminate 2:4 Pid:$d code $x\n>,<Pid,ax>

        mov     ss:[CurrentPDB],0       ; match all PDBs during FS clean up
        or      ss:[ProcStatus],PS_DYING; the process is at death's door

;   Call VDM manager for VDM process clean up

        cmp     ss:[ProcType],PT_REALMODE
        jne     short pt10
        movzx   eax,Pid
        FlatContext <ds,es>,cx
        CCALL32 VDMMKILLVDM,eax,,pascal ; call VDM Manager to cleanup VDM stuff
    ASSUME   DS:NOTHING,ES:NOTHING,FS:NOTHING,GS:NOTHING

;   Reset KBD mode if last setting by thread of this process was RAW

pt10:   test    ss:[KBD_Mode],80h       ; check last mode setting by
        jz      short pt20              ; this process, jump if Cooked
        call    CookedKBD               ; set KBD to cooked mode

;   Release Loader and Swapper semaphores if owned

pt20:   FlatContext <ds,es>,ax,noassume

; PaulDev - removed call - this is not what TstnClt does.
;       CCALL32 _LDRTstnClrSem,,nocall  ; release loader semaphore if owned

        cmp     ss:[ptda_child],0       ; child ptda handle must be 0!
        jnz     ptie                    ; jmp if child exists

        mov     AX,ss:[Pid]             ; check to see if this is a
                                        ; process with special signals
        DosContext DS
        cmp     AX,MUF_Pid
        jnz     pt25
        mov     MUF_Pid,0               ; MUF process, reset flag
pt25:   cmp     AX,HDE_Pid
        jnz     pt30
        mov     HDE_Pid,0               ; Hard error process, reset flag
pt30:   cmp     ax,SISData.SIS_FgndPID  ; Keyboard focus dying?
        jne     pt40                    ;  no, skip ahead
        mov     SISData.SIS_FgndPID,0   ; No keyboard focus any more
        mov     fs,[_Sis2].is_sel       ; update infoseg copy
        mov     fs:SIS_FgndPID,0

;*  Free existing search structures in PTDA
;
;   if any existing searches, call FindExit to free search structures
;
;   NOTE: This code was originally in DOS_Abort, but it was moved here
;         because we do PTDA termination here, while DOS_Abort does
;         file system clean up that is common to PDB and PTDA processes.

pt40:   TaskContext ds
        cmp     word ptr ds:[SrchRmp],0
        je      short pt50
        mov     es,word ptr ds:[SrchRmp+2]
        CALLFAR FindExit

;*  Kill off remainder of this process.  Close file handles and signal to
;   relevant network folks that this process is dead.

pt50:   cmp     ds:[FNotifyLocal_Count],0
        je      pt52
        CALLFAR FNotifyExit
pt52:   DosContext  ds
        cmp     CNotifyGlobal_Count,0
        TaskContext ds
        je      pt60
        CALLFAR CNotifyExit
pt60:   CALLFAR DOS_Abort               ; Clean up file system stuff
    ASSUME  DS:NOTHING
        push    bp
        mov     bp,CurrTCB
        test    [bp].TCBForce_Flg,TK_FF_BUF; Buffer assigned?
        pop     bp
        jz      short pt70              ; Buffer is not assigned
        CALLFAR RlseBuffr               ; Release assigned buffer

;       Bump ref. counts on current directories

pt70:   mov     si,offset TASKAREA:CDS_Handle
        TaskContext ds
        mov     cx,NUMDRIVE
        push    bx                      ; WDM D78512 save around DelCDS loop
pt75:   lodsw                           ; get next handle
        or      ax,ax
        jz      short pt80
        CALLFAR DelCDS
        xor     bx,bx                   ; WDM D78512 to zero CDS_handle
        sub     si,2                    ; WDM D78512 point back to handle
        mov     TASKAREA:[si],bx        ; WDM D78512 zero out handle
        add     si,2                    ; WDM D78512 reset pointer forward
pt80:   loop    pt75
        pop     bx                      ; WDM D78512 restore
;       Remove Join/Subst CDSs for VDMs

        mov     cx,NUMDRIVE
        mov     ax,1                    ; (AX) = 1-base drive number
pt85:   push    ax
        CALLFAR GetCDS
        pop     ax
        jc      short pt90              ; jump if invalid CDS
        cmp     es:[di.cd_pid],0
        je      short pt90              ; don't delete global CDSs
        push    ax
        CALLFAR DelCDS
        pop     ax
pt90:   inc     ax
        loop    pt85

;       Now all files are closed, so it's time to kill the task
;
        call    ProcessKill             ; kill off the process
        InternalError <ProcessTerminate: ProcessKill returned>

EndProc ProcessTerminate


;***EP  w_KillProcess - Terminate a process
;
;       Terminates specified process and decendents (if any).
;
;       ENTRY   (AX) = 0 = terminate process and all child processes
;                      1 = terminate process only
;               (BX) = PID to terminate
;       EXIT    Carry Clear
;                       (AX) = 0 = no error
;               Carry Set
;                       (AX) = error code, invalid PID
;       USES    All exept BP

    ASSUME      DS:NOTHING,ES:NOTHING,SS:TASKAREA

Procedure w_KillProcess,faronly

;       MMIOPH Performance Hook Removed
;       Maj/Min = 1069H, Data = bx (Pid)

ifdef SECURITY                                                     ;@SEC
        xor     cx,cx                   ; zero argument                   ;@SEC
        jmp     stp00                                                     ;@SEC
                                                                          ;@SEC
Entry w_KillProc,faronly                                                  ;@SEC
        mov     ax,1                    ;                                 ;@SEC
        mov     cx,-1                   ; indicate forced kill process    ;@SEC
                                                                          ;@SEC
stp00:                                                                    ;@SEC
endif                                                                     ;@SEC
        test    ax,0feh
        jz      stp0                    ; termination flag ok
        mov     ax,ERROR_INVALID_DATA   ; (AX) = return error if other bits set
        stc                             ; mark error
        jmp     SHORT stp2              ; invalid action code

stp0:   mov     dx,bx                   ; (DX) = PID
        mov     bx,ax
        or      bx,bx
        jnz     stp1                    ; kill only PID
        mov     bx,0                    ; kill Command Subtree
stp1:   xor     ah,ah
        mov     al,SIGTERM
ifndef SECURITY ; only execute the XOR on NON-security kernel                        ;@SEC
        xor     cx,cx                   ; zero argument                   ;@SEC
endif                                                                     ;@SEC
        call    POST_SIGNAL             ; send the signal

stp2:   ret

EndProc w_KillProcess


;***EP  w_CWait - Wait for child process to end (API interface only)
;
;       w_CWait is the API interface procedure for CWait.  See below.
;
;       ENTRY   (AX) = Action code
;                       0 : Find a finished process - ignore it's subtree
;                       1 : Find a finished process tree
;               (BX) = Wait or return flag
;                       0 : If no child (tree or process) is done, wait for it.
;                       1 : If no child (tree or process) is done, do not wait.
;               (CX) = PID
;                       0 : Find any finished child (tree or process)
;                       Nonzero : Find this specific child (tree or process)
;
;       EXIT    Carry Clear
;                       (EAX) = Exit type
;                       (EBX) = PID
;                       (EDX) = Exit code
;               Carry Set
;                       (AX) = ERROR_WAIT_NO_CHILDREN
;                       (AX) = ERROR_CHILD_NOT_COMPLETE
;                       (AX) = ERROR_INTERRUPT
;                       (AX) = ERROR_INVALID_DATA
;
;       USES    AX, BX, CX, DX, SI, DI, ES, DS, Flags

Procedure w_CWait,faronly

        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

;       validate action flag

        mov     dx,ax
        or      dx,bx
        test    dx,0fffeh               ; no bits on except bit 1.
        jz      wcw1                    ; bits off - parameters valid.

        mov     ax,ERROR_INVALID_DATA   ; invalid flags.
        stc
        jmp     short wcwx              ; error codes propogated.

wcw1:   mov     bh,al                   ; (BH) = Action Code
        mov     ax,PS_SYNCPARENT        ; asyncronous child processes only
        FlatContext <ds,es>,dx
        CALLF32 CWait                   ; call internal CWait procedure
wcwx:   ret

EndProc w_CWait


;***LP  CookedKBD - Put keyboard in cooked mode.
;
;       ENTRY:  none
;
;       EXIT:   KBD is in cooked mode for this screen group.
;
;       USES:   AX,BX,SI,DS,ES
;
;       NOTE:   It would be better if we didn't issue the IOCtl unless KBD was
;               in raw mode; however, the only way to determine the KBD state
;               is to issue an IOCtl...

        ASSUME  DS:NOTHING,ES:NOTHING,SS:TASKAREA

Procedure CookedKBD,near

LocalVar    KBDMode,BYTE                ; Parameter packet for Generic IOCtl
ParaPktSize  EQU    1                   ; size of above LocalVar

;       PMONLY

;       check to see if this process' screen group is larger than the
;       normal maximum. If so this process is detached and we don't
;       don't want to be messing with any keyboards
        TaskContext     ds
        mov     al, ss:[Cons_Loc.Scrn_Num]
        cmp     al, NSCRN
        jz      detached

        EnterProc

        CALLFAR AllocReqPacketWait      ; (ES:BX) = request packet

        mov     KBDMode,0               ; Cooked mode

        mov     es:[bx].PktLen,PktHeadSize+LENGenIOCTL2 ; Set packet length
        mov     es:[bx].PktCmd,CMDGenIOCTL ; Set command code

        mov     es:[bx].GIOCategory,IOC_KC ; Set category code
        mov     es:[bx].GIOFunction,IOKC_IM ; Set function code

;       BUGBUG: We assume that the PTDA does not move during this device call
;
        lea     ax,KBDMode              ; (AX) = parameter offset
        mov     word ptr es:[bx].GIOParaPack.Offst,AX ; Set parameter address
        mov     word ptr es:[bx].GIOParaPack.Segmt,SS
        mov     word ptr es:[bx].GIOParaLen,ParaPktSize ; and length

        xor     ax,ax                                   ; AX = 0
        mov     word ptr es:[bx].GIODataPack.Offst,AX   ; Data packet (not used..
        mov     word ptr es:[bx].GIODataPack.Segmt,SS   ; ...but avoids fault)
        mov     word ptr es:[bx].GIODataLen,AX          ; length is zero

        DosContext  <ds>
        lds     SI,ConInpDev            ; (DS:SI) = KBD device driver

        mov     es:[bx].PktStatus,0     ; initialize status
        CALLFAR DevIOCall2              ; Send IOCtl

        CALLFAR FreeReqPacket           ; Done with packet

        LeaveProc

detached:
        ret

EndProc CookedKBD

HIGH3CODE ENDS

        FARCODE HIGH32
TKSWAP_TEXT     SEGMENT

;***EP  TKSuspendThread - Suspended threads execution
;
;       Suspend execution of specified thread.
;
;       ENTRY   TID
;
;       EXIT    (AX) = 0 = success
;                    > 0 = error, invalid thread ID
;
;       USES    EAX, ECX, EDX, Flags

        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _TKSuspendThread

        ArgVar          Tid,DWORD
        LocalVar        pTCB,DWORD

        EnterProc

        lea     eax,[pTCB]
        SSToDS  eax
        PushP   eax                     ; ppTCB
        movzx   eax,WORD PTR Tid
        PushP   eax                     ; Tid
        PushP   [_pPTDACur]             ; pPTDA
        CCALL32 _TKTidTo_pTCB,,,PushP
        or      eax,eax
        stc
        jnz     short sptr              ; Error - exit

        mov     ecx,[pTCB]
        or      ds:[ecx].TCBForce_Flg,TK_FF_ICE; freeze thread's execution
        cmp     ecx,_pTCBCur                        ;B731784
        jne     sptr                                ;B731784
        cmp     [_ptcbPriQReady],0                  ;fix
        je      sptr                                ;fix
        or      _Resched,RESCHED_RELINQUISH         ;B731784
sptr:   LeaveProc
        RETC

EndProc _TKSuspendThread


;***EP  TKResumeThread - Resume suspended thread
;
;       Resume execution of specified thread.
;
;       ENTRY   Tid
;
;       EXIT    (AX) = 0 = success
;                    > 0 = error, invalid thread ID
;
;       USES    EAX, ECX, EDX, Flags

        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _TKResumeThread

        ArgVar          Tid,DWORD
        LocalVar        pTCB,DWORD

        EnterProc
        lea     eax,[pTCB]
        SSToDS  eax
        PushP   eax                     ; ppTCB
        movzx   eax,WORD PTR Tid
        PushP   eax                     ; Tid
        PushP   [_pPTDACur]             ; pPTDA
        CCALL32 _TKTidTo_pTCB,,,PushP
        or      eax,eax
        jnz     short rst2              ; Error - exit     B731678

        mov     eax,[pTCB]
        btr     ds:[eax].TCBForce_Flg,3
        .errnz  ((1 SHL 3) - TK_FF_ICE) ; verify bit index
        jnc     rst4                    ; was not frozen - error B731678

;       Thread was frozen - now we resume it.

        cmp     [eax].TCBState,STATE_FROZEN     ; is this thread frozen?
        jne     short rst1              ; no, don't change

;        CCALL32 _SCHSetState,<eax,STATE_READY>  ; set thread back to run state
        mov     [eax].TCBState,STATE_READY
        CCALL32 _TKUpdateState,<eax>

        mov     dx, [eax].TCBPriority   ; get pri of thread being resumedB731784
        mov     edi,_pTCBCur            ; get current TCB addr           B731784
        mov     cx, [edi].TCBPriority   ; get curr runners pri           B731784
        cmp     cx, dx                  ;                                B731784
        jae     rst1                    ;                             fix
        or      _Resched,RESCHED_RELINQUISH  ;                           B731784
        cmp     [eax].TCBPriClass, CLASS_TIME_CRITICAL   ;               B731784
        jne     rst1                             ;                       B731784
        or      _TCResched,RESCHED_RELINQUISH  ;                         B731784

rst1:   xor     eax,eax
        jmp     short rstx

rst4:   mov     eax,ERROR_NOT_FROZEN    ; B731678
        jmp     short rst3              ; B731678

rst2:   mov     eax,ERROR_INVALID_THREADID
rst3:   stc
rstx:   LeaveProc
        RETC

EndProc _TKResumeThread

TKSWAP_TEXT ENDS

END
