02.2インターバルタイマー(STIMER)
時間に関する機能には、日付と時刻の取得の他にインターバルタイマーがあります。間隔計時機構とも呼ばれ、一定時間おきに行う処理を作る際や一定時間プログラムの実行を止める場合などに利用されます。
10秒間プログラムの実行を停止する
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- LA R2,6 SET LOOP COUNTER TRYENQ DS 0H ENQ (SPFEDIT,DSNMEMB, TEST PDS MEMBER RESERVED BY + E,0,SYSTEMS), ISPF EDITOR OR NOT. + RET=TEST LTR RF,RF SUCCESSFUL ? BZ PROGEND YES, PROGRAM DONE WTO 'MYP001I MEMBER IS USED NOW' NO, INFORM ENQ ERROR SPACE , STIMER WAIT,BINTVL=WAITTIME SLEEP 10SECOND SPACE , BCT R2,TRYENQ TRY ENQ AGAIN SPACE , PROGEND DS 0H SVC 3 EXIT TO DISPATCHER SPACE , WAITTIME DC F'1000' 10.00SEC(1/100SEC ORDER) SPFEDIT DC CL8'SPFEDIT' ENQ CATEGORY DSNMEMB DC AL1(52) RESOURCE NAME LENGTH DC CL44'MY.JCL' DSNAME DC CL8'DATA1' MEMBER
一定時間プログラムの実行を止めるにはSTIMERサービスのWAIT機能を使います。STIMERマクロの最初の定位置パラメーターにWAITを指定し、続けて待ち合わせ時間を定義したパラメーターを指定します。サンプルでは待ち合わせ時間を2進整数で指定しています。1/100秒単位で指定でき、1は1/100秒、100は1秒となります。STIMERマクロ発行後、OSサービスルーチン内で指定した時間が経過するまで待ち状態に入ります。指定した時間が経過するとプログラムに戻ってきます。
サンプルの処理内容は、指定した区分データセットのメンバーがISPFエディターで編集中かをENQマクロでテストします。編集中であればENQが失敗するので、その事をWTOマクロでコンソールにメッセージで通知して、10秒間待ち状態に入ります。10秒経過後、再びENQをトライします。このサイクルで6回繰り返し、都合1分間リトライします。ENQに成功した場合と、リトライ回数をオーバーしたらプログラムは終了します。
ENQマクロによる排他制御が獲得できない時、一定回数リトライすることはよく行われますが、人間の操作が絡む資源の場合、単にループするよりはSTIMERマクロを組み合わせて一定時間待ってからリトライするのが一般的です。
指定した時刻になったら通知してもらう
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- MVI WKUPECB,0 CLEAR ECB STIMER REAL,TIMREXIT, SET TIMER + TOD=WKUPTIME WAIT ECB=WKUPECB WAKE-UP AT SPECIFIED TIME : : 指定した時刻に行う処理をここに書く : : WKUPECB DC F'0' ECB FOR WAKE-UP MAINLINE WKUPTIME DC ZL8'15000000' WAKE-UP TIME=15:00:00.00 : : TIMREXIT DS 0H USING *,RF DEFINE TIMER EXIT BASE REG ST RE,12(,RD) SAVE RETURN ADDRESS L R1,AECB LOAD ECB ADDRESS POST (1) WAKE-UP MAINLINE ROUTINE L RE,12(,RD) LOAD RETURN ADDRESS B 0(,RE) RETURN TO OS AECB DC A(WKUPECB) PTR TO MAINLINE ECB WORD DROP RF FORGET BASE REG
目覚まし時計プログラムです。一定時間の経過ではなく、指定した時刻になったら起き上がるサンプルです。今度はWAITではなくREALを指定しています。REALは実時間の経過を通知する機能です。TODパラメーターは間隔時間ではなく時刻を指定するパラメーターです。MVSではTODの代わりにLTパラメーターでもかまいません。
運用の自動化ソフトなどを使えば必要ありませんが、18:00になったらオンラインシステムを終了させる、21:00になったらバックアップジョブを実行させる、など決まった時刻になったら行う処理を自動化させるためには目覚まし時計が必要です。
10秒ループしたら自分で自分をキャンセルする
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- STIMER TASK,TIMREXIT, SET TIMER BY USED CPU TIME + TUINTVL=CPUTIMER : : LOOP DS 0H LOCAL CPU LOOP AT HERE LA R0,* I SLL R0,31 I ALR R0,R1 I SRDL R0,14 I B LOOP V : : CPUTIMER DC F'384000' AVAILABLE CPU TIME : : TIMREXIT DS 0H ABEND 322 ABEND US WITH U322
実時間ではなくCPU時間によるインターバルタイムの計測です。REALの代わりにTASKと指定します。間隔時間の指定方法はREALもTASKも同じです。このサンプルではCPUタイマー単位(約26.04166マイクロ秒)で指定しています。約10秒です。わかりにくいので普通にBINTVLで指定してかまいません。
サンプルの処理は一定のCPU時間を使い切ったらプログラムをABENDさせる例です。タイマーをセットしてから、わざと無限ループに入ります。指定した時間のCPUを使い切ると、TIMREXITに飛び込んできます。
TIMREXIT DS 0H USING *,RF DEFINE TEMP BASE REG STM RE,RC,12(RD) SAVE CALLER GPRS L RC,MAINBASE ESTABLISH OUR BASE ADDRESS DROP RF FORGET TEMP BASE REG : : POST WKUPECB POST TO WAKE-UP MAIN LINE : : LM RE,RC,12(RD) LOAD CALLER GPRS BR RE RETURN TO CALLER(OS) MAINBASE DC A(MAINENTR) MAIN LINE BASE ADDRESS
サンプルではタイマー出口内で大した処理をしてませんので簡単に書いてますが、出口ルーチン内からメインライン側のデータ領域などを直接参照・更新したい場合は、上記のようなハウスキーピングをすればいいでしょう。メインライン側のベースアドレスを同じベースレジスターに再設定します。STIMER出口ルーチンの規約では、汎用レジスター0?12の内容はSTIMERマクロ発行時の内容とは規定されていません。仮にGR12にプログラムのベースアドレスが入っていたとしても、それはたまたまです。マニュアル通りGR0?12は壊れていると言う前提で再設定しましょう。STIMERに限らずすべてのマクロの出口ルーチンについて言えます。マニュアルに記載されている出口ルーチンのレジスター規約を必ず確認してそれに従います。
STIMERで設定したタイマーは設定時間が経過して出口で通知されると無効になります。再びタイマーによる時間測定が必要なら改めてSTIMERマクロを発行する必要があります。STIMERマクロは必ずしもメインルーチン内で出す必要はありません。出口ルーチン内でSTIMERマクロを発行してタイマーを再設定してもかまいません。
タイマー測定のキャンセル
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- STIMER REAL,TIMREXIT, SET TIMER BY REAL TIME + BINTVL=INTVLTMR : : L R0,=F'10000000' LOAD LOOP COUNTER LOOP DS 0H LOCAL CPU LOOP AT HERE SLR R2,R2 I LA R3,0 I XR R4,R4 I L R5,=F'0' I BCT R0,LOOP V : : TTIMER CANCEL CANCEL TIMER LTR R0,R0 HAVE ANY REMAINING TIME ? + REMAINING TIME STORED IN GR0 + WITH CPUTIMER FORMAT(26.04166) : : INTVLTMR DC F'1000' 10.00SEC : : TIMREXIT DS 0H BR RE NO OPERATING IN EXIT
TTIMERマクロを使うと一度設定したタイマーの残り時間を調べたり、タイマー計測をキャンセルすることができます。
サンプルでは10秒の実時間タイマーを設定してから、5命令×一千万回で計五千万回の命令を実行します。その後TTIMERで設定したタイマーを取り消します。GR0にタイマーの残り時間がCPUタイマー形式(約26.04166マイクロ秒単位)で返されます。サンプルではタイマー出口は意味を持たないのでBR 14命令で何もせずに復帰しています。
タイマーを設定している常駐型のプログラムなどでは、オペレーターコマンドなどによって処理を終了する時、TTIMERで不要になったタイマー設定を取り消します。TPモニターなどユーザーアプリケーションを自分の制御で実行するようなソフトでは、ユーザープログラム開始前にTASK指定のSTIMERでCPUタイマーを設定し、ユーザープログラムが終了した時点でそれを取り消したりします。
STIMERサービスは1つのタスクで同時に複数使用することはできません。STIMERサービスによるインターバルタイマーの設定は1つしか出来ないのです。同じタスクで複数のインターバルタイムを計測するためにはSTIMERM(MSPではSTIMERE、VOS3では公開されていません)マクロを利用します。MSPのSTIMEREサービスでは経過時間の通知に出口ルーチンではなく、ECBポストによる方法も選択できます。