--- nono/vm/scheduler.h 2026/04/29 17:04:42 1.1.1.5 +++ nono/vm/scheduler.h 2026/04/29 17:04:50 1.1.1.7 @@ -20,36 +20,51 @@ class Scheduler : public Device { using inherited = Device; + public: + // 動作モード + // 動作モード変数 (mode) はスケジューラの走行状態を表している。以下の + // ビットがすべて %0 なら高速モード、どれかでも %1 なら通常モードになる。 + // + // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // mode | |SYNC| CPUSTAT | + // | +---+---- CPU の状態 + // +-------------- 高速モード抑制 + // + // bit1,0 (CPUSTAT) は CPU の状態を示す。%00 の時だけ高速走行が可能。 + // これは MPUDevice::Run() の戻り値でもある。 + // b1 b0 + // 0 0 通常状態 + // 0 1 STOP 状態 (m88k なら擬似 STOP 状態) + // 1 0 HALT 状態 (ダブルバスフォールト) + // 1 1 HALT 状態だがこちらのビットパターンは使わない + // + // bit2 (SYNC) が UI からの高速モード指示。%0 なら高速、%1 なら通常。 + // なのでどっちかというと高速モード抑制指示というほうがいいかも。 + + static const uint32 SCHED_CPU_STOP = 0x0001; // CPU が STOP 状態 + static const uint32 SCHED_CPU_HALT = 0x0002; // CPU が HALT 状態 + static const uint32 SCHED_SYNC = 0x0004; // 高速モード抑制指示(UI) + + // 便宜上用意しておく + static const uint32 SCHED_CPU_NORMAL= 0x0000; // CPU が通常状態 + static const uint32 SCHED_CPU_MASK = (SCHED_CPU_STOP | SCHED_CPU_HALT); + + private: // リクエストフラグ - static const uint REQ_SYNC = 0x0001; // スケジューラを同期モードに - static const uint REQ_FAST = 0x0002; // スケジューラを高速モードに - static const uint REQ_RUN = 0x0004; // MPU が通常状態になった - static const uint REQ_STOP = 0x0008; // MPU が STOP 状態になった - static const uint REQ_MODEMASK = 0x000f; // mode マスク + // REQ_CPU_MODE は CPU mode が何らか変化することのフラグ。どの状態に変化 + // するかは new_cpumode 変数で示す。1回のループ期間中に複数回の変化が + // 起きても最終状態だけに変化するため。 + // REQ_USER_MODE と new_usermode も同様。 + static const uint REQ_CPU_MODE = 0x0001; // CPU 状態を変更 + static const uint REQ_USER_MODE = 0x0002; // 同期/高速モード変更 static const uint REQ_POWER_ON = 0x0010; // 電源オン static const uint REQ_POWER_OFF = 0x0020; // 電源オフ static const uint REQ_EXIT = 0x0040; // アプリケーション終了 static const uint REQ_RESET = 0x0080; // ハードウェアリセット - // 動作モード - // 動作モード変数 (mode) は高速モードか通常モードかと、MPU が通常状態が - // STOP 状態かを同時に保持している。高速走行中であっても MPU が STOP 状態 - // なら通常走行するというロジックを比較1回で済ませるため。 - static const uint32 SCHED_STOP = 0x0001; // スケジューラが STOP 状態 - static const uint32 SCHED_SYNC = 0x0002; // 同期(%1)/高速(%0)モード - - // 演算を1回で済ませるために、この2値は同じ値にすること。 - // ただしこれをチェックするために全員が m68030.h/m88100.h を include すると - // m88k を修正するたびに m68k も含めて全部ビルドが走るのはかなりつらいので - // 定義されてる時だけチェックすることにする。 - // もともと将来のポカよけなのでビルド中1回でも通過すれば十分。 -#if defined(CPU_REQ_STOP) - static_assert(SCHED_STOP == CPU_REQ_STOP, "must be the same"); -#endif - public: Scheduler(); - ~Scheduler() override; + virtual ~Scheduler() override; bool Init() override; @@ -75,20 +90,6 @@ class Scheduler : public Device atomic_reqflag |= REQ_RESET; } - // サイクル数を仮想時間 [nsec] に変換 - uint64 Cycle2Vtime(uint64 cycle) const { - return cycle * 1000 * 1000 / mpu_clock; - } - - // 仮想時間 [nsec] をサイクル数に変換 - uint64 Vtime2Cycle(uint64 vtime) const { - return vtime * mpu_clock / (1000 * 1000); - } - - // 仮想時刻取得 - uint64 GetVirtTime() const { - return Cycle2Vtime(gMPU->total_cycle()); - } // スケジューラが高速モードなら true を返す。 // ここでいう高速モードは STOP 状態中でも高速モード。 @@ -118,13 +119,20 @@ class Scheduler : public Device // リセットイベントコールバック void ResetCallback(Event& ev); + // スレッド終了を指示する + void RequestExit(); + pthread_t thread {}; bool thread_created {}; // スレッドが作成されたら true // スケジューラの動作モード。SCHED_* uint32 mode {}; - int mpu_clock {}; // MPU クロック [kHz] + // REQ_CPU_MODE フラグで変更するモード + uint32 new_cpumode {}; + + // REQ_USER_MODE フラグで変更するモード + uint32 new_usermode {}; uint64 rtimestart {}; // スケジューラ開始実時刻 uint64 rtimebase {}; // 実時間の基準時刻