--- nono/vm/syncer.cpp 2026/04/29 17:05:42 1.1.1.6 +++ nono/vm/syncer.cpp 2026/04/29 17:05:59 1.1.1.9 @@ -10,6 +10,7 @@ #include "syncer.h" #include "config.h" +#include "event.h" #include "monitor.h" #include "mpu680x0.h" #include "scheduler.h" @@ -44,14 +45,15 @@ bool Syncer::Init() { mpu680x0 = dynamic_cast(mpu); + thman = gMainApp.GetThreadManager(); mode = SYNCMODE_POWEROFF; overslept = 0; dmac_idle = 1; // 高速モード指定 - bool fast_mode = gConfig->Find("fast-mode").AsInt(); - RequestFullSpeed(fast_mode); + bool fast_mode = gConfig->Find("fast-mode").AsBool(); + NotifyFullSpeed(fast_mode); // クロックの同期方法 const ConfigItem& sync_item = gConfig->Find("clock-sync"); @@ -68,10 +70,11 @@ Syncer::Init() scheduler->ConnectMessage(MessageID::SCHEDULER_SYNCMODE, this, ToMessageCallback(&Syncer::ChangeModeMessage)); - sync_event.func = ToEventCallback(&Syncer::SyncCallback); - sync_event.time = 50_msec; - sync_event.SetName("Sync"); - scheduler->RegistEvent(sync_event); + auto evman = GetEventManager(); + sync_event = evman->Regist(this, + ToEventCallback(&Syncer::SyncCallback), + "Sync"); + sync_event->time = 50_msec; return true; } @@ -99,13 +102,14 @@ Syncer::StartTime() // Restart() は経過時間をリセットしてからタイマーを開始の意。 realtime.Restart(); - rtime = realtime.Elapsed(); + rtime = nsec_to_tsec(realtime.Elapsed_nsec()); rtime_epoch = rtime; vtime_epoch = scheduler->GetVirtTime(); // パフォーマンス表示用。 // 最初の集計が行われる起動後1秒までは、この値が表示されるので // インチキして 100% にしておく。 + clock_khz = mpu->GetClockSpeed(); perf_counter = 100; last_perf_rtime = rtime_epoch; last_perf_vtime = vtime_epoch; @@ -115,7 +119,7 @@ Syncer::StartTime() // CPU 状態変更(通常/STOP/HALT)を指示する。 // CPU が呼ぶはずなので自スレッドからのみ呼ばれるはず。 void -Syncer::RequestCPUMode(uint32 cpumode) +Syncer::NotifyCPUMode(uint32 cpumode) { uint32 newmode; @@ -129,7 +133,7 @@ Syncer::RequestCPUMode(uint32 cpumode) // DMAC のアクティブ状態を指示する。 void -Syncer::RequestDMACActive(bool active) +Syncer::NotifyDMACActive(bool active) { uint32 newmode; @@ -144,52 +148,51 @@ Syncer::RequestDMACActive(bool active) // true なら高速モード、false なら同期モード。 // 他スレッドから呼んでもよい。 void -Syncer::RequestFullSpeed(bool enable) +Syncer::NotifyFullSpeed(bool enable) { scheduler->SendMessage(MessageID::SCHEDULER_SYNCMODE, enable); } -// ブートページモードの変更を指示する。 -// (MainbusBaseDevice::SwitchBootPage から呼ぶので個別には呼ばないこと) +// キー入力状態の変更を指示する。 void -Syncer::RequestBootPageMode(bool isrom) +Syncer::NotifyKeyPressed(bool pressed) { uint32 newmode; - if (isrom) { - newmode = mode | SYNCMODE_BOOT; + if (pressed) { + newmode = mode | SYNCMODE_KEY; } else { - newmode = mode & ~SYNCMODE_BOOT; + newmode = mode & ~SYNCMODE_KEY; } ChangeMode(newmode); } -// キー入力状態の変更を指示する。 +// 電源状態の変更を指示する。 void -Syncer::RequestKeyPressed(bool pressed) +Syncer::NotifyPowerOffMode(bool poweroff) { uint32 newmode; - if (pressed) { - newmode = mode | SYNCMODE_KEY; + if (poweroff) { + newmode = mode | SYNCMODE_POWEROFF; } else { - newmode = mode & ~SYNCMODE_KEY; + newmode = mode & ~SYNCMODE_POWEROFF; } ChangeMode(newmode); } -// 電源状態の変更を指示する。 +// サウンド出力状態の変更を指示する。 void -Syncer::RequestPowerOffMode(bool poweroff) +Syncer::NotifySoundRunning(bool running) { uint32 newmode; - if (poweroff) { - newmode = mode | SYNCMODE_POWEROFF; + if (running) { + newmode = mode | SYNCMODE_SOUND; } else { - newmode = mode & ~SYNCMODE_POWEROFF; + newmode = mode & ~SYNCMODE_SOUND; } ChangeMode(newmode); @@ -258,7 +261,7 @@ Syncer::ChangeMode(uint32 newmode) // 同期イベント void -Syncer::SyncCallback(Event& ev) +Syncer::SyncCallback(Event *ev) { DPRINTF("SyncCallback\n"); DoSync(); @@ -269,12 +272,11 @@ Syncer::SyncCallback(Event& ev) // 同期処理 // ここで仮想時間を実時間と同期させる。 -// スリープしすぎた実時間を返す。 void Syncer::DoSync() { // 実時間をここで更新 - rtime = realtime.Elapsed(); + rtime = nsec_to_tsec(realtime.Elapsed_nsec()); DPRINTF("Sync begin rtime=%s\n", SecToStr(rtime).c_str()); // 統計情報 @@ -285,7 +287,7 @@ Syncer::DoSync() } // XXX 次回 Start する時のイベント間隔をここ(DoSync())で事前に決めている - sync_event.time = 50_msec; + sync_event->time = 50_msec; // 同期モードなら.. if (mode != 0) { @@ -302,7 +304,7 @@ Syncer::DoSync() // スリープしすぎた時間を計測。 // この時間にはスリープ時間を計算するための時間も含む。 - rtime = realtime.Elapsed(); + rtime = nsec_to_tsec(realtime.Elapsed_nsec()); DPRINTF("Sync wakeup rtime=%s\n", SecToStr(rtime).c_str()); uint64 realslept = rtime - prev; if (realslept > diff) { @@ -318,7 +320,7 @@ Syncer::DoSync() } else if (realslept < diff) { uint64 under = diff - realslept; if (under > overslept) { - sync_event.time = 0; + sync_event->time = 0; } } } else if (rspan > vspan + overslept) { @@ -343,14 +345,7 @@ Syncer::CalcPerf() // 百分率で小数以下1桁分までとなるよう整数で計算する perfq.EnqueueForce((uint32)(vperf * 1000 / rperf)); // 移動平均を求める (perfq は常に要素数分埋めてある) - uint ma = 0; - uint qlen = perfq.Length(); - __assume(qlen != 0); - for (int i = 0; i < qlen; i++) { - auto v = perfq.Peek(i); - ma += v; - } - ma /= qlen; + uint ma = perfq.GetMovingAverage(); // 最下位を四捨五入して捨てる (整数%になる) ma = (ma + 5) / 10; perf_counter = ma; @@ -364,6 +359,13 @@ Syncer::CalcPerf() mpu680x0->CalcStat(); } + uint64 mpu_exec = mpu->GetExecCount(); + last_mpu_exec_per_sec = mpu_exec - last_mpu_exec; + last_mpu_exec = mpu_exec; + + // ついでにここで各スレッドの CPU 利用率も調べる。 + thman->CalcPerf(rtime); + last_perf_rtime = rtime; last_perf_vtime = vtime; next_perf_rtime = rtime + PERF_INTERVAL; @@ -376,9 +378,8 @@ Syncer::PutlogRealtime() uint64 vtime = scheduler->GetVirtTime(); // 電源オン時からここまでの時間を表示するだけでリセット等はしない。 - putlog(0, "Elapsed since power-on: %u.%03u sec, %6.2f%%", - (uint)(rtime / (1000 * 1000 * 1000)), - (uint)((rtime / (1000 * 1000)) % 1000), + putlog(0, "Elapsed since power-on: %.3f sec, %6.2f%%", + (double)rtime / 1_sec, (double)vtime / rtime * 100); #if 0 @@ -387,13 +388,14 @@ Syncer::PutlogRealtime() for (const auto e : events) { sum += e->count; } - putlog(0, "%lu events done, %6.3fM/sec", sum, (double)sum / rtime * 1000); + putlog(0, "%lu events done, %6.3fM/sec", sum, + (double)sum / rtime * 1_usec); #endif } // モニタ更新の下請け (Scheduler から呼ばれる) int -Syncer::MonitorUpdateSub(TextScreen& screen, uint64 tmp_vtime) +Syncer::MonitorScreenSub(TextScreen& screen, uint64 tmp_vtime) { int y = 0; @@ -420,10 +422,10 @@ Syncer::MonitorUpdateSub(TextScreen& scr } else { screen.Puts(19, y, TA::Off, "Full"); } - screen.Puts(24, y, TA::OnOff((tmp_mode & SYNCMODE_BOOT)), "Boot"); - screen.Puts(29, y, TA::OnOff((tmp_mode & SYNCMODE_KEY)), "Key"); - screen.Puts(34, y, TA::OnOff((tmp_mode & SYNCMODE_POWEROFF)), "POff"); - screen.Puts(38, y, ")"); + screen.Puts(24, y, TA::OnOff((tmp_mode & SYNCMODE_KEY)), "Key"); + screen.Puts(29, y, TA::OnOff((tmp_mode & SYNCMODE_POWEROFF)), "POff"); + screen.Puts(34, y, TA::OnOff((tmp_mode & SYNCMODE_SOUND)), "Sound"); + screen.Puts(39, y, ")"); y++; // 日まで表示しようとするときは桁位置を動かす @@ -445,7 +447,6 @@ Syncer::MonitorUpdateSub(TextScreen& scr y += 2; screen.Puts(0, y, "Rating MPU Speed :"); - uint clock_khz = mpu->GetClockSpeed(); if (__predict_true((clock_khz % 1000) == 0)) { screen.Print(21, y++, "%4u.%1uMHz", clock_khz / 1000, (clock_khz / 100) % 10); @@ -461,6 +462,8 @@ Syncer::MonitorUpdateSub(TextScreen& scr int y1 = 0; screen.Print(x, y1++, "Max OverSlept: %13s", SecToStr(overslept).c_str()); screen.Print(x, y1++, "Sync per sec : %4u", last_sync_count); + std::string mpu_str = format_number(last_mpu_exec_per_sec); + screen.Print(x, y1++, "MPU Exec/sec : %13s", mpu_str.c_str()); return y; }