|
|
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:
23: // リクエストフラグ
24: static const uint REQ_SYNC = 0x0001; // スケジューラを同期モードに
25: static const uint REQ_FAST = 0x0002; // スケジューラを高速モードに
26: static const uint REQ_RUN = 0x0004; // MPU が通常状態になった
27: static const uint REQ_STOP = 0x0008; // MPU が STOP 状態になった
28: static const uint REQ_MODEMASK = 0x000f; // mode マスク
29: static const uint REQ_POWER_ON = 0x0010; // 電源オン
30: static const uint REQ_POWER_OFF = 0x0020; // 電源オフ
31: static const uint REQ_EXIT = 0x0040; // アプリケーション終了
1.1.1.5 root 32: static const uint REQ_RESET = 0x0080; // ハードウェアリセット
1.1 root 33:
34: // 動作モード
35: // 動作モード変数 (mode) は高速モードか通常モードかと、MPU が通常状態が
36: // STOP 状態かを同時に保持している。高速走行中であっても MPU が STOP 状態
37: // なら通常走行するというロジックを比較1回で済ませるため。
38: static const uint32 SCHED_STOP = 0x0001; // スケジューラが STOP 状態
39: static const uint32 SCHED_SYNC = 0x0002; // 同期(%1)/高速(%0)モード
1.1.1.3 root 40:
41: // 演算を1回で済ませるために、この2値は同じ値にすること。
42: // ただしこれをチェックするために全員が m68030.h/m88100.h を include すると
43: // m88k を修正するたびに m68k も含めて全部ビルドが走るのはかなりつらいので
44: // 定義されてる時だけチェックすることにする。
45: // もともと将来のポカよけなのでビルド中1回でも通過すれば十分。
46: #if defined(CPU_REQ_STOP)
1.1 root 47: static_assert(SCHED_STOP == CPU_REQ_STOP, "must be the same");
1.1.1.3 root 48: #endif
1.1 root 49:
50: public:
51: Scheduler();
1.1.1.6 ! root 52: virtual ~Scheduler() override;
1.1 root 53:
1.1.1.3 root 54: bool Init() override;
1.1 root 55:
1.1.1.4 root 56: nnSize GetMonitorSize() override;
57: void MonitorUpdate(TextScreen&) override;
1.1 root 58:
59: // スレッド開始
60: void ThreadRun();
61:
1.1.1.2 root 62: // スレッド終了
1.1 root 63: void Terminate();
64:
65: // スケジューラを開始 (電源オン時に vm から呼ばれる)
66: void Run();
67:
68: // 電源オフ要求
69: void RequestPowerOff() {
70: atomic_reqflag |= REQ_POWER_OFF;
71: }
72:
1.1.1.5 root 73: // リセット要求
74: void RequestResetHard() {
75: atomic_reqflag |= REQ_RESET;
76: }
77:
1.1 root 78:
79: // スケジューラが高速モードなら true を返す。
80: // ここでいう高速モードは STOP 状態中でも高速モード。
81: bool GetFullSpeed() const { return ((mode & SCHED_SYNC) == 0); }
82:
83: // スケジューラの動作モードを設定する。
84: // true なら高速モード、false なら同期モード。
85: void SetFullSpeed(bool enable);
86:
1.1.1.2 root 87: // イベントを開始する
88: void StartEvent(Event *newev);
89: // イベントを停止する
90: void StopEvent(Event *event);
1.1 root 91:
92: std::list<Event *> eventlist {}; // 有効なイベントリスト
93: std::mutex evcs {}; // イベントリストのロック
94:
95: // 状態変更要求
96: // スケジューラループの状態を変更したい場合はこのフラグを立てる。
97: // REQ_MODE_* の相反するビット以外は同時に複数立ててもいいはず。
98: // 処理されると再び 0 になる。
99: std::atomic<uint32> atomic_reqflag {};
100: std::condition_variable cv {};
101: std::mutex cvmtx {};
102:
103: private:
1.1.1.5 root 104: // リセットイベントコールバック
105: void ResetCallback(Event& ev);
106:
1.1.1.2 root 107: pthread_t thread {};
1.1.1.5 root 108: bool thread_created {}; // スレッドが作成されたら true
1.1.1.2 root 109:
1.1 root 110: // スケジューラの動作モード。SCHED_*
1.1.1.5 root 111: uint32 mode {};
1.1 root 112:
1.1.1.5 root 113: uint64 rtimestart {}; // スケジューラ開始実時刻
114: uint64 rtimebase {}; // 実時間の基準時刻
115: uint64 vtimebase {}; // 仮想時間の基準時刻
1.1 root 116:
117: // 前回 RTC へ 32Hz 入力パルスを入れた時刻 (実時間の絶対時刻系)
1.1.1.5 root 118: uint64 rtc_last_clock {};
1.1 root 119: };
120:
1.1.1.2 root 121: extern std::unique_ptr<Scheduler> gScheduler;
1.1 root 122:
123: // 現在時刻 [nsec] を取得する
124: static inline uint64 GetRealTime()
125: {
126: struct timeval tv;
127: gettimeofday(&tv, NULL);
128: return (uint64)(tv.tv_sec * 1000 * 1000 + tv.tv_usec) * 1000;
129: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.