--- nono/vm/goldfish_tty.cpp 2026/04/29 17:05:29 1.1.1.2 +++ nono/vm/goldfish_tty.cpp 2026/04/29 17:05:42 1.1.1.4 @@ -42,6 +42,7 @@ #include "mainbus.h" #include "mpu.h" #include "scheduler.h" +#include "syncer.h" // コンストラクタ GFTTYDevice::GFTTYDevice() @@ -61,8 +62,11 @@ bool GFTTYDevice::Create() { // 対応するホストドライバを作成 - hostcom.reset(new HostCOMDevice(this, "HostCOM")); + try { + hostcom.reset(new HostCOMDevice(this, "HostCOM")); + } catch (...) { } if ((bool)hostcom == false) { + warnx("Failed to initialize HostCOMDevice at %s", __method__); return false; } hostcom->SetRxCallback(ToDeviceCallback(&GFTTYDevice::HostRxCallback)); @@ -75,18 +79,15 @@ GFTTYDevice::SetLogLevel(int loglevel_) { inherited::SetLogLevel(loglevel_); - assert((bool)hostcom); - hostcom->SetLogLevel(loglevel_); + if ((bool)hostcom) { + hostcom->SetLogLevel(loglevel_); + } } // 初期化 bool GFTTYDevice::Init() { - if (inherited::Init() == false) { - return false; - } - mainbus = GetMainbusDevice(); gfpic = GetGFPICDevice(1); @@ -101,6 +102,7 @@ GFTTYDevice::Init() void GFTTYDevice::ResetHard(bool poweron) { + sesame_idx = 0; rxq.clear(); intr_enable = false; ChangeInterrupt(); @@ -140,7 +142,7 @@ GFTTYDevice::WritePort(uint32 offset, ui switch (offset) { case PUT_CHAR: putlog(2, "PUT_CHAR <- $%02x", data); - hostcom->Tx(data); + Tx(data); break; case COMMAND: @@ -215,7 +217,7 @@ GFTTYDevice::Command(uint32 cmd) putlog(1, "WRITE_BUFFER: BusError at $%08x", addr); break; } - hostcom->Tx(data); + Tx(data); } break; } @@ -245,6 +247,40 @@ GFTTYDevice::Command(uint32 cmd) } } +// 1バイト送信。 +void +GFTTYDevice::Tx(uint32 data) +{ + // パフォーマンス測定用のギミック。 + // GFTTY に特定の文字列を書き込むと、 + // VM 電源オン時から現在までの実時間をログに出力する。NetBSD の + // マルチユーザブートがあらかた終わってログインプロンプトが出る手前の + // /etc/rc.local に + // + // printf '\e[?68008h\e[?68008l' + // + // と書いておくことで、ここまでにかかる時間を表示できる。 + // この値はホスト性能に依存するため、同一環境下での相対比較のみ可能。 + // + // このエスケープシーケンスは DEC/xterm 拡張の設定と解除を続けて行う + // もので、68008 は空いてそうな適当な値。知らない番号の拡張機能については + // おそらく黙って何もしないだけだと思うので、どの端末エミュレータを通過 + // しても副作用は少ないと思われる。 + static const char sesame[] = "\x1b[?68008h\x1b[?68008l"; + if (__predict_false(data == sesame[sesame_idx])) { + sesame_idx++; + if (__predict_false(sesame_idx >= strlen(sesame))) { + GetSyncer()->PutlogRealtime(); + sesame_idx = 0; + } + } else { + sesame_idx = 0; + } + + // 1バイト送信。 + hostcom->Tx(data); +} + void GFTTYDevice::ChangeInterrupt() {