Expand description
§優先度ベースのプリエンプティブ・ラウンドロビン・スケジューラ
このモジュールは、各CPUコアごとに独立したランキューを持つ(Per-Core SMP)、優先度ベースのプリエンプティブ・ラウンドロビン・スケジューラの実装を提供します。 EL1カーネルスレッドとEL0ユーザープロセスの両方のマルチプロセス環境をサポートしています。
Structs§
- Core
Runqueue - 各コアで動作するプロセスのランキュー構造体。
- Process
- プロセス制御ブロック (PCB)。プロセスのメタデータ、実行コンテキスト、スタック情報を保持します。
Enums§
- Priority
- プロセスのスケジュール優先度を表す列挙型。
- Process
State - プロセスの状態を表す列挙型。
Statics§
- NEXT_
PID 🔒 - 次に割り当てるべきプロセスIDを管理するアトミックカウンタ。
- PREEMPT_
COUNTS 🔒 - 各コアごとのプリエンプション禁止カウンタ。
preempt_count == 0の時のみプリエンプション(強制タスク切り替え)が許可されます。 - RUNQUEUES 🔒
- 各コア固有のランキュー (Per-Core Runqueues)。 各コアが独立してランキューに対する排他制御(Mutex)を行います。
- ZOMBIES 🔒
- 終了したプロセスの「墓場」。
exit()は現在実行中のプロセスのカーネルスタック上で動作するため、 その場でProcessをドロップすると自身のスタックを解放してしまい、Use-After-Free が発生します。 そのため、一度この墓場領域に退避させ、別のプロセスへのコンテキストスイッチが行われた後 (そのスタックから外れた後)に、reap_zombies()を通じて安全にメモリを解放します。
Functions§
- core_id
- 現在実行中のCPUコアのID (0〜3) を取得します。
mpidr_el1レジスタからアフィニティレベル0を取得します。 - current_
sp 🔒 - 現在のスタックポインタ (SP) の値を取得します。
- decrement_
wait_ ticks - 待機状態 (Waiting) にある全プロセスの待ち時間チック数をデクリメントします。 チック数が0になったプロセスは実行可能状態 (Ready) に戻ります。
- enter_
userspace 🔒 ⚠ - exit
- 呼び出し元のプロセスを終了させます。
- get_
current_ page_ table - 現在の CPU コアで実行されているプロセスの TTBR0 ページテーブル物理アドレスを取得します。
- get_
current_ process_ id - 現在実行中のプロセスのPIDを取得します。 try_lock が失敗した場合は None を返します。
- get_
current_ process_ name - 現在実行中のプロセスの名前を取得します。 try_lock が失敗した場合は None を返します。
- get_
process_ page_ table - 指定した PID を持つプロセスの TTBR0 ページテーブル物理アドレスを取得します。
- init
- スケジューラの初期化処理。
起動コア (Core 0) 用の初期プロセス
kernel_mainを登録し、他のコアのランキューを空で初期化します。 - is_
current_ process_ critical - パニックハンドラ等から、現在のプロセスが主要なシステムプロセス(PID 0 または gui_shell など)であるかどうかを判定します。 デッドロックを防ぐため、try_lock を使用します。
- is_
preempt_ enabled - 現在のコアでプリエンプションが許可されている(preempt_count == 0)かを判定します。
- preempt_
disable - 現在のコアのプリエンプションを一時的に禁止します(カウントをインクリメント)。
- preempt_
enable - プリエンプション禁止を解除します(カウントをデクリメント)。
カウントが
0に戻り、かつ再スケジュール要求(need_resched)があれば即座に切り替えを実行します。 - reap_
zombies 🔒 - 現在のスタックポインタ (SP) がそのスタック上に存在しないゾンビプロセス(終了済みプロセス)を解放します。 まだスタックが使用中のプロセス(exit直後の自分自身など)は、次回以降のクリーンアップに持ち越します。
- register_
idle_ process - アイドルプロセス (
idle_core) を特定のコアに登録し、そのコアの初期プロセスとします。 - schedule 🔒
- スケジューリングのコア処理。 飢餓防止(starvation_count)を考慮した、優先度ベースのプリエンプティブ・ラウンドロビンアルゴリズムを適用し、 最もスコアの高い Ready 状態のプロセスを選択してコンテキストスイッチを行います。
- scheduler_
tick - タイマー割り込み(Tick)から毎チック呼び出され、プロセスの残りタイムスライスを管理します。
- should_
preempt - 現在のコアでプリエンプション(強制切り替え)を実行すべき状態かを判定します。
- sleep
- 指定した期間(タイマーチック数)だけ、呼び出し元のプロセスを待機状態 (Waiting) に移行させます。
- spawn
- カーネル空間 (EL1) で実行される新しいプロセス (カーネルスレッド) を生成し、 ロードバランシングに基づいてプロセス数が最も少ないコアのランキューに登録します。
- spawn_
on_ core - 特定のコアをターゲットにしてカーネルプロセス (カーネルスレッド) を生成します。
- spawn_
user - ユーザー空間 (EL0) で動作する新しいユーザープロセスを生成し、 ロードバランシングに基づいてプロセス数が最も少ないコアのランキューに登録します。
- spawn_
user_ on_ core - 指定したコアをターゲットにして、ユーザー空間 (EL0) で動作するユーザープロセスを生成します。
- spawn_
with_ arg - 引数
usizeを1つ取るカーネルプロセス (カーネルスレッド) を生成し、 ロードバランシングに基づいてプロセス数が最も少ないコアのランキューに登録します。 - spawn_
with_ arg_ on_ core - コアと引数
usizeを指定してカーネルプロセス (カーネルスレッド) を生成し、 対象コアのランキューに登録します。 - stack_
contains 🔒 - 指定されたスタックポインタ (SP) が、メモリ領域に含まれるかを判定します。
- switch_
context 🔒 ⚠ - tick
- 定期的に呼び出され(タイマー割り込みなど)、待機状態 (Waiting) にあるプロセスのチック数を更新し、
必要に応じて
schedule()を実行してコンテキストスイッチを行います。 - trampoline 🔒
- コンテキストスイッチで最初に起動するトランポリン関数。
レジスタ
x19からエントリポイント、x20から引数を受け取り、対象の関数を実行します。 実行が終了したスレッドは、exit()を呼び出して自身を終了させます。 - user_
trampoline 🔒 - ユーザープロセスのトランポリン関数。
switch_contextからretで呼ばれ、SP_EL1をカーネルスタックに、SP_EL0をユーザースタックに設定した上で、enter_userspaceを用いて EL0 に降下します。 - yield_
now - 呼び出し元のプロセスを一時的に実行可能状態 (Ready) に戻し、即座に再スケジュールを実行して CPUを他のプロセスに譲ります(コオペラティブ・マルチタスク)。