|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2017 [email protected] ! 4: // ! 5: ! 6: #pragma once ! 7: ! 8: #include <atomic> ! 9: #include <condition_variable> ! 10: #include <mutex> ! 11: #include <pthread.h> ! 12: #include "device.h" ! 13: #include "event.h" ! 14: #include "mpu.h" ! 15: ! 16: // スケジューラ ! 17: class Scheduler : public Device ! 18: { ! 19: typedef Device inherited; ! 20: ! 21: // リクエストフラグ ! 22: static const uint REQ_SYNC = 0x0001; // スケジューラを同期モードに ! 23: static const uint REQ_FAST = 0x0002; // スケジューラを高速モードに ! 24: static const uint REQ_RUN = 0x0004; // MPU が通常状態になった ! 25: static const uint REQ_STOP = 0x0008; // MPU が STOP 状態になった ! 26: static const uint REQ_MODEMASK = 0x000f; // mode マスク ! 27: static const uint REQ_POWER_ON = 0x0010; // 電源オン ! 28: static const uint REQ_POWER_OFF = 0x0020; // 電源オフ ! 29: static const uint REQ_EXIT = 0x0040; // アプリケーション終了 ! 30: ! 31: // 動作モード ! 32: // 動作モード変数 (mode) は高速モードか通常モードかと、MPU が通常状態が ! 33: // STOP 状態かを同時に保持している。高速走行中であっても MPU が STOP 状態 ! 34: // なら通常走行するというロジックを比較1回で済ませるため。 ! 35: static const uint32 SCHED_STOP = 0x0001; // スケジューラが STOP 状態 ! 36: static const uint32 SCHED_SYNC = 0x0002; // 同期(%1)/高速(%0)モード ! 37: // 演算を1回で済ませるために、同じ値にすること ! 38: static_assert(SCHED_STOP == CPU_REQ_STOP, "must be the same"); ! 39: ! 40: public: ! 41: Scheduler(); ! 42: virtual ~Scheduler(); ! 43: ! 44: virtual bool Init(); ! 45: ! 46: virtual bool MonitorUpdate(); ! 47: ! 48: // スレッド開始 ! 49: void ThreadRun(); ! 50: ! 51: // スレッド終了指示 ! 52: void Terminate(); ! 53: ! 54: // スケジューラを開始 (電源オン時に vm から呼ばれる) ! 55: void Run(); ! 56: ! 57: // 電源オフ要求 ! 58: void RequestPowerOff() { ! 59: atomic_reqflag |= REQ_POWER_OFF; ! 60: } ! 61: ! 62: // サイクル数を仮想時間 [nsec] に変換 ! 63: uint64 Cycle2Vtime(uint64 cycle) const { ! 64: return cycle * 1000 * 1000 / mpu_clock; ! 65: } ! 66: ! 67: // 仮想時間 [nsec] をサイクル数に変換 ! 68: uint64 Vtime2Cycle(uint64 vtime) const { ! 69: return vtime * mpu_clock / (1000 * 1000); ! 70: } ! 71: ! 72: // 仮想時刻取得 ! 73: uint64 GetVirtTime() const { ! 74: return Cycle2Vtime(gMPU->total_cycle()); ! 75: } ! 76: ! 77: // スケジューラが高速モードなら true を返す。 ! 78: // ここでいう高速モードは STOP 状態中でも高速モード。 ! 79: bool GetFullSpeed() const { return ((mode & SCHED_SYNC) == 0); } ! 80: ! 81: // スケジューラの動作モードを設定する。 ! 82: // true なら高速モード、false なら同期モード。 ! 83: void SetFullSpeed(bool enable); ! 84: ! 85: // イベントを登録する ! 86: void AddEvent(Event *newev); ! 87: // イベントを削除する ! 88: void DelEvent(Event *event); ! 89: ! 90: std::list<Event *> eventlist {}; // 有効なイベントリスト ! 91: std::mutex evcs {}; // イベントリストのロック ! 92: ! 93: // 状態変更要求 ! 94: // スケジューラループの状態を変更したい場合はこのフラグを立てる。 ! 95: // REQ_MODE_* の相反するビット以外は同時に複数立ててもいいはず。 ! 96: // 処理されると再び 0 になる。 ! 97: std::atomic<uint32> atomic_reqflag {}; ! 98: std::condition_variable cv {}; ! 99: std::mutex cvmtx {}; ! 100: ! 101: private: ! 102: // スケジューラの動作モード。SCHED_* ! 103: uint32 mode = 0; ! 104: ! 105: int mpu_clock = 0; // MPU クロック [kHz] ! 106: ! 107: uint64 rtimestart = 0; // スケジューラ開始実時刻 ! 108: uint64 rtimebase = 0; // 実時間の基準時刻 ! 109: uint64 vtimebase = 0; // 仮想時間の基準時刻 ! 110: ! 111: // 前回 RTC へ 32Hz 入力パルスを入れた時刻 (実時間の絶対時刻系) ! 112: uint64 rtc_last_clock = 0; ! 113: }; ! 114: ! 115: extern Scheduler *gScheduler; ! 116: ! 117: // 現在時刻 [nsec] を取得する ! 118: static inline uint64 GetRealTime() ! 119: { ! 120: struct timeval tv; ! 121: gettimeofday(&tv, NULL); ! 122: return (uint64)(tv.tv_sec * 1000 * 1000 + tv.tv_usec) * 1000; ! 123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.