Annotation of nono/vm/vm.cpp, revision 1.1.1.14

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.8   root        7: //
                      8: // VM (基本クラス)
                      9: //
                     10: 
1.1       root       11: #include "vm.h"
1.1.1.9   root       12: #include "debugger.h"
1.1.1.3   root       13: #include "mainapp.h"
1.1.1.9   root       14: #include "mainbus.h"
1.1       root       15: #include "scheduler.h"
1.1.1.8   root       16: #include "signalthread.h"
1.1.1.9   root       17: #include "syncer.h"
1.1       root       18: 
                     19: // コンストラクタ
1.1.1.11  root       20: VM::VM(const char *vmname_)
1.1       root       21: {
1.1.1.11  root       22:        vmname = vmname_;
                     23:        assert(vmname);
                     24: 
1.1.1.8   root       25:        // SignalThread は他のスレッドより先に起動する必要があるので、先頭。
                     26:        // Scheduler は以降の他のデバイスからのイベント登録を受け付ける必要が
                     27:        // あるためその次。
1.1.1.14! root       28:        // Debugger は HostCOM と stdio ドライバが競合した場合に優先したいため
        !            29:        // もあって必ず先に配置する必要がある。
1.1.1.8   root       30:        NEWDV(SignalThread, new SignalThread());
                     31:        NEWDV(Scheduler, new Scheduler());
1.1.1.9   root       32:        NEWDV(Syncer, new Syncer());
1.1.1.8   root       33:        NEWDV(Debugger, new Debugger());
1.1       root       34: }
                     35: 
                     36: // デストラクタ
                     37: VM::~VM()
                     38: {
1.1.1.4   root       39:        Dispose();
                     40: }
                     41: 
                     42: // 終了
                     43: void
                     44: VM::Dispose()
                     45: {
1.1.1.8   root       46:        // まずスレッドを止める。
                     47:        // デバッガスレッドがスケジューラスレッドにアクセスするのでデバッガが先。
                     48:        if ((bool)pDebugger) {
1.1.1.9   root       49:                GetDebugger()->TerminateThread();
1.1.1.8   root       50:        }
                     51:        if ((bool)pScheduler) {
1.1.1.9   root       52:                GetScheduler()->TerminateThread();
1.1.1.8   root       53:        }
                     54: 
                     55:        // 残りのスレッドを停止
                     56:        for (auto obj : gMainApp.GetObjects()) {
                     57:                auto th = dynamic_cast<ThreadDevice *>(obj);
                     58:                if (th) {
                     59:                        th->TerminateThread();
                     60:                }
1.1.1.4   root       61:        }
1.1.1.8   root       62: 
                     63:        // 作ったときと逆順で解放する
                     64:        if ((bool)pDebugger) {
                     65:                pDebugger.reset();
                     66:        }
                     67: 
                     68:        if ((bool)pScheduler) {
                     69:                pScheduler.reset();
                     70:        }
                     71: 
                     72:        // ほかのオブジェクトの解放はグローバルデストラクタにおまかせ。
                     73:        // だめだったらまた考える。
1.1       root       74: }
                     75: 
1.1.1.13  root       76: // 動的コンストラクション。
1.1       root       77: bool
1.1.1.13  root       78: VM::Create(VM::CreationPhase phase)
1.1       root       79: {
1.1.1.8   root       80:        // d->Create() は Object を追加する場合があるため、ここで
1.1.1.13  root       81:        // ranged for は使えない。また追加されたデバイスの Create()/Create2() も
1.1.1.7   root       82:        // 実行したいため、ループ終了条件で毎回 size() を取り出して比較する。
1.1.1.8   root       83:        for (int i = 0; i < gMainApp.GetObjects().size(); i++) {
                     84:                auto dev = dynamic_cast<Device *>(gMainApp.GetObjects()[i]);
                     85:                if (dev) {
1.1.1.13  root       86:                        if (phase == CreationPhase::First) {
                     87:                                if (!dev->Create()) {
                     88:                                        return false;
                     89:                                }
                     90:                        } else {
                     91:                                if (!dev->Create2()) {
                     92:                                        return false;
                     93:                                }
1.1.1.8   root       94:                        }
1.1       root       95:                }
                     96:        }
                     97: 
1.1.1.13  root       98:        // ログのためのメンバ変数初期化。
                     99:        // 同じオブジェクトに対して複数回呼んでも副作用はない。
                    100:        for (auto obj : gMainApp.GetObjects()) {
                    101:                auto dev = dynamic_cast<Device *>(obj);
                    102:                if (dev) {
                    103:                        dev->EarlyInit();
                    104:                }
                    105:        }
                    106: 
1.1       root      107:        return true;
                    108: }
                    109: 
                    110: // 初期化
                    111: bool
                    112: VM::Init()
                    113: {
1.1.1.8   root      114:        for (auto obj : gMainApp.GetObjects()) {
                    115:                auto dev = dynamic_cast<Device *>(obj);
                    116:                if (dev) {
                    117:                        if (!dev->Init()) {
                    118:                                return false;
                    119:                        }
                    120:                }
                    121:        }
                    122: 
1.1.1.11  root      123:        // デバイスの初期化が全部出来たのでメインバスの初期化。
                    124:        auto mainbus = dynamic_cast<MainbusDevice*>(pMainbus.get());
                    125:        if (mainbus->InitMainbus() == false) {
                    126:                return false;
                    127:        }
                    128: 
1.1.1.12  root      129:        // イベントが出揃ったのでスケジューラモニタの行数を確定。
                    130:        auto scheduler = dynamic_cast<Scheduler*>(pScheduler.get());
                    131:        if (scheduler->Init2() == false) {
                    132:                return false;
                    133:        }
                    134: 
1.1.1.8   root      135:        return true;
                    136: }
                    137: 
                    138: // スレッド開始
                    139: bool
                    140: VM::StartThread()
                    141: {
                    142:        for (auto obj : gMainApp.GetObjects()) {
                    143:                auto th = dynamic_cast<ThreadDevice *>(obj);
                    144:                if (th) {
                    145:                        if (!th->StartThread()) {
                    146:                                return false;
                    147:                        }
1.1       root      148:                }
                    149:        }
                    150: 
                    151:        return true;
                    152: }
                    153: 
                    154: // 設定の適用
                    155: bool
                    156: VM::Apply()
                    157: {
1.1.1.8   root      158:        for (auto obj : gMainApp.GetObjects()) {
                    159:                auto dev = dynamic_cast<Device *>(obj);
                    160:                if (dev) {
                    161:                        if (!dev->Apply()) {
                    162:                                return false;
                    163:                        }
1.1       root      164:                }
                    165:        }
                    166: 
                    167:        return true;
                    168: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.