www.pudn.com > norti2.0 > NOMON.C
/******************************************************************************
* NORTiオブジェクトモニタ・サンプル(PC9801,IBM-PC,FMR,ROM) *
* *
* File name : nomon.c *
* Copyright (c) Miyazaki System Planning Office. 1991-1995 *
* *
* Compile : cl /c /A? /Ox nomon.c (MS-C 5.1/6.0/7.0) *
* tcc -c -m? nomon.c (TC 2.0, TC++ 1.0) *
* bcc -c -m? -O2 nomon.c (BC++ 3.x) *
* *
* 91-10-25 TRCOM Version *
* 92-02-16 Ver1.00 *
* 92-08-20 Ver1.10 *
* 93-01-18 Ver1.11 *
* 93-02-17 Ver1.12 *
* 93-05-16 Ver1.13β *
* 94-01-05 Ver1.14 *
* 95-06-15 Ver1.20 *
* 95-09-20 Ver1.21 *
******************************************************************************/
#if 0
・下記のマクロを定義することで、コンパイルを制御できます。
CLKS=? ・・・ システムクロック・モニタ数(0〜1,デフォルト1)
RDQS=? ・・・ レディキュー・モニタ数 (0〜1,デフォルト1)
TSKS=? ・・・ タスク・モニタ数 (0〜 ,デフォルト6)
FLGS=? ・・・ イベントフラグ・モニタ数 (0〜 ,デフォルト2)
SEMS=? ・・・ セマフォ・モニタ数 (0〜 ,デフォルト2)
MBXS=? ・・・ メイルボックス・モニタ数 (0〜 ,デフォルト2)
MPLS=? ・・・ メモリプール・モニタ数 (0〜 ,デフォルト2)
TIM=? ・・・・ オブジェクトモニタ用タイマハンドラ周期(0〜,MSEC単位,デフォルト1)
ROM ・・・・・・ 画面出力しない(ROM化等)
NOSPL ・・・・ PC9801で画面分割しない
(例) cl /c /Ox /DTSKS=14 /DFLGS=0 /DSEMS=0 /DMBXS=0 /DMPLS=0 /DROM nomon.c
tcc -c -DTSKS=14 -DFLGS=0 -DSEMS=0 -DMBXS=0 -DMPLS=0 -DROM nomon.c
・画面出力の形式
CLK RDQ1 TSK1 TSK2 TSK3 TSK4 TSK5 TSK6 FLG1 FLG2 SEM1 SEM2 MBX1 MBX2 MPL1 MPL2
.... .... .... .... .... .... .... .... .... .... .... .... .... .... .... ....
.... .... .... .... .... .... .... .... .... .... .... .... .... .... .... ....
・オブジェクトモニタバッファの形式
extern B NEAR monbuf[]; ・・・・・ ASCIIZ文字列の配列
monbuf+0x00 'CLK .... .... ',0
+0x10 'RDQ1 .... .... ',0
+0x20 'TSK1 .... .... ',0
+0x30 'TSK2 .... .... ',0
+0x40 'TSK3 .... .... ',0
:
+0xf0 'MPL2 .... .... ',0,0
#endif
#ifdef M_I86 /* MS-C */
#include
#include
#include
#include
#endif
#ifdef __TURBOC__
#include
#include
#include
#endif
#if (defined(_MCC68K)||defined(__TID__)||defined(__CPU__))
#include /* ICC */ /* Hitachi C */
#undef ROM
#define ROM
#endif
#ifdef LSI_C80
#include
#undef ROM
#define ROM
#endif
#define NOMON_C
#include "norti.h"
#include "nosys.h"
#ifdef M_I86
#pragma check_stack(off) /* MS-C スタックチェックなし */
#endif
#ifndef NULL
#define NULL 0 /* NULLポインタ */
#endif
/* モニタする個数の定義 */
#ifndef CLKS
#define CLKS 1 /* システムクロック・モニタ数 */
#endif
#ifndef RDQS
#define RDQS 1 /* レディキュー・モニタ数 */
#endif
#ifndef TSKS
#define TSKS 6 /* タスク・モニタ数 */
#endif
#ifndef FLGS
#define FLGS 2 /* イベントフラグ・モニタ数 */
#endif
#ifndef SEMS
#define SEMS 2 /* セマフォ・モニタ数 */
#endif
#ifndef MBXS
#define MBXS 2 /* メイルボックス・モニタ数 */
#endif
#ifndef MPLS
#define MPLS 2 /* メモリプール・モニタ数 */
#endif
/* モニタする個数の合計 */
#define TOTAL (CLKS+RDQS+TSKS+FLGS+SEMS+MBXS+MPLS)
#if (TOTAL<16)
#define OBJS 16 /* 最低16個 */
#else
#define OBJS TOTAL
#endif
/* その他の定義 */
#ifndef TIM
#define TIM 1 /* タイマハンドラ周期(MSEC単位)*/
#endif
/* 定義されている変数 */
B NEAR cdecl monbuf[(OBJS+1)*16]; /* オブジェクトモニタ・バッファ */
/* 定義されている関数 */
TMRHDR montmr(void); /* オブジェクトモニタ・ハンドラ */
void cdecl monext(void); /* オブジェクトモニタ終了 */
void cdecl monsta(void); /* オブジェクトモニタ起動 */
BOOL cdecl set_montsk(ID id); /* モニタする先頭タスクIDを設定 */
BOOL cdecl set_monflg(ID id); /* モニタする先頭イベントフラグIDを設定 */
BOOL cdecl set_monsem(ID id); /* モニタする先頭セマフォIDを設定 */
BOOL cdecl set_monmbx(ID id); /* モニタする先頭メイルボックスIDを設定 */
BOOL cdecl set_monmpl(ID id); /* モニタする先頭メモリプールIDを設定 */
/* 直書きするVRAMアドレス(PC9801)*/
#ifdef NOSPL
#define VRAM_98 0xa0000000L /* 画面分割しない場合はテキストVRAM先頭 */
#else
#define VRAM_98 0xa00010a0L /* 画面分割する場合は裏テキストVRAM */
#endif /*(日本語FEPの使う領域を避けて+0xa0)*/
/* 内部変数 */
#ifndef ROM
static W NEAR vram = VRAM_98; /* モニタ画面のVRAMアドレス */
static B NEAR videobuf[80*3]; /* 画面出力バッファ */
#endif
static ID NEAR mon_tskid = 1; /* モニタする先頭タスクID */
static ID NEAR mon_flgid = 1; /* モニタする先頭イベントフラグID */
static ID NEAR mon_semid = 1; /* モニタする先頭セマフォID */
static ID NEAR mon_mbxid = 1; /* モニタする先頭メイルボックスID */
static ID NEAR mon_mplid = 1; /* モニタする先頭メモリプールID */
static UB NEAR montmr_cnt; /* タイマハンドラ内部のカウンタ */
/* 1桁16進変換マクロ(0〜9,a〜f)*/
#define ito1x(p,i) (*(p)=(B)((((i)&15)<10)?('0'+((i)&15)):('a'-10+((i)&15))))
/* 1桁ID変換マクロ(0〜9,A〜無制限)*/
#define ito1id(p,i) (*(p)=(B)((i<10)?('0'+i):('A'-10+(i))))
/*****************************************************************************
* INT型の16進ASCII変換
*
******************************************************************************/
static void NEAR ito04x(B NEAR *p, int i)
{
ito1x(p++, i>>12);
ito1x(p++, i>>8 );
ito1x(p++, i>>4 );
ito1x(p, i );
}
/*****************************************************************************
* オブジェクトモニタ・バッファ初期化
*
******************************************************************************/
static void NEAR init_monbuf(void)
{
B NEAR *p;
INT i;
#ifndef ROM
memset(videobuf, ' ', sizeof videobuf);
#endif
memset(monbuf, '\0', sizeof monbuf);
for (i = 0; i < OBJS; i++)
{ memset(monbuf + i * 16, ' ', 15);
}
p = monbuf;
#if CLKS
memcpy(p, "CLK", 3);
p += 16;
#endif
#if RDQS
memcpy(p, "RDQ", 3);
p += 16;
#endif
#if TSKS
for (i = TSKS; i != 0; i--)
{ memcpy(p, "TSK", 3);
p += 16;
}
#endif
#if FLGS
for (i = FLGS; i != 0; i--)
{ memcpy(p, "FLG", 3);
p += 16;
}
#endif
#if SEMS
for (i = SEMS; i != 0; i--)
{ memcpy(p, "SEM", 3);
p += 16;
}
#endif
#if MBXS
for (i = MBXS; i != 0; i--)
{ memcpy(p, "MBX", 3);
p += 16;
}
#endif
#if MPLS
for (i = MPLS; i != 0; i--)
{ memcpy(p, "MPL", 3);
p += 16;
}
#endif
}
#if CLKS
/*****************************************************************************
* システムクロック状態モニタ
*
* CLK
* xxxx システム時刻下位(16進)
* iiii 時間待ちタスクIDの並び
******************************************************************************/
static void NEAR monclk(B NEAR *p)
{
/* 2行目の出力データ作成 */
p += 5;
ito04x(p, SYSCLK.ltime);
/* 3行目の出力データ作成 */
p += 5;
ito04x(p, SYSCLK.mtime);
}
#endif
#if RDQS
/*****************************************************************************
* レディキュー状態モニタ
*
* RDQ? ? = 最高優先度
* iiii 最高優先度の実行待ちタスクIDの並び
* jjjj 次の優先度の実行待ちタスクIDの並び
******************************************************************************/
static void NEAR monrdq(B NEAR *p)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
T_RDQ NEAR *rdq; /* レディキューへのポインタ */
TPRI pri;
INT i, j;
/* 1行目の出力データ作成 */
pri = 1;
rdq = &RDQ[1];
while (rdq->qcnt == 0)
{ pri++;
rdq++;
}
ito1id(p+3, pri);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, ".... ....", 9);
/* 2行目の出力データ作成 */
j = rdq->qcnt;
tcb = rdq->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
/* 3行目の出力データ作成 */
if (pri < tpri_max)
{
p += 5;
rdq++;
while (rdq->qcnt == 0)
{ rdq++;
}
j = rdq->qcnt;
tcb = rdq->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
}
}
#endif
#if TSKS
/*****************************************************************************
* タスク状態モニタ
*
* TSK? ? = タスクID
* sssp sss = タスク状態, p = 優先度(run, rdy 時)
* xxxx 起床要求カウント等
******************************************************************************/
static void NEAR montsk(B NEAR *p, ID id)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
INT c;
/* 1行目の出力データ作成 */
ito1id(p+3, id);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, "rdy ....", 9);
/* タスク未生成の場合 */
tcb = pTCB[id];
if (id > tskid_max || tcb->tid == 0)
{ p[0] = 'n'; p[1] = 'o'; p[2] = 'n';
return;
}
/* 2,3行目の出力データ作成(SUSPENDの場合) */
if ((c = tcb->suscnt) != 0)
{
switch (tcb->sts)
{
case S_DMT:
p[0] = 'd'; p[1] = 'm'; p[2] = 't';
break;
case S_RDY:
p[0] = 's'; p[1] = 'u'; p[2] = 's';
ito04x(p+5, c); /* 強制待ち要求カウント */
break;
default:
p[0] = 'w'; p[1] = 'a'; p[2] = 's';
ito04x(p+5, c); /* 強制待ち要求カウント */
break;
}
}
/* 2,3行目の出力データ作成(SUSPENDでない場合) */
else
{
switch (tcb->sts)
{
case S_DMT:
p[0] = 'd'; p[1] = 'm'; p[2] = 't';
break;
case S_SLP:
p[0] = 's'; p[1] = 'l'; p[2] = 'p';
break;
case S_WAI:
p[0] = 'w'; p[1] = 'a'; p[2] = 'i';
break;
case S_MPL:
p[0] = 'm'; p[1] = 'p'; p[2] = 'l';
break;
case S_SEM:
p[0] = 's'; p[1] = 'e'; p[2] = 'm';
break;
case S_MBX:
p[0] = 'm'; p[1] = 'b'; p[2] = 'x';
break;
case S_RDY:
if (tcb == RDQ[0].head)
{ p[1] = 'u'; p[2] = 'n';
}
ito1id(p+3, tcb->pri); /* 優先度 */
if ((c = tcb->wupcnt) != 0)
ito04x(p+5, c); /* 起床要求カウント */
break;
default:
p[0] = 'f'; p[1] = 'l'; p[2] = 'g';
ito04x(p+5, tcb->waiptn); /* 待ちパターン */
break;
}
}
}
#endif
#if FLGS
/*****************************************************************************
* イベントフラグ状態モニタ
*
* FLG? ? = イベントフラグID
* xxxx イベントフラグパターン
* iiii イベントフラグ待ちタスクIDの並び
******************************************************************************/
static void NEAR monflg(B NEAR *p, ID id)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
T_FLG NEAR *flg; /* イベントフラグへのポインタ */
INT i, j, c;
/* 1行目の出力データ作成 */
ito1id(p+3, id);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, ".... ....", 9);
/* 2行目の出力データ作成 */
if (id > flgid_max)
{ memcpy(p, "non ", 4);
return;
}
flg = &FLG[id];
if ((c = (INT)flg->ptn) != 0)
ito04x(p, c); /* イベントフラグ値 */
/* 3行目の出力データ作成 */
p += 5;
if ((j = flg->qcnt) != 0)
{ tcb = flg->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
}
}
#endif
#if SEMS
/*****************************************************************************
* セマフォ状態モニタ
*
* SEM? ? = セマフォID
* xxxx セマフォカウント値
* iiii セマフォ待ちタスクIDの並び
******************************************************************************/
static void NEAR monsem(B NEAR *p, ID id)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
T_SEM NEAR *sem; /* セマフォへのポインタ */
INT i, j, c;
/* 1行目の出力データ作成 */
ito1id(p+3, id);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, ".... ....", 9);
/* 2行目の出力データ作成 */
if (id > semid_max)
{ memcpy(p, "non ", 4);
return;
}
sem = &SEM[id];
if ((c = sem->cnt) != 0)
ito04x(p, c); /* セマフォカウント値 */
/* 3行目の出力データ作成 */
p += 5;
if ((j = sem->qcnt) != 0)
{ tcb = sem->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
}
}
#endif
#if MBXS
/*****************************************************************************
* メールボックス状態モニタ
*
* MBX? ? = メールボックスID
* xxxx メッセージの並び(先頭ニブルのみ)
* iiii メッセージ待ちタスクIDの並び
******************************************************************************/
static void NEAR monmbx(B NEAR *p, ID id)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
T_MBX NEAR *mbx; /* メールボックスへのポインタ */
T_MSG FAR *msg; /* メッセージへのポインタ */
INT i, j;
/* 1行目の出力データ作成 */
ito1id(p+3, id);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, ".... ....", 9);
/* 2行目の出力データ作成 */
if (id > mbxid_max)
{ memcpy(p, "non ", 4);
return;
}
mbx = &MBX[id];
i = 0;
msg = mbx->top;
while (msg != NULL)
{ ito1x(p+i, msg->msgcont[0]);
if (++i == 4)
break;
msg = msg->next;
}
/* 3行目の出力データ作成 */
p += 5;
if ((j = mbx->qcnt) != 0)
{ tcb = mbx->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
}
}
#endif
#if MPLS
/*****************************************************************************
* メモリプール状態モニタ
*
* MPL? ? = メモリプールID
* xxxx 空きブロック数
* iiii メモリ待ちタスクIDの並び
******************************************************************************/
static void NEAR monmpl(B NEAR *p, ID id)
{
T_TCB NEAR *tcb; /* TCBへのポインタ */
T_MPL NEAR *mpl; /* メモリプールへのポインタ */
INT i, j, c;
/* 1行目の出力データ作成 */
ito1id(p+3, id);
/* 2,3行目の初期化 */
p += 5;
memcpy(p, ".... ....", 9);
/* 2行目の出力データ作成 */
if (id > mplid_max)
{ memcpy(p, "non ", 4);
return;
}
mpl = pMPL[id];
if ((c = mpl->frbcnt) != 0)
ito04x(p, c); /* 空きブロック数 */
/* 3行目の出力データ作成 */
p += 5;
if ((j = mpl->qcnt) != 0)
{ tcb = mpl->head;
for (i = 0; i < 4; i++)
{ ito1id(p+i, tcb->tid);
if (--j == 0)
break;
tcb = tcb->next;
}
}
}
#endif
#ifndef ROM
/*****************************************************************************
* オブジェクトモニタ出力データ編集(FMR,IBM-PC)
*
* モニタ結果を画面へ出力する並びに変換する。
******************************************************************************/
static void NEAR putmon_videobuf(void)
{
INT i;
B NEAR *p1;
B NEAR *p2;
p1 = videobuf;
p2 = monbuf;
for (i = 0; i < 80/5; i++)
{
memcpy(p1, p2, 5);
memcpy(p1+80, p2+5, 5);
memcpy(p1+80*2, p2+10, 5);
p1 += 5;
p2 += 16;
}
}
/*****************************************************************************
* オブジェクトモニタ画面出力(PC9801)
*
******************************************************************************/
static void NEAR putmon_98(void)
{
INT i;
UB NEAR *p;
H FAR *v;
/* 0回目は出力しない */
if (montmr_cnt == 0)
{ montmr_cnt = 1;
return;
}
/* 1回目でモニタ結果出力(VRAM直書き)*/
p = (UB NEAR *)monbuf;
v = (H FAR *)vram;
for (i = 0; i < 80/5; i++)
{
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v = *p++;
v += 80 - 4;
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v = *p++;
v += 80 - 4;
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v++ = *p++;
*v = *p++;
v -= 80 * 2 - 1;
p++;
}
montmr_cnt = 0;
}
/*****************************************************************************
* オブジェクトモニタ画面出力(FMR)
*
* コンソールBIOSの負荷が重いため1行ずつ分けて出力する。
******************************************************************************/
static void NEAR putmon_fmr(void)
{
union REGS regs;
UINT rowcol;
UB cursts, i;
/* 0回目は出力しない */
if ((i = montmr_cnt) == 0)
{ montmr_cnt = 1;
return;
}
/* 1回目は出力データ編集 */
if (i == 1)
{ putmon_videobuf();
montmr_cnt = 2;
return;
}
/* 2〜4回目でモニタ結果出力 */
i -= 2;
/* カーソル状態,位置読み取り */
regs.h.ah = 0x0c;
int86(0x91, ®s, ®s);
cursts = regs.h.al;
regs.h.ah = 0x0e;
int86(0x91, ®s, ®s);
rowcol = regs.x.dx;
/* カーソル消す */
regs.h.ah = 0x0b;
regs.h.al = 1;
int86(0x91, ®s, ®s);
/* カーソル移動 */
regs.h.ah = 0x0d;
regs.h.dh = (UB)(i + 1);
regs.h.dl = 1;
int86(0x91, ®s, ®s);
/* 文字列出力 */
regs.h.ah = 0x1e;
regs.x.cx = 80;
regs.x.di = (UINT)videobuf + i * 80;
int86(0x91, ®s, ®s);
/* カーソル状態,位置復元 */
regs.h.ah = 0x0d;
regs.x.dx = rowcol;
int86(0x91, ®s, ®s);
regs.h.ah = 0x0b;
regs.h.al = cursts;
int86(0x91, ®s, ®s);
if (++montmr_cnt > 4)
montmr_cnt = 0;
}
/*****************************************************************************
* オブジェクトモニタ画面出力(IBM-PC)
*
* ビデオBIOSの負荷が重いため1行ずつ分けて出力する。
******************************************************************************/
/* bpでBIOSに渡すので int86,int86x が使えない */
static UB int10_func13[] =
{ 0x55, /* PUSH BP */
0x8b,0xec, /* MOV BP,SP */
0xb8,0x00,0x13, /* MOV AX,1300H */
0xb7,0x00, /* MOV BH,0 */
0xb3,0x07, /* MOV BL,7 */
0xb9,0x50,0x00, /* MOV CX,80 */
0x8a,0x76,0x06, /* MOV DH,[BP+6] */
0xb2,0x00, /* MOV DL,0 */
0x8b,0x6e,0x08, /* MOV BP,[BP+8] */
0x1e, /* PUSH DS */
0x07, /* POP ES */
0xcd,0x10, /* INT 10H */
0x5d, /* POP BP */
0xcb, /* RETF */
};
typedef int (FAR *FP_HH)(H, H);
static FP_HH int10_func13p = (FP_HH)((W)int10_func13);
static void NEAR putmon_ibm(void)
{
UB i;
/* 0回目は出力しない */
if ((i = montmr_cnt) == 0)
{ montmr_cnt = 1;
return;
}
/* 1回目は出力データ編集 */
if (i == 1)
{ putmon_videobuf();
montmr_cnt = 2;
return;
}
/* 2〜4回目でモニタ結果出力 */
i -= 2;
(*int10_func13p)(i, (H)(videobuf + 80 * (H)i));
if (++montmr_cnt > 4)
montmr_cnt = 0;
}
/*****************************************************************************
* DOSエクステンダ(EXE286)上で実行中か
*
******************************************************************************/
static BOOL isEXE286(void)
{
static BOOL exe286 = -1;
/* 未判定の場合 */
if (exe286 == -1)
{
B FAR *p1 = (B FAR *)0x400000L; /* BIOS ワークエリア */
B FAR *p2 = (B FAR *)0x380400L; /* EXE286 では p1 と同じアドレス */
UH i = 0x200; /* 200H バイトも比較すれば十分 */
do
{ if (*p1++ != *p2++)
return exe286 = FALSE;
} while (--i != 0);
return exe286 = TRUE;
}
/* 判定済みの場合 */
return exe286;
}
/*****************************************************************************
* セグメントディスクリプタを作成する
*
******************************************************************************/
static void FAR *EXE286SegAbsolute(W absaddr, UH size)
{
union REGS regs;
regs.x.ax = 0xfe30;
regs.x.si = (H)(absaddr >> 16);
regs.x.bx = 0;
regs.x.cx = size - 1;
regs.h.dl = 0x92;
intdos(®s, ®s);
return (void FAR *)(((W)regs.x.ax << 16) + (H)absaddr);
}
/*****************************************************************************
* 画面分割(PC9801)
*
* CRT BIOS の「複数の表示領域の設定」機能を用いて、画面の上部複数行に裏テキス
* トVRAM を表示させる。(これは日本語FEPが用いている手法と同じ)
******************************************************************************/
static void NEAR splitvram(int rows) /* rows = 分割行数(0で分割解除)*/
{
H FAR *p;
H buf[4];
union REGS regs;
if ((UH)vram < 0x1000)
return; /* 裏VRAMでなければNOP */
if (isEXE286()) /* EXE286上で実行中の場合 */
{ p = (H FAR *)vram; /* CRT-BIOSパラメータはVRAM上に取る */
buf[0] = p[0]; /* (リアルモードのメモリが欲しいため)*/
buf[1] = p[1]; /* 破壊するVRAM内容を保存 */
buf[2] = p[2];
buf[3] = p[3];
regs.x.bx = (UH)(VRAM_98 >> 16);
}
else
{ p = buf;
regs.x.bx = (H)((W)p >> 16);
}
regs.x.cx = (H)((W)p);
regs.h.ah = 0x0f;
if (rows != 0)
{ p[0] = (H)vram; /* 領域0のVRAMオフセット */
p[1] = (H)rows; /* 領域0の行数 */
p[2] = (H)(rows * 160); /* 領域1のVRAMオフセット */
p[3] = (H)(25 - rows); /* 領域1の行数 */
regs.x.dx = 2;
}
else
{ p[0] = 0; /* 領域0のVRAMオフセット */
p[1] = 25; /* 領域0の行数 */
regs.x.dx = 1;
}
int86(0x18, ®s, ®s);
if (p != buf)
{ p[0] = buf[0]; /* 破壊したVRAM内容を復元 */
p[1] = buf[1];
p[2] = buf[2];
p[3] = buf[3];
}
}
#endif /* !ROM */
/*****************************************************************************
* オブジェクトモニタ終了
*
* montmr 周期起動タイマハンドラを非活性化する。
* monsta 関数で atexit してある。
******************************************************************************/
void cdecl monext(void)
{
#if TIM
act_cyc(0, TCY_OFF);
#endif
#ifndef ROM
if (ispc9801()) /* PC9801の場合 */
splitvram(0); /* 画面分割解除 */
#endif
}
/*****************************************************************************
* オブジェクトモニタ・ハンドラ
*
* 各モニタ処理関数を呼び出して、結果を画面に出力する。
* このハンドラは、インターバル割込内で呼び出される非タスクの処理。
******************************************************************************/
TMRHDR montmr(void)
{
INT i, max;
B NEAR *p;
UINT psw;
psw = vdis_psw(); /* 割込み禁止 */
if (montmr_cnt == 0)
{
p = monbuf;
#if CLKS
monclk(p);
p += 16;
#endif
#if RDQS
monrdq(p);
p += 16;
#endif
#if TSKS
max = mon_tskid + TSKS;
for (i = mon_tskid; i < max; i++)
{ montsk(p, i);
p += 16;
}
#endif
#if FLGS
max = mon_flgid + FLGS;
for (i = mon_flgid; i < max; i++)
{ monflg(p, i);
p += 16;
}
#endif
#if SEMS
max = mon_semid + SEMS;
for (i = mon_semid; i < max; i++)
{ monsem(p, i);
p += 16;
}
#endif
#if MBXS
max = mon_mbxid + MBXS;
for (i = mon_mbxid; i < max; i++)
{ monmbx(p, i);
p += 16;
}
#endif
#if MPLS
max = mon_mplid + MPLS;
for (i = mon_mplid; i < max; i++)
{ monmpl(p, i);
p += 16;
}
#endif
}
/* 画面出力 */
#ifndef ROM
if (ispc9801())
putmon_98();
else if (isfmr())
putmon_fmr();
else if (isibmpc())
putmon_ibm();
#endif
vset_psw(psw); /* 割込み禁止戻す */
ret_tmr();
}
/*****************************************************************************
* オブジェクトモニタ起動
*
* montmr 関数を周期起動タイマハンドラとして定義、活性化する。
* 本関数の2回目以降の呼び出しでは、活性化のみ行う。
* ハンドラ番号には、システム予約の0を用いている。
******************************************************************************/
void cdecl monsta(void)
{
static UB init = 0; /* 初期化済みフラグ */
static T_TIME time = { TIM, 0, 0 }; /* 周期 */
#ifndef ROM
W absadr;
#endif
/* 未初期化の場合 */
if (!init)
{
init_monbuf();
#if TIM
def_cyc(0, montmr, TCY_ON, time);
#endif
init = 1;
#ifndef ROM
judgepc();
atexit(monext);
if (ispc9801() && isEXE286())
{ absadr = ((vram >> 12) & 0xf0000L) + (UH)vram;
vram = (W)EXE286SegAbsolute(absadr, 0);
}
#endif
}
/* 初期化済の場合(2回目以降の呼出)*/
#if TIM
else
act_cyc(0, TCY_ON);
#endif
/* 共通の処理 */
montmr_cnt = 0;
#ifndef ROM
if (ispc9801()) /* PC9801の場合 */
splitvram(3); /* 画面上3行に裏テキスト分割 */
#endif
}
/*****************************************************************************
* モニタする先頭タスクIDを設定
*
******************************************************************************/
BOOL cdecl set_montsk(ID id)
{
if (id < 1 || id > tskid_max)
return FALSE;
#if TSKS
mon_tskid = id;
return TRUE;
#else
return FALSE;
#endif
}
/*****************************************************************************
* モニタする先頭イベントフラグIDを設定
*
******************************************************************************/
BOOL cdecl set_monflg(ID id)
{
if (id < 1 || id > flgid_max)
return FALSE;
#if FLGS
mon_flgid = id;
return TRUE;
#else
return FALSE;
#endif
}
/*****************************************************************************
* モニタする先頭セマフォIDを設定
*
******************************************************************************/
BOOL cdecl set_monsem(ID id)
{
if (id < 1 || id > semid_max)
return FALSE;
#if SEMS
mon_semid = id;
return TRUE;
#else
return FALSE;
#endif
}
/*****************************************************************************
* モニタする先頭メイルボックスIDを設定
*
******************************************************************************/
BOOL cdecl set_monmbx(ID id)
{
if (id < 1 || id > mbxid_max)
return FALSE;
#if MBXS
mon_mbxid = id;
return TRUE;
#else
return FALSE;
#endif
}
/*****************************************************************************
* モニタする先頭メモリプールIDを設定
*
******************************************************************************/
BOOL cdecl set_monmpl(ID id)
{
if (id < 1 || id > mplid_max)
return FALSE;
#if MPLS
mon_mplid = id;
return TRUE;
#else
return FALSE;
#endif
}
/* end */