SDV でのサービス品質のスケジューリング

SDV サービス品質(QoS)スケジューリング フレームワークは、Lifecycle Manager(LM)によって管理されるサービス バンドルに対して、決定論的な CPU リソース割り当てを提供します。このプラットフォームは、低レベルの Linux スケジューリング属性(ポリシー、優先度、Nice)を論理プリセットに抽象化することで、サービス開発と車両全体のシステム チューニングを明確に分離できます。これにより、システムがバックグラウンド タスクを制約して不安定さを防ぎながら、安全性が重要なワークロードや時間制約のあるワークロードに必要なコンピューティング帯域幅を提供できます。

役割と責任

SDV スケジューリング モデルは、委任された責任パターンに従って、サービスが移植可能でありながら、OEM がシステムをチューニングできるようにします。

ロール 責任範囲 主な成果物
SDV プラットフォーム(Google) sdv_service_bundles_scheduling.proto スキーマを定義し、LM 強制ロジックを実装して、sdv_service_bundles_scheduling クライアント ライブラリを提供します。 Protobuf の定義とプラットフォーム ライブラリ
OEM(システム インテグレータ) 各プリセットの具体的な値(特定のハードウェアで ELEVATED が意味するものなど)を定義し、システム全体の設定を制御します。 /product/etc/lifecycle_config.textproto
サービス デベロッパー 適切な論理プリセット名を選択し、サービス バンドル マニフェストに scheduling_config.textproto パスを登録します。 scheduling_config.textprotosdv_service_bundles_manifest.textproto

技術ワークフロー

  1. プラットフォームの統合: OEM は、車両固有の lifecycle_config.textproto を定義します。このファイルは、システム全体のスケジューリング プロファイル(プリセット)を確立し、ターゲット ハードウェアに基づいて具体的な Linux スケジューリング属性にマッピングします。
  2. サービス バンドルの開発: デベロッパーは、APEX パッケージ内に scheduling_config.textproto をバンドルし、論理プリセット(ELEVATED など)を推奨して、内部スレッド名を定義します。
  3. サービス バンドルの統合: 車両統合フェーズで、OEM はデベロッパーが推奨するプリセットを確認します。OEM は、推奨されるプロファイルを維持することも、オーバーライドすることもできます。たとえば、APEX に署名する前に、システム全体の安定性を向上させるために、ELEVATED サービスを NORMAL にダウングレードします。
  4. ランタイム属性の解決: サービスが開始されると、LM はサービスのマニフェストから承認されたプリセットを特定し、OEM のシステム構成から対応する Linux 属性を取得します。
  5. 起動の同期と強制: LM は、解決された属性をサービス プロセスに適用してから、シグナルと続行プロトコルを使用して実行を続行するように通知します。

基本コンセプト

SDV スケジューリング フレームワークの中心となるコンセプトは次のとおりです。

スケジューリング プリセット

スケジューリング プリセットは、SDV で QoS を管理するための主要なメカニズムです。デベロッパーは、未加工の Linux スケジューリング パラメータを定義するのではなく、事前定義されたプリセットを参照します。実行時に、LM はこれらの論理名を具体的な Linux スケジューリング属性にマッピングします。

lifecycle_config.textproto に例として構成されているプリセットは次のとおりです。

プリセット名 スケジューリング ポリシー 一般的な Nice 値 一般的なユースケース
NORMAL SCHED_OTHER 0 標準サービス(HVAC、メディア、設定)
ELEVATED SCHED_OTHER -10 コア システム コンポーネントとインフラストラクチャ
IDLE SCHED_IDLE 19 バックグラウンド分析と重要でないロギング
CUSTOM ユーザー定義 -20(初期) リアルタイム ポリシーまたはアフィニティを必要とするサービス

プリセットを適用する場合、LM は setpriority システム呼び出しを使用して、プロセス全体の nice 値を設定します。これは、デフォルトの Linux Completely Fair Scheduler(CFS)での競合中にプロセスが受け取る相対的な CPU シェアに影響します。

権限とセキュリティ

不正な優先度のエスカレーションを防ぐため、SDV プラットフォームは SELinux ドメインと Linux 機能に基づく階層型セキュリティ モデルを採用しています。

セキュリティ ドメイン

  • untrusted_service_bundle: 標準プリセット(NORMALELEVATEDIDLE)のデフォルト ドメイン。カーネルはこのドメインのプロセスを制限し、独自のスケジューリング パラメータを変更できないようにします。
  • priority_service_bundle: システム全体の lifecycle_config.textprotois_privileged: true が設定されているプリセットを使用するサービス バンドルに付与されます。このドメインに移行すると、プロセスに CAP_SYS_NICE 機能が付与され、独自のリソース割り当てを管理できるようになります。

CAP_SYS_NICE 機能

このプラットフォームは、priority_service_bundle ドメインのプロセスに CAP_SYS_NICE 機能を提供します。この権限により、プロセスは次の操作を行うことができます。

  • 独自の nice 値を初期割り当てを超えて引き上げます。
  • スケジューリング ポリシーを SCHED_FIFOSCHED_RR などのリアルタイム クラスに変更します。
  • sched_setaffinity を使用して CPU アフィニティを設定します。
  • SCHED_DEADLINE の特別な期限パラメータを構成します。

この機能を専用ドメインに制限することで、明示的に承認されたサービスの中断を制限し、システム全体のスケジューリング バランスを保護します。

構成ガイド

このセクションでは、OEM とサービス デベロッパーの両方に構成に関するガイダンスを提供します。

OEM ガイド: システム全体のプリセット

OEM は、/product/etc/lifecycle_config.textproto にスケジューリング プロファイルを定義します。このプラットフォームには、lifecycle_management/config/lifecycle_config.textproto に例が用意されています。OEM は、車両のハードウェアに基づいてこの例を調整する必要があります。

例: リアルタイム プリセットを定義する

OEM は、標準アプリケーションによってプリエンプトされない安全関連サービス用に CRITICAL プリセットを定義できます。

# lifecycle_config.textproto
scheduling_presets {
  name: "CRITICAL"
  is_privileged: true
  thread_scheduling_configuration {
    policy: 1      # SCHED_FIFO
    priority: 80   # High real-time priority
  }
}

デベロッパー ガイド: サービス バンドルの構成

サービス デベロッパーは、scheduling_config.textproto ファイルでプリセットを推奨し、必要に応じて論理スレッド名を定義します。このプラットフォームで検出されるようにするには、このファイルへのパスを sdv_service_bundles_manifest.textproto に登録する必要があります。

例: マニフェストの登録

# sdv_service_bundles_manifest.textproto
service_bundle_entries {
  name: "SensorService"
  scheduling_config_path: "configs/scheduling_config.textproto"
}

例: 標準プリセットを使用する

ほとんどのサービスでは、scheduling_config.textproto でプリセット名を参照するだけで十分です。

# configs/scheduling_config.textproto
scheduling_preset_name: "ELEVATED"

例: サービスによって生成されたワーカースレッドのスケジューリング

サービス デベロッパーは、低レイテンシのセンサーデータ ループなどの特殊なタスクを処理するために、コードに追加のワーカースレッドを作成できます。デベロッパーは、構成ファイルでこれらの内部スレッドに名前付きのスケジューリング属性を定義できます。

このメタデータを使用して内部ワーカースレッドのプロパティを設定する権限付きサービスでのみ、手動適用を使用します。

# configs/scheduling_config.textproto
scheduling_preset_name: "CUSTOM"

# Map of logical thread names to their attributes (propagated as metadata)
thread_scheduling_configuration {
  key: "sensor-processing-thread"
  value {
    policy: 1        # SCHED_FIFO
    priority: 50
    cpu_affinity_ids: [2, 3]  # Pin to specific cores
  }
}

システムの動作と強制

SDV プラットフォームは、サービス固有のコードを実行する前にスケジューリング構成を有効にする厳格な強制モデルを採用しています。

起動の同期

サービスが誤った優先度で実行されないようにするため(初期化フェーズでも)、LM と Service Bundle Runner(SBR)はシグナルと続行の同期プロトコルを使用します。

  1. プロセスの作成: LM は SBR プロセスをフォークします。この時点で、SBR 子プロセスは実行されていますが、すぐにブロック状態になり、stdin でシグナルを待機します。
  2. 属性の適用: 子がブロックされている間、LM は setpriority システム呼び出しを使用して、リクエストされた nice 値を適用し、スケジューリング ポリシー(SCHED_IDLE など)を構成します。
  3. セキュリティの移行: LM は SELinux ドメインの移行を実行し、子を untrusted_service_bundle ドメインまたは priority_service_bundle ドメインに移動します。
  4. シグナル: すべてのパラメータが正常に適用された後にのみ、LM は子プロセスの stdin に 1 バイトのシグナルを送信します。
  5. 実行: SBR はシグナルを受信し、サービス ライブラリの読み込みとライフサイクル メソッドの呼び出しを開始します。

メインスレッドとライフサイクルへの影響

サービス ライブラリを読み込む前に同期することで、このプラットフォームは、すべてのライフサイクル コールバックでメイン実行スレッドのリクエストされた優先度を維持します。

  • onCreate: すべての依存関係インジェクションと初期リソース割り当ては、正しい優先度で行われます。
  • onStart: プリセットは、アクティブ状態への移行と初期ワークループを制御します。
  • onStoponDestroy: このプラットフォームは、シャットダウン中に重要なシステム アクティビティが停止しないように、同じ優先度でクリーンアップ オペレーションを実行します。

バインダ スレッドプールと優先度の継承

プラットフォーム管理のバインダ スレッドプールのスレッドは、プールを作成したスレッドの優先度で処理を実行しません。代わりに、同期トランザクションの場合、サーバー スレッドは呼び出し元の優先度を継承します。バインダ カーネル ドライバは、この優先度継承メカニズムを制御します。

スレッドレベルのファインチューニング

きめ細かい制御(リアルタイム処理ループなど)を必要とするサービス バンドルは、ワーカースレッドに構成を手動で適用する必要があります。スレッドレベルの構成を適用する手順は次のとおりです。

  1. 権限付きプリセット(is_privileged: true が設定されている)をリクエストします。
  2. sdv_service_bundles_scheduling ライブラリの get_scheduling_configuration 関数を使用して、thread_scheduling_configuration を読み取ります。
  3. sched_setattr を使用して、ワーカースレッドに属性を適用します。

SELinux と機能の強制

このプラットフォームは、SELinux と CAP_SYS_NICE Linux 機能を使用して、スケジューリング プリセットを強制します。

  • NORMALIDLE などのプリセットを使用するサービスの場合、スケジューリングは起動時に LM によって構成されます。これらのサービスには CAP_SYS_NICE 機能がなく、優先度やポリシーを変更できません。
  • 権限付きプリセット(is_privileged: true)を使用するサービスには、CAP_SYS_NICE 機能が付与されます。これにより、リアルタイム タスクに必要なように、内部スレッドのスケジューリングを手動で制御できます。

検証とサンプル

スケジューリング動作を検証するには、ログ分析とシステムレベルのパフォーマンス測定を組み合わせる必要があります。SDV プラットフォームには、これらの手法を示す専用のサンプルが用意されています。

QoS スケジューリング サンプル

samples/qos_scheduling にあるこのサンプルには、並行して実行して進行状況を報告するように設計されたパフォーマンス テスト サービスがいくつか含まれています。

  • PerformanceTesterNormal: NORMAL プリセットで実行されます。
  • PerformanceTesterElevated: ELEVATED プリセットで実行されます。
  • PerformanceTesterRealtime: CUSTOM プリセットを使用して、内部ワーカースレッドに SCHED_FIFO を適用します。
  • PolicyOffender: NORMAL プリセットを使用しながらリアルタイムの優先度を設定しようとする診断サービス。これは、このプラットフォームが不正なエスカレーションを正常にブロックすることを確認するために使用されます。

検証スイートを実行する

  1. QoS 固有のオーケストレーション構成を有効にします。

    adb shell setprop persist.sdv.orchestrator_config_path /etc/orch/vm_qos_scheduling_orch_config.textproto

  2. デバイスを再起動して、それぞれのスケジューリング ドメインでサービスを開始します。

    adb reboot

  3. ログをフィルタして、比較パフォーマンスの結果を確認します。

    adb logcat | grep sdv_sample_qos_common

    PerformanceTesterElevated サービスは、PerformanceTesterNormal と比較して、完了した作業単位が大幅に多いことを報告します。PolicyOffender サービスのログには、EPERM エラーまたは SELinux 拒否エラーが含まれています。

下位互換性

  • 下位互換性を確保するため、マニフェストで scheduling_config_path を指定しているが、構成ファイルで not を指定していない従来のサービス バンドルは、権権限付きサービスとして自動的に扱われます。scheduling_preset_nameこれにより、手動スレッド チューニングに依存する古いサービスに必要な機能(CAP_SYS_NICE など)が維持されます。
  • ルート構成メッセージ DeadlineSchedulingConfiguration は、今後のリリースで名前が変更される予定です。現在の名前は履歴であり、このメッセージが期限スケジューリングだけでなく、すべてのスケジューリング タイプを処理することを正確に反映していません。