%ZTMS2 ;SEA/RDS-TaskMan: Submanager, Part 4 (Unload, Get Device) ;2/19/08 13:38
;;8.0;KERNEL;**2,18,23,36,67,118,127,163,167,175,199,275,446**;Jul 10, 1995;Build 44
;Per VHA Directive 2004-038, this routine should not be modified.
;
;^%ZTSK(ZTSK),^%ZTSCH("DEV",IO) is locked on entry or return from GETNEXT
PROCESS ;SUBMGR--process task and all others waiting for same device
L +^%ZTSCH("TASK",ZTSK):1 I '$T Q ;Only allow one copy of a task at one time
D LOOKUP I $D(ZTREJECT) Q
D DEVICE
I POP L Q ;Release all locks
I ZTSYNCFL]"",'$$SYNCFLG("A",ZTSYNCFL,%ZTIO) D Q
. D SYNCQ(ZTSYNCFL,%ZTIO,ZTDTH,ZTSK),^%ZISC L ;Release all locks
. Q
;Go run task
D TASK^%ZTMS3 I ZTYPE="C"!$D(ZTNONEXT) Q
D GETNEXT^%ZTMS7 I $D(ZTNONEXT)!$D(ZTQUIT) Q
G PROCESS
;
LOOKUP ;PROCESS--unload task, switch ucis, and test entry routine
K (%ZTIME,%ZTIO,DT,IO,U,ZTCPU,ZTDEVN,ZTDTH,ZTNODE,ZTPAIR,ZTPFLG,ZTQUEUED,ZTSK,ZTUCI,ZTYPE,ZTLKTM) ;p446
D TSKSTAT(4,"")
S ZTREC=^%ZTSK(ZTSK,0),ZTREC02=^(.02)
S ZTREC2=^%ZTSK(ZTSK,.2),ZTREC21=^(.21),ZTREC25=^(.25)
S ZTSYNCFL=$P(ZTREC2,"^",7),DUZ=+$P(ZTREC,U,3),DUZ(0)="@"
S X=$P(ZTREC02,U)_","_$P(ZTREC02,U,2)
I $P(ZTREC02,U,4) S $P(X,",",2)=ZTCPU
;should do a check to see if X is OK, Should check UCI mapping.
I X'=ZTUCI S ZTUCI=X D SWAP^%XUCI
S X=$P($P(ZTREC,U,2),"("),ZTRTN=$P(ZTREC,U,1,2)
I $E(X)'="%",$L(X) X ^%ZOSF("TEST") I X=""!'$T D REJECT S ZTREJECT=""
Q
;
REJECT ;LOOKUP--entry routine isn't here; reject task
N Y X ^%ZOSF("UCI")
D TSKSTAT("B","No routine at destination "_Y_".")
I $D(ZTDEVN) D DEVLK^%ZTMS1(-1,%ZTIO) K ZTDEVN
L Q ;Clear all locks
;
DEVICE ;PROCESS--prepare requested device; if can't, make task wait
;First clean-up all IO variables that could influence the device
K %ZIS,IO,IOCPU,IOHG,IOPAR,IOUPAR,IOS
;If don't need a device, Setup minimum.
S ZTIO=$P(ZTREC2,U),ZTIOT=$P(ZTREC2,U,3)
I ZTIO="" S (IO,IO(0),IOF,IOM,ION,IOS,IOSL,IOST,IOT)="",POP=0 Q
;
;setup call
S %ZIS="LRS0"_$S($P(ZTREC2,U,5)="DIRECT":"D",1:"")
S:ZTIOT="HFS" %ZIS("HFSIO")=$P(ZTREC2,U,6),%ZIS("IOPAR")=ZTREC25
S:ZTIOT="MT" %ZIS("IOPAR")=ZTREC25
S (IO,IO(0))=%ZTIO,IOP=ZTIO
S:'$D(^%ZTSCH("DEVTRY",$P(ZTIO,";"))) ^($P(ZTIO,";"))=%ZTIME ;Set problem device check
K ^XUTL("XQ",$J),IO("ERROR")
;
S:$P(ZTREC2,U,4)["MINIOUT" %ZISLOCK="^%ZTSCH(""NETMAIL"",IO)" ;The hang is on the close
;call
S %ZISTO=3 D ^%ZIS K %ZISTO,%ZISLOCK ;See that we use a timeout.
I %ZTIO]"" D DEVLK^%ZTMS1(-1,%ZTIO) K ZTDEVN
I 'POP K ^%ZTSCH("DEVTRY",IO),^($P(ZTIO,";")) ;Clear problem device check
;Reset %ZTIO if IO doesn't match
I 'POP,%ZTIO]"",IO'=%ZTIO C %ZTIO K IO(1,%ZTIO),^%ZTSCH("DEVTRY",$P(%ZTIO,";")) S %ZTIO=IO
;
;results
I POP,(ZTYPE'="C"),(ZTIOT="TRM")!(ZTIOT="RES")!(ZTIOT="HG") D IONQ Q ;only add to IO queue if not type C.
I POP D SCHNQ Q
I IOT'="RES",IOT'="HG" U IO
S IO(0)=IO
I $P(^%ZIS(1,+IOS,0),U,7)="y" D ^%ZTMSH
Q
;
IONQ ;DEVICE--put task on Device Waiting List
I $D(^%ZTSK(ZTSK,0))[0 D TSKSTAT("I",4) G IOQX
D TSKSTAT("A","")
N %ZTIO S %ZTIO=IO
S ZTIO(1)=$P(ZTREC2,U,5),ZTIOS=ZTREC21
D NQ^%ZTM4 ;Uses %ZTIO as the Device $I value
IOQX L Q ;Clear all Locks
;
SCHNQ ;DEVICE--if HFS or SPL or TYPE'=C, reschedule task 10 min in future (try later)
S ZTH=$$NEWH($H,300)
D TSKSTAT(1,"rescheduled for busy device")
S $P(^%ZTSK(ZTSK,.2),U,8)=$P(^%ZTSK(ZTSK,.2),U,8)+1 ;ReQ count
D SCHTM(ZTH)
I $L($G(IO("ERROR"))) S $P(^%ZTSK(ZTSK,.12),U,2,9)=$H_U_IO("ERROR") ;May tell why couldn't get device
L Q ;Clear all locks
;
SCHTM(ZTDTH) ;Set a new schedule time, See that task is updated
S $P(^%ZTSK(ZTSK,0),U,6)=$$H0^%ZTM(ZTDTH),^%ZTSK(ZTSK,.04)=ZTDTH,^%ZTSCH(ZTDTH,ZTSK)=""
Q
NEWH(%H,%Y) ;Build a new schedule time, Return $H3 time.
N %
I %H["," S %H=$$H3^%ZTM(%H)
Q (%H+%Y)
;
SYNCFLG(ACT,FLAG,ZIO,STAT) ;Allocate/deallocate sync flag
N X,DA,SYNC
L +^%ZISL(14.8):30 E Q 0
S X=0,SYNC=FLAG_"~"_ZIO,DA=$O(^%ZISL(14.8,"B",SYNC,0))
I ACT["A" D
. I DA S X=0 Q
. ;I $D(^%ZTSCH("SYNC",ZIO,FLAG)) S X=0 Q
. S X=$P(^%ZISL(14.8,0),"^",3)+1 F Q:'$D(^%ZISL(14.8,X)) S X=X+1
. S $P(^(0),"^",3,4)=X_"^"_($P(^%ZISL(14.8,0),"^",4)+1),^%ZISL(14.8,X,0)=SYNC,^%ZISL(14.8,"B",SYNC,X)=""
. S X=1 Q
I ACT["D" D S X=1
. Q:DA'>0
. K ^%ZISL(14.8,DA),^%ZISL(14.8,"B",SYNC,DA)
. S $P(^(0),"^",3,4)=(DA-1)_"^"_($P(^%ZISL(14.8,0),"^",4)-1)
. Q
I ACT["S" D S X=1
. Q:DA'>0
. S ^%ZISL(14.8,DA,1)=$G(STAT)
. Q
I ACT["?" S X=(DA)!($D(^%ZTSCH("SYNC",ZIO,FLAG)))
L -^%ZISL(14.8)
Q X
;
SYNCQ(FLAG,ZIO,ZTH,ZTSK) ;Put task on sync flag waiting list
L +^%ZTSCH("SYNC")
S ^%ZTSCH("SYNC",ZIO,FLAG,ZTSK)=ZTH
L -^%ZTSCH("SYNC")
Q
SCHSYNC(FLAG,ZIO) ;put a waiting task in IO queue
L +^%ZTSCH("SYNC") I $D(^%ZTSCH("SYNC",ZIO,FLAG)) N ZTH,ZTSK D
. S ZTSK=$O(^(FLAG,0)),ZTH=$G(^(+ZTSK)) Q:ZTSK="" S:$D(^%ZTSCH("IO",ZIO))[0 ^(ZIO)=IOT
. S ^%ZTSCH("IO",ZIO,ZTH,ZTSK)=""
. K ^%ZTSCH("SYNC",ZIO,FLAG,ZTSK)
. Q
L -^%ZTSCH("SYNC")
Q
TSKSTAT(CODE,MSG) ;Record status
S $P(^%ZTSK(ZTSK,.1),U,1,3)=$G(CODE)_U_$H_U_$G(MSG)
Q
;
POST ;Post INIT cleanup for patch XU*8*167
N T S T=0
F S T=$O(^%ZTSCH(T)) Q:T'>0 I $D(^%ZTSCH(T,0)) K ^%ZTSCH(T,0)
Q
%ZTMS2 ;SEA/RDS-TaskMan: Submanager, Part 4 (Unload, Get Device) ;2/19/08 13:38
+1 ;;8.0;KERNEL;**2,18,23,36,67,118,127,163,167,175,199,275,446**;Jul 10, 1995;Build 44
+2 ;Per VHA Directive 2004-038, this routine should not be modified.
+3 ;
+4 ;^%ZTSK(ZTSK),^%ZTSCH("DEV",IO) is locked on entry or return from GETNEXT
PROCESS ;SUBMGR--process task and all others waiting for same device
+1 ;Only allow one copy of a task at one time
LOCK +^%ZTSCH("TASK",ZTSK):1
IF '$TEST
QUIT
+2 DO LOOKUP
IF $DATA(ZTREJECT)
QUIT
+3 DO DEVICE
+4 ;Release all locks
IF POP
LOCK
QUIT
+5 IF ZTSYNCFL]""
IF '$$SYNCFLG("A",ZTSYNCFL,%ZTIO)
Begin DoDot:1
+6 ;Release all locks
DO SYNCQ(ZTSYNCFL,%ZTIO,ZTDTH,ZTSK)
DO ^%ZISC
LOCK
+7 QUIT
End DoDot:1
QUIT
+8 ;Go run task
+9 DO TASK^%ZTMS3
IF ZTYPE="C"!$DATA(ZTNONEXT)
QUIT
+10 DO GETNEXT^%ZTMS7
IF $DATA(ZTNONEXT)!$DATA(ZTQUIT)
QUIT
+11 GOTO PROCESS
+12 ;
LOOKUP ;PROCESS--unload task, switch ucis, and test entry routine
+1 ;p446
KILL (%ZTIME,%ZTIO,DT,IO,U,ZTCPU,ZTDEVN,ZTDTH,ZTNODE,ZTPAIR,ZTPFLG,ZTQUEUED,ZTSK,ZTUCI,ZTYPE,ZTLKTM)
+2 DO TSKSTAT(4,"")
+3 SET ZTREC=^%ZTSK(ZTSK,0)
SET ZTREC02=^(.02)
+4 SET ZTREC2=^%ZTSK(ZTSK,.2)
SET ZTREC21=^(.21)
SET ZTREC25=^(.25)
+5 SET ZTSYNCFL=$PIECE(ZTREC2,"^",7)
SET DUZ=+$PIECE(ZTREC,U,3)
SET DUZ(0)="@"
+6 SET X=$PIECE(ZTREC02,U)_","_$PIECE(ZTREC02,U,2)
+7 IF $PIECE(ZTREC02,U,4)
SET $PIECE(X,",",2)=ZTCPU
+8 ;should do a check to see if X is OK, Should check UCI mapping.
+9 IF X'=ZTUCI
SET ZTUCI=X
DO SWAP^%XUCI
+10 SET X=$PIECE($PIECE(ZTREC,U,2),"(")
SET ZTRTN=$PIECE(ZTREC,U,1,2)
+11 IF $EXTRACT(X)'="%"
IF $LENGTH(X)
XECUTE ^%ZOSF("TEST")
IF X=""!'$TEST
DO REJECT
SET ZTREJECT=""
+12 QUIT
+13 ;
REJECT ;LOOKUP--entry routine isn't here; reject task
+1 NEW Y
XECUTE ^%ZOSF("UCI")
+2 DO TSKSTAT("B","No routine at destination "_Y_".")
+3 IF $DATA(ZTDEVN)
DO DEVLK^%ZTMS1(-1,%ZTIO)
KILL ZTDEVN
+4 ;Clear all locks
LOCK
QUIT
+5 ;
DEVICE ;PROCESS--prepare requested device; if can't, make task wait
+1 ;First clean-up all IO variables that could influence the device
+2 KILL %ZIS,IO,IOCPU,IOHG,IOPAR,IOUPAR,IOS
+3 ;If don't need a device, Setup minimum.
+4 SET ZTIO=$PIECE(ZTREC2,U)
SET ZTIOT=$PIECE(ZTREC2,U,3)
+5 IF ZTIO=""
SET (IO,IO(0),IOF,IOM,ION,IOS,IOSL,IOST,IOT)=""
SET POP=0
QUIT
+6 ;
+7 ;setup call
+8 SET %ZIS="LRS0"_$SELECT($PIECE(ZTREC2,U,5)="DIRECT":"D",1:"")
+9 IF ZTIOT="HFS"
SET %ZIS("HFSIO")=$PIECE(ZTREC2,U,6)
SET %ZIS("IOPAR")=ZTREC25
+10 IF ZTIOT="MT"
SET %ZIS("IOPAR")=ZTREC25
+11 SET (IO,IO(0))=%ZTIO
SET IOP=ZTIO
+12 ;Set problem device check
IF '$DATA(^%ZTSCH("DEVTRY",$PIECE(ZTIO,";")))
SET ^($PIECE(ZTIO,";"))=%ZTIME
+13 KILL ^XUTL("XQ",$JOB),IO("ERROR")
+14 ;
+15 ;The hang is on the close
IF $PIECE(ZTREC2,U,4)["MINIOUT"
SET %ZISLOCK="^%ZTSCH(""NETMAIL"",IO)"
+16 ;call
+17 ;See that we use a timeout.
SET %ZISTO=3
DO ^%ZIS
KILL %ZISTO,%ZISLOCK
+18 IF %ZTIO]""
DO DEVLK^%ZTMS1(-1,%ZTIO)
KILL ZTDEVN
+19 ;Clear problem device check
IF 'POP
KILL ^%ZTSCH("DEVTRY",IO),^($PIECE(ZTIO,";"))
+20 ;Reset %ZTIO if IO doesn't match
+21 IF 'POP
IF %ZTIO]""
IF IO'=%ZTIO
CLOSE %ZTIO
KILL IO(1,%ZTIO),^%ZTSCH("DEVTRY",$PIECE(%ZTIO,";"))
SET %ZTIO=IO
+22 ;
+23 ;results
+24 ;only add to IO queue if not type C.
IF POP
IF (ZTYPE'="C")
IF (ZTIOT="TRM")!(ZTIOT="RES")!(ZTIOT="HG")
DO IONQ
QUIT
+25 IF POP
DO SCHNQ
QUIT
+26 IF IOT'="RES"
IF IOT'="HG"
USE IO
+27 SET IO(0)=IO
+28 IF $PIECE(^%ZIS(1,+IOS,0),U,7)="y"
DO ^%ZTMSH
+29 QUIT
+30 ;
IONQ ;DEVICE--put task on Device Waiting List
+1 IF $DATA(^%ZTSK(ZTSK,0))[0
DO TSKSTAT("I",4)
GOTO IOQX
+2 DO TSKSTAT("A","")
+3 NEW %ZTIO
SET %ZTIO=IO
+4 SET ZTIO(1)=$PIECE(ZTREC2,U,5)
SET ZTIOS=ZTREC21
+5 ;Uses %ZTIO as the Device $I value
DO NQ^%ZTM4
IOQX ;Clear all Locks
LOCK
QUIT
+1 ;
SCHNQ ;DEVICE--if HFS or SPL or TYPE'=C, reschedule task 10 min in future (try later)
+1 SET ZTH=$$NEWH($HOROLOG,300)
+2 DO TSKSTAT(1,"rescheduled for busy device")
+3 ;ReQ count
SET $PIECE(^%ZTSK(ZTSK,.2),U,8)=$PIECE(^%ZTSK(ZTSK,.2),U,8)+1
+4 DO SCHTM(ZTH)
+5 ;May tell why couldn't get device
IF $LENGTH($GET(IO("ERROR")))
SET $PIECE(^%ZTSK(ZTSK,.12),U,2,9)=$HOROLOG_U_IO("ERROR")
+6 ;Clear all locks
LOCK
QUIT
+7 ;
SCHTM(ZTDTH) ;Set a new schedule time, See that task is updated
+1 SET $PIECE(^%ZTSK(ZTSK,0),U,6)=$$H0^%ZTM(ZTDTH)
SET ^%ZTSK(ZTSK,.04)=ZTDTH
SET ^%ZTSCH(ZTDTH,ZTSK)=""
+2 QUIT
NEWH(%H,%Y) ;Build a new schedule time, Return $H3 time.
+1 NEW %
+2 IF %H[","
SET %H=$$H3^%ZTM(%H)
+3 QUIT (%H+%Y)
+4 ;
SYNCFLG(ACT,FLAG,ZIO,STAT) ;Allocate/deallocate sync flag
+1 NEW X,DA,SYNC
+2 LOCK +^%ZISL(14.8):30
IF '$TEST
QUIT 0
+3 SET X=0
SET SYNC=FLAG_"~"_ZIO
SET DA=$ORDER(^%ZISL(14.8,"B",SYNC,0))
+4 IF ACT["A"
Begin DoDot:1
+5 IF DA
SET X=0
QUIT
+6 ;I $D(^%ZTSCH("SYNC",ZIO,FLAG)) S X=0 Q
+7 SET X=$PIECE(^%ZISL(14.8,0),"^",3)+1
FOR
IF '$DATA(^%ZISL(14.8,X))
QUIT
SET X=X+1
+8 SET $PIECE(^(0),"^",3,4)=X_"^"_($PIECE(^%ZISL(14.8,0),"^",4)+1)
SET ^%ZISL(14.8,X,0)=SYNC
SET ^%ZISL(14.8,"B",SYNC,X)=""
+9 SET X=1
QUIT
End DoDot:1
+10 IF ACT["D"
Begin DoDot:1
+11 IF DA'>0
QUIT
+12 KILL ^%ZISL(14.8,DA),^%ZISL(14.8,"B",SYNC,DA)
+13 SET $PIECE(^(0),"^",3,4)=(DA-1)_"^"_($PIECE(^%ZISL(14.8,0),"^",4)-1)
+14 QUIT
End DoDot:1
SET X=1
+15 IF ACT["S"
Begin DoDot:1
+16 IF DA'>0
QUIT
+17 SET ^%ZISL(14.8,DA,1)=$GET(STAT)
+18 QUIT
End DoDot:1
SET X=1
+19 IF ACT["?"
SET X=(DA)!($DATA(^%ZTSCH("SYNC",ZIO,FLAG)))
+20 LOCK -^%ZISL(14.8)
+21 QUIT X
+22 ;
SYNCQ(FLAG,ZIO,ZTH,ZTSK) ;Put task on sync flag waiting list
+1 LOCK +^%ZTSCH("SYNC")
+2 SET ^%ZTSCH("SYNC",ZIO,FLAG,ZTSK)=ZTH
+3 LOCK -^%ZTSCH("SYNC")
+4 QUIT
SCHSYNC(FLAG,ZIO) ;put a waiting task in IO queue
+1 LOCK +^%ZTSCH("SYNC")
IF $DATA(^%ZTSCH("SYNC",ZIO,FLAG))
NEW ZTH,ZTSK
Begin DoDot:1
+2 SET ZTSK=$ORDER(^(FLAG,0))
SET ZTH=$GET(^(+ZTSK))
IF ZTSK=""
QUIT
IF $DATA(^%ZTSCH("IO",ZIO))[0
SET ^(ZIO)=IOT
+3 SET ^%ZTSCH("IO",ZIO,ZTH,ZTSK)=""
+4 KILL ^%ZTSCH("SYNC",ZIO,FLAG,ZTSK)
+5 QUIT
End DoDot:1
+6 LOCK -^%ZTSCH("SYNC")
+7 QUIT
TSKSTAT(CODE,MSG) ;Record status
+1 SET $PIECE(^%ZTSK(ZTSK,.1),U,1,3)=$GET(CODE)_U_$HOROLOG_U_$GET(MSG)
+2 QUIT
+3 ;
POST ;Post INIT cleanup for patch XU*8*167
+1 NEW T
SET T=0
+2 FOR
SET T=$ORDER(^%ZTSCH(T))
IF T'>0
QUIT
IF $DATA(^%ZTSCH(T,0))
KILL ^%ZTSCH(T,0)
+3 QUIT