|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #pragma once
8:
1.1.1.3 root 9: #include "device.h"
10: #include "event.h"
11: #include "mpu.h"
1.1 root 12: #include <atomic>
13: #include <condition_variable>
1.1.1.3 root 14: #include <list>
1.1 root 15: #include <mutex>
16: #include <pthread.h>
17:
18: // スケジューラ
19: class Scheduler : public Device
20: {
1.1.1.3 root 21: using inherited = Device;
1.1 root 22:
1.1.1.7 ! root 23: public:
! 24: // 動作モード
! 25: // 動作モード変数 (mode) はスケジューラの走行状態を表している。以下の
! 26: // ビットがすべて %0 なら高速モード、どれかでも %1 なら通常モードになる。
! 27: //
! 28: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
! 29: // mode | |SYNC| CPUSTAT |
! 30: // | +---+---- CPU の状態
! 31: // +-------------- 高速モード抑制
! 32: //
! 33: // bit1,0 (CPUSTAT) は CPU の状態を示す。%00 の時だけ高速走行が可能。
! 34: // これは MPUDevice::Run() の戻り値でもある。
! 35: // b1 b0
! 36: // 0 0 通常状態
! 37: // 0 1 STOP 状態 (m88k なら擬似 STOP 状態)
! 38: // 1 0 HALT 状態 (ダブルバスフォールト)
! 39: // 1 1 HALT 状態だがこちらのビットパターンは使わない
! 40: //
! 41: // bit2 (SYNC) が UI からの高速モード指示。%0 なら高速、%1 なら通常。
! 42: // なのでどっちかというと高速モード抑制指示というほうがいいかも。
! 43:
! 44: static const uint32 SCHED_CPU_STOP = 0x0001; // CPU が STOP 状態
! 45: static const uint32 SCHED_CPU_HALT = 0x0002; // CPU が HALT 状態
! 46: static const uint32 SCHED_SYNC = 0x0004; // 高速モード抑制指示(UI)
! 47:
! 48: // 便宜上用意しておく
! 49: static const uint32 SCHED_CPU_NORMAL= 0x0000; // CPU が通常状態
! 50: static const uint32 SCHED_CPU_MASK = (SCHED_CPU_STOP | SCHED_CPU_HALT);
! 51:
! 52: private:
1.1 root 53: // リクエストフラグ
1.1.1.7 ! root 54: // REQ_CPU_MODE は CPU mode が何らか変化することのフラグ。どの状態に変化
! 55: // するかは new_cpumode 変数で示す。1回のループ期間中に複数回の変化が
! 56: // 起きても最終状態だけに変化するため。
! 57: // REQ_USER_MODE と new_usermode も同様。
! 58: static const uint REQ_CPU_MODE = 0x0001; // CPU 状態を変更
! 59: static const uint REQ_USER_MODE = 0x0002; // 同期/高速モード変更
1.1 root 60: static const uint REQ_POWER_ON = 0x0010; // 電源オン
61: static const uint REQ_POWER_OFF = 0x0020; // 電源オフ
62: static const uint REQ_EXIT = 0x0040; // アプリケーション終了
1.1.1.5 root 63: static const uint REQ_RESET = 0x0080; // ハードウェアリセット
1.1 root 64:
65: public:
66: Scheduler();
1.1.1.6 root 67: virtual ~Scheduler() override;
1.1 root 68:
1.1.1.3 root 69: bool Init() override;
1.1 root 70:
1.1.1.4 root 71: nnSize GetMonitorSize() override;
72: void MonitorUpdate(TextScreen&) override;
1.1 root 73:
74: // スレッド開始
75: void ThreadRun();
76:
1.1.1.2 root 77: // スレッド終了
1.1 root 78: void Terminate();
79:
80: // スケジューラを開始 (電源オン時に vm から呼ばれる)
81: void Run();
82:
83: // 電源オフ要求
84: void RequestPowerOff() {
85: atomic_reqflag |= REQ_POWER_OFF;
86: }
87:
1.1.1.5 root 88: // リセット要求
89: void RequestResetHard() {
90: atomic_reqflag |= REQ_RESET;
91: }
92:
1.1 root 93:
94: // スケジューラが高速モードなら true を返す。
95: // ここでいう高速モードは STOP 状態中でも高速モード。
96: bool GetFullSpeed() const { return ((mode & SCHED_SYNC) == 0); }
97:
98: // スケジューラの動作モードを設定する。
99: // true なら高速モード、false なら同期モード。
100: void SetFullSpeed(bool enable);
101:
1.1.1.2 root 102: // イベントを開始する
103: void StartEvent(Event *newev);
104: // イベントを停止する
105: void StopEvent(Event *event);
1.1 root 106:
107: std::list<Event *> eventlist {}; // 有効なイベントリスト
108: std::mutex evcs {}; // イベントリストのロック
109:
110: // 状態変更要求
111: // スケジューラループの状態を変更したい場合はこのフラグを立てる。
112: // REQ_MODE_* の相反するビット以外は同時に複数立ててもいいはず。
113: // 処理されると再び 0 になる。
114: std::atomic<uint32> atomic_reqflag {};
115: std::condition_variable cv {};
116: std::mutex cvmtx {};
117:
118: private:
1.1.1.5 root 119: // リセットイベントコールバック
120: void ResetCallback(Event& ev);
121:
1.1.1.7 ! root 122: // スレッド終了を指示する
! 123: void RequestExit();
! 124:
1.1.1.2 root 125: pthread_t thread {};
1.1.1.5 root 126: bool thread_created {}; // スレッドが作成されたら true
1.1.1.2 root 127:
1.1 root 128: // スケジューラの動作モード。SCHED_*
1.1.1.5 root 129: uint32 mode {};
1.1 root 130:
1.1.1.7 ! root 131: // REQ_CPU_MODE フラグで変更するモード
! 132: uint32 new_cpumode {};
! 133:
! 134: // REQ_USER_MODE フラグで変更するモード
! 135: uint32 new_usermode {};
! 136:
1.1.1.5 root 137: uint64 rtimestart {}; // スケジューラ開始実時刻
138: uint64 rtimebase {}; // 実時間の基準時刻
139: uint64 vtimebase {}; // 仮想時間の基準時刻
1.1 root 140:
141: // 前回 RTC へ 32Hz 入力パルスを入れた時刻 (実時間の絶対時刻系)
1.1.1.5 root 142: uint64 rtc_last_clock {};
1.1 root 143: };
144:
1.1.1.2 root 145: extern std::unique_ptr<Scheduler> gScheduler;
1.1 root 146:
147: // 現在時刻 [nsec] を取得する
148: static inline uint64 GetRealTime()
149: {
150: struct timeval tv;
151: gettimeofday(&tv, NULL);
152: return (uint64)(tv.tv_sec * 1000 * 1000 + tv.tv_usec) * 1000;
153: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.