Added service function. (A service function dumping information for debugging, Added service function for screen drawing ON / OFF control) Specifically, see README. Make the object's destructor called from bios_exit () Add appropriate Destroy function to each object. Delete objects properly We have checked the termination process as a whole, as done. Fix to accept interrupts even during key_wait (). (Previously, only key input was accepted) Some timer interrupts are improved. (UNIXTimer.c) Change the wonx_include directory to wonx. Changed to search the full path to perl automatically and insert it at the beginning of perl script. Makefile review, improvement. Changed ON / OFF of screen drawing to switch according to display level. (See README for details.) Also change to display level lowered by F9 and display level raised by F10. In accordance with that, we have reviewed a part of ON / OFF part of drawing and key input event processing. Fixed to display message when pressing key. Obj ObjListData_GetPrev (ObjListData data) Obj ObjListData_GetNext (ObjListData data) To ObjListData ObjListData_GetPrev (ObjListData data) ObjListData ObjListData_GetNext (ObjListData data) Fixed to. Added install, uninstall target to Makefile. Fixed challsrc.sh. Version 2.2 - from wonx-2.2.tar.gz
322 lines
10 KiB
C
322 lines
10 KiB
C
/*****************************************************************************/
|
||
/* ここから */
|
||
/*****************************************************************************/
|
||
|
||
#include <unistd.h>
|
||
#include <signal.h>
|
||
|
||
#include "UNIXTimerP.h"
|
||
#include "WonX.h"
|
||
|
||
/*****************************************************************************/
|
||
/* メンバ関数の定義 */
|
||
/*****************************************************************************/
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* コールバック関数 */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
/* pointed_unix_timer の値はいつ変化するかわからないので,最適化を禁止する */
|
||
|
||
volatile static UNIXTimer pointed_unix_timer = NULL;
|
||
|
||
static void UNIXTimer_CallBackFunction(int argument)
|
||
{
|
||
int ret;
|
||
int old;
|
||
|
||
/*
|
||
* static なフラグを立てて,コールバック関数からコールバック関数が
|
||
* 呼ばれたのを検出するのが必要かも.
|
||
*/
|
||
|
||
if (pointed_unix_timer == NULL) return;
|
||
if (!pointed_unix_timer->timer_on) return;
|
||
|
||
if (pointed_unix_timer->pause) {
|
||
pointed_unix_timer->interrupt_in_pause++;
|
||
if (pointed_unix_timer->interrupt_in_pause > 1000) {
|
||
WonX_Error("UNIXTimer_CallBackFunction", "interrupt count is too much.");
|
||
}
|
||
} else {
|
||
if (pointed_unix_timer->interrupt_in_pause == 0)
|
||
pointed_unix_timer->interrupt_in_pause = 1;
|
||
while (pointed_unix_timer->interrupt_in_pause > 0) {
|
||
pointed_unix_timer->interrupt_in_pause--;
|
||
if (pointed_unix_timer->callback != NULL) {
|
||
|
||
/*
|
||
* コールバック関数の中から UNIXTimer_Unpause() などが呼ばれて,
|
||
* そこからさらにコールバック関数が呼ばれたりしたときのために,
|
||
* ポーズする.またこのとき,interrupt_in_pause がインクリメント
|
||
* されると無限ループに陥ってしまう可能性がある(?)ので,
|
||
* interrupt_in_pause を保存してコールバック関数の実行後に元に戻す.
|
||
*/
|
||
pointed_unix_timer->pause++;
|
||
old = pointed_unix_timer->interrupt_in_pause;
|
||
ret = (*pointed_unix_timer->callback)(pointed_unix_timer->parameter);
|
||
pointed_unix_timer->pause--;
|
||
pointed_unix_timer->interrupt_in_pause = old;
|
||
|
||
/*
|
||
* コールバック関数の中で UNIXTimer_* 関連の関数が呼び出されると,
|
||
* ここで UNIXTimer オブジェクトの状態が変わってしまう可能性がある.
|
||
*/
|
||
|
||
/*
|
||
* 以下の処理は同じことを関数の先頭でやっているので,
|
||
* 最適化されて削除されないように注意すること.
|
||
*/
|
||
if (pointed_unix_timer == NULL) return;
|
||
if (!pointed_unix_timer->timer_on) return;
|
||
|
||
if (ret) {
|
||
pointed_unix_timer->interrupt_in_pause = 0;
|
||
UNIXTimer_OFF(pointed_unix_timer);
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* コールバック関数中で,ポーズの状態が切り替わってしまった
|
||
* ときのため.
|
||
* 以下の処理は同じようなことをちょっと前にやっているので,
|
||
* 最適化されて削除されないように注意すること.
|
||
*/
|
||
if (pointed_unix_timer->pause) break;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pointed_unix_timer->auto_preset)
|
||
UNIXTimer_ON(pointed_unix_timer);
|
||
else
|
||
UNIXTimer_OFF(pointed_unix_timer);
|
||
|
||
return;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* タイマの ON, OFF */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
/*
|
||
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
|
||
* 常に注意すること.でないと不可解なバグの原因になる.
|
||
*/
|
||
|
||
int UNIXTimer_ON(UNIXTimer unix_timer)
|
||
{
|
||
int t;
|
||
|
||
unix_timer->timer_on = 1;
|
||
pointed_unix_timer = unix_timer;
|
||
|
||
/*
|
||
* SIGALRM を使用するので,sleep() 中にアラームが起きた場合には,
|
||
* コールバック関数からの復帰後に sleep() の残り時間は継続されない.
|
||
*/
|
||
signal(SIGALRM, UNIXTimer_CallBackFunction);
|
||
|
||
#if 0 /* use ualarm() */
|
||
/* ualarm(); の引数に0を用いてはダメなので */
|
||
t = unix_timer->interval * 1000;
|
||
if (t < 1) t = 1;
|
||
ualarm(t, 0);
|
||
#else /* use alarm() */
|
||
/* alarm(); の引数に0を用いてはダメなので */
|
||
t = unix_timer->interval / 1000;
|
||
if (t < 1) t = 1;
|
||
alarm(t);
|
||
#endif
|
||
|
||
return (0);
|
||
}
|
||
|
||
int UNIXTimer_OFF(UNIXTimer unix_timer)
|
||
{
|
||
alarm(0); /* タイマを無効にする */
|
||
unix_timer->timer_on = 0;
|
||
pointed_unix_timer = NULL;
|
||
return (0);
|
||
}
|
||
|
||
int UNIXTimer_IsON(UNIXTimer unix_timer)
|
||
{ return (unix_timer->timer_on != 0); }
|
||
int UNIXTimer_IsOFF(UNIXTimer unix_timer)
|
||
{ return (unix_timer->timer_on == 0); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* 一時停止 */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
/*
|
||
* 関数の先頭と末尾を Pause, Unpause でくくるばあいなどは,
|
||
* 関数から関数を呼び出したときに,2重 Pause, Unpause が起きるので
|
||
* 注意すること.(ただし,ポーズはネストできる)
|
||
*/
|
||
|
||
/*
|
||
* ポーズはネストされるので,UNIXTimer_Unpause() を安易に繰り返し呼んだり
|
||
* しないように注意すること.
|
||
*/
|
||
|
||
/*
|
||
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
|
||
* 常に注意すること.でないと不可解なバグの原因になる.
|
||
*/
|
||
|
||
int UNIXTimer_Pause(UNIXTimer unix_timer)
|
||
{
|
||
unix_timer->pause++; /* ポーズはネストできる */
|
||
|
||
return (0);
|
||
}
|
||
|
||
int UNIXTimer_Unpause(UNIXTimer unix_timer)
|
||
{
|
||
if (unix_timer->pause == 0)
|
||
WonX_Error("UNIXTimer_Unpause", "Duplicated unpause.");
|
||
if (unix_timer->pause < 0)
|
||
WonX_Error("UNIXTimer_Unpause", "Invalid pause.");
|
||
|
||
if (unix_timer->pause == 1) {
|
||
if (unix_timer->interrupt_in_pause > 0) {
|
||
|
||
/*
|
||
* 万が一,ここでタイマ割り込みが発生しても,
|
||
* unix_timer->pause は 1 なので,コールバック関数は呼ばれないので,
|
||
* 問題無し.
|
||
* オートプリセットならば,べつに問題無し.
|
||
* オートプリセットでなければ timer_on フラグが落ちるので,問題無い.
|
||
*/
|
||
|
||
/*
|
||
* 処理中にタイマ割り込みが発生すると面倒なので,
|
||
* タイマをいったん無効にする.
|
||
*/
|
||
alarm(0);
|
||
|
||
/*
|
||
* 状態値を変更する直前・直後で割り込みが入ると面倒なので,
|
||
* 割り込みをOFFにしてからデクリメントする.
|
||
*/
|
||
/* コールバック関数を呼ぶ前に,pause フラグを無効にする */
|
||
unix_timer->pause--; /* ポーズはネストできる */
|
||
|
||
/* コールバック関数の呼び出し */
|
||
UNIXTimer_CallBackFunction(0);
|
||
} else {
|
||
if (unix_timer->interrupt_in_pause < 0)
|
||
WonX_Error("UNIXTimer_Unpause", "Invalid interrupt_in_pause.");
|
||
unix_timer->pause--; /* ポーズはネストできる */
|
||
}
|
||
} else {
|
||
unix_timer->pause--; /* ポーズはネストできる */
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
int UNIXTimer_IsPause(UNIXTimer unix_timer)
|
||
{ return (unix_timer->pause != 0); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* オートプリセット */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
int UNIXTimer_SetAutoPreset(UNIXTimer unix_timer)
|
||
{ return (unix_timer->auto_preset = 1); }
|
||
int UNIXTimer_ResetAutoPreset(UNIXTimer unix_timer)
|
||
{ return (unix_timer->auto_preset = 0); }
|
||
int UNIXTimer_IsAutoPreset(UNIXTimer unix_timer)
|
||
{ return (unix_timer->auto_preset != 0); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* インターバル */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
int UNIXTimer_GetInterval(UNIXTimer unix_timer)
|
||
{ return (unix_timer->interval); }
|
||
int UNIXTimer_SetInterval(UNIXTimer unix_timer, int interval)
|
||
{ return (unix_timer->interval = interval); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* コールバック関数の呼び出し時のパラメータ */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
void * UNIXTimer_GetParameter(UNIXTimer unix_timer)
|
||
{ return (unix_timer->parameter); }
|
||
void * UNIXTimer_SetParameter(UNIXTimer unix_timer, void * parameter)
|
||
{ return (unix_timer->parameter = parameter); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* コールバック関数の取得・登録 */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
UNIXTimerCallBack UNIXTimer_GetCallBack(UNIXTimer unix_timer)
|
||
{ return (unix_timer->callback); }
|
||
UNIXTimerCallBack UNIXTimer_SetCallBack(UNIXTimer unix_timer,
|
||
UNIXTimerCallBack callback)
|
||
{ return (unix_timer->callback = callback); }
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* オブジェクトの作成 */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
UNIXTimer UNIXTimer_Create(int auto_preset, int interval, void * parameter,
|
||
UNIXTimerCallBack callback)
|
||
{
|
||
UNIXTimer unix_timer;
|
||
|
||
unix_timer = (UNIXTimer)malloc(sizeof(_UNIXTimer));
|
||
if (unix_timer == NULL)
|
||
WonX_Error("UNIXTimer_Create", "Cannot allocate memory.");
|
||
|
||
unix_timer->timer_on = 0;
|
||
unix_timer->pause = 0;
|
||
unix_timer->interrupt_in_pause = 0;
|
||
unix_timer->auto_preset = 0;
|
||
unix_timer->interval = 0;
|
||
unix_timer->parameter = NULL;
|
||
unix_timer->callback = NULL;
|
||
|
||
if (auto_preset) UNIXTimer_SetAutoPreset(unix_timer);
|
||
else UNIXTimer_ResetAutoPreset(unix_timer);
|
||
|
||
UNIXTimer_SetInterval(unix_timer, interval);
|
||
UNIXTimer_SetParameter(unix_timer, parameter);
|
||
UNIXTimer_SetCallBack(unix_timer, callback);
|
||
|
||
return (unix_timer);
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*/
|
||
/* オブジェクトの削除 */
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
/*
|
||
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
|
||
* 常に注意すること.でないと不可解なバグの原因になる.
|
||
*/
|
||
|
||
UNIXTimer UNIXTimer_Destroy(UNIXTimer unix_timer)
|
||
{
|
||
if (unix_timer == NULL)
|
||
WonX_Error("UNIXTimer_Destroy", "Object is not created.");
|
||
|
||
UNIXTimer_OFF(unix_timer);
|
||
|
||
free(unix_timer);
|
||
|
||
return (NULL);
|
||
}
|
||
|
||
/*****************************************************************************/
|
||
/* ここまで */
|
||
/*****************************************************************************/
|
||
|
||
/*****************************************************************************/
|
||
/* End of File. */
|
||
/*****************************************************************************/
|