割込ハンドラへの優先度継承

Download Report

Transcript 割込ハンドラへの優先度継承

2005/7/15
ARTLinux,
ハードリアルタイム処理機能を拡張した
Linuxカーネル
石綿 陽一
[email protected]
株式会社ムービングアイ
URL : http://www.movingeye.co.jp
Copyright (C) MovingEye Inc.
■ARTLinuxの特徴
MovingEye Inc.
ARTLinux:
ハードリアルタイム処理機能を拡張したLinuxカーネル
•
•
•
•
•
固定優先度に基づくスケジューリング機能
実時間タスクをユーザプロセスとして実行
多段階の優先度継承機能
ハードウェア割込を周期的にポーリング
アプリケーションのバイナリ互換
Linuxの全システムコールを実時間処理に利用可能
• デバイスドライバのソース互換
再コンパイルによって実時間処理に利用可能なバイナリを生成
Copyright (C) MovingEye Inc.
■ハードリアルタイムOS
MovingEye Inc.
• 実時間処理の定義
得られた値だけでなく, 値を得た時刻にも依存して計算結果の正しさが
決まる処理
• ハードリアルタイムスケジューリングの理論
複数のタスクがあり, 開始時刻, 最悪実行時間, デッドラインが与えら
れているとき, デッドラインまでに処理の終了を保証する理論
– プリエンプティブマルチタスク機能
– 固定優先度によるタスクスケジューリング機能
• ハードリアルタイムOS
– 十分に短い割込応答性能
Copyright (C) MovingEye Inc.
■優先度逆転
MovingEye Inc.
高
処理1
優
先
度
処理2
処理3
低
T1
時刻T1まで
時刻T1
時刻T1からT2まで
時刻T2
時刻T2から時刻T3まで
時刻T3から
T2
T3
最も高い優先度の処理1が実行される.
処理1が処理3の結果待ちになる.
中間の優先度の処理2が実行される.
処理2が終了.
処理3が実行される.
処理1が実行される.
Copyright (C) MovingEye Inc.
■優先度継承
MovingEye Inc.
高
優
先
度
処理1
処理3
処理1
処理2
処理3
低
時刻T1まで
時刻T1
時刻T1からT2まで
時刻T2
時刻T2から
T1
T2
最も高い優先度の処理1が実行される.
処理1が処理3の結果待ちになる.
処理1の優先度が処理3に継承される.
処理3が実行される.
処理3が終了.
処理1が実行される.
Copyright (C) MovingEye Inc.
■Linux実時間拡張の分類
MovingEye Inc.
“A comparison of real-time Linux approaches”
URL: http://linuxdevices.com/articles/AT4721170330.html
によると,
1.
2.
3.
4.
5.
6.
7.
•
non-CONFIG_PREEMPT
CONFIG_PREEMPT
CONFIG_PREEMPT_RT
Nested OS
Dual-OS/Dual-Core
Migration Between OSes
Migration Within OS
ARTLinux
Copyright (C) MovingEye Inc.
■Linux実時間拡張の手法
MovingEye Inc.
1. non-CONFIG_PREEMPT
通常のLinux
ハードウェアの速度向上により, 応用によっては十分な実時間性能
2. CONFIG_PREEMPT
クリティカルセクション以外ではプリエンプティブ
クリティカルセクション脱出時にプロセススケジューリング
3. CONFIG_PREEMPT_RT
クリティカルセクション内にプリエンプトポイントを追加
spin lockを優先度継承機能 (ただし一段階と思われる) を持つ
suspended lockに置換
•
ARTLinux
割込ハンドラを実時間タスク (プロセス) 内で実行
spin lockを多段階優先度継承機能を持つsuspended lock (realtime lockと呼ぶ) に置換
Copyright (C) MovingEye Inc.
■LinuxカーネルのSMP対応と実時間処理
MovingEye Inc.
非プリエンプティブ
UNIX
非効率なSMP
Linux 2.0
Linux 2.2
Linux 2.4
複数のCPUが
カーネルコードを
同時に実行できない
非プリエンプティブ
非リアルタイム
SMPの効率化
ロックの細分化
効率的なSMP
Linux 2.6
複数のCPUが
カーネルコードを
同時に実行可能
プリエンプティブ
ソフトリアルタイム
Copyright (C) MovingEye Inc.
■割込応答時間の短縮
MovingEye Inc.
割
込
割込
割込 プリエンプト プロセス
禁止期間 ハンドラ 延期期間 スイッチ
ブロック
期間
アプリ
ケーション
割込応答時間
赤で示した期間は, 他のプロセスを実行している.
割込応答時間を短縮するためには, 赤で示した期間を短縮す
る必要がある.
Copyright (C) MovingEye Inc.
■割込禁止期間の短縮
MovingEye Inc.
割込ハンドラとプロセス, 割込ハンドラ間の排他制御
1. ハードウェア割込マスク中
local_irq_disable()からlocal_irq_enable()までの間
割込ハンドラの実行中
最長時間はLinuxカーネルコードに依存
2. 1. と同様
3. 1. と同様
•
real-time schedulerやreal-time lock処理中の一部
割込ハンドラがプロセス内で実行されるため, プロセス間の排他制御
に置換
最長時間はLinuxカーネルコードに非依存
Copyright (C) MovingEye Inc.
■プリエンプト延期期間
MovingEye Inc.
1. タイマ割込まで
タイマ割込周期によって短縮可能
2. クリティカルセクション終了まで
ユーザコード実行中や, クリティカルセクション以外のカーネルコード
実行中は, 延期されない.
最長時間はLinuxカーネルコードに依存
3. プリエンプトポイントまで
クリティカルセクションがプリエンプトポイントで分割されるため, 1.より
短縮される.
最長時間は修正されたLinuxカーネルコードに依存
•
常に延期されない
Copyright (C) MovingEye Inc.
■ブロック期間の短縮
MovingEye Inc.
クリティカルセクション中, つまりあるspin lockがロック中にプ
リエンプトして, そのspin lockにブロックされる場合
1. クリティカルセクション中はプリエンプトしないので, ブロッ
クされない.
2. 1. と同様
3. ロックが解除されるまで
優先度継承機能によって短縮される.
多段階にブロックされていた場合, 優先度逆転によって長時間になる.
•
ロックが解除されるまで
多段階にブロックされていた場合でも, 多段階優先度継承機能によっ
て短縮される.
Copyright (C) MovingEye Inc.
■ARTLinuxにおける割込時間短縮の手法
MovingEye Inc.
spin lockを
suspended lockに置換
Linuxカーネル
コードに依存
クリティカル
セクションが伸長
優先度
逆転が発生
Linuxカーネル
コードに非依存
ブロック
期間が伸長
多段階
ブロックが発生
優先度
逆転を抑制
多段階優先度
継承機能
割込禁止
期間の短縮
割込ハンドラを
プロセス内で実行
プリエンプト延期
期間の短縮
ブロック
期間の短縮
割込応答
時間の短縮
Copyright (C) MovingEye Inc.
■割込ハンドラへの優先度継承
MovingEye Inc.
割込ハンドラの優先度設定
• 割込ハンドラ > 実時間タスク > 非実時間プロセス
割込ハンドラによって, クリティカルタスクの実行が阻害される.
• 実時間タスク > 割込ハンドラ > 非実時間プロセス
実時間タスクが割込ハンドラの実行待になった場合, 優先度逆転が
発生する.
どちらにも問題があり, アプリケーションに依存して決まる.
• 静的な設定方法
システムコールで割込ハンドラの優先度を設定する.
• 動的な設定方法
実時間タスクの優先度を割込ハンドラに継承する.
ARTLinuxではwait_queueに優先度継承機能を持たせて,
割込ハンドラの優先度を動的に設定している.
Copyright (C) MovingEye Inc.
■割込ハンドラの周期実行
MovingEye Inc.
• タイマ割込に基づいて実時間タスクの正確な周期実行を
実現する.
• タイマ以外のハードウェア割込を実時間タスク上で周期的
にポーリングする.
– 割込応答時間が長くなる.
• 実時間処理に適当なのか?
– 実時間処理と割り込み処理は矛盾.
– 周期実行は割り込み処理のモデル化の一つ.
• デバイスを制御できるのか?
– 周辺ICの高機能化により素早い割り込みレスポンスは不要.
Copyright (C) MovingEye Inc.
■性能測定
MovingEye Inc.
• 指定周波数 (1000, 500, 200, 100, 50, 20, 10, 9, 8, 7μ
秒) で実時間タスクを周期実行する.
• プロセッサ内蔵されているTime Stamp Counterで周期を
計測する.
• 100,000回計測して, 誤差の絶対値を得る.
• プロセッサはIntel Pentium 4の2.40GHz
Copyright (C) MovingEye Inc.
■測定結果 (バックグラウンド無し)
MovingEye Inc.
9.0
周期誤差の絶対値 [μs]
8.0
7.0
7.0
6.0
5.0
99.9%
最大値
4.0
3.0
2.0
1.0
1.6
0.7
0.3
0.7
0.2
0.6
0.1
0.6
0.1
0.7
0.2
0.6
0.1
1000 500
200
100
50
20
0.0
0.1
10
0.8
0.2
0.50.7
9
8
0.6
7
指定周期 [μs]
Copyright (C) MovingEye Inc.
■測定結果 (バックグラウンドでDhrystone)
MovingEye Inc.
9.0
周期誤差の絶対値 [μs]
8.0
7.1
7.0
6.0
5.0
99.9%
最大値
4.0
3.0
2.1
2.0
1.0
1.6
0.20.2
0.20.2
0.30.4
0.9
0.3
1000 500
200
100
50
0.8
0.2
0.8
0.2
20
1.1
0.3
0.3
0.4
0.5
9
8
7
0.0
10
指定周期 [μs]
Copyright (C) MovingEye Inc.
■測定結果 (バックグラウンドでコピー)
9.0
MovingEye Inc.
8.3
周期誤差の絶対値 [μs]
8.0
7.0
6.5
6.0
5.4
5.0
3.7
4.0
3.0
2.0
1.0
3.6
3.2
2.6
1.5
99.9%
最大値
3.0
2.7
1.9
1.7
0.8
3.1
2.8
1.0
1.0
200
100
0.9
0.0
1000 500
50
20
10
9
8
7
指定周期 [μs]
Copyright (C) MovingEye Inc.
■新しいシステムコール
MovingEye Inc.
int art_enter(art_prio_t prio,
art_flags_t flags, int usec)
実時間タスクに変換する.
int art_wait(void)
次の周期を待つ.
int art_exit(void)
実時間実行を終了する.
int art_wait_phase(unsigned long usec,
art_prio_t prio)
指定した時刻を待つ.
int art_yield(void)
実行を中断する.
Copyright (C) MovingEye Inc.
■サンプルプログラム
#include
#include
#include
#include
MovingEye Inc.
<stdio.h>
<stdlib.h>
<sys/io.h>
<linux/art_task.h>
#define TRUE 1
#define KBD_PORT 0x61
#define SPK_BIT 0x02
main(int argc, char *argv[])
{
int temp, hz, i;
hz = atoi(argv[1]);
ioperm(KBD_PORT, 1, TRUE);
art_enter(ART_PRIO_MAX, ART_TASK_PERIODIC, 500000 / hz);
for (i = 0; i < hz * 5; ++i) {
art_wait();
temp = inb(KBD_PORT);
temp = (i & 1) ? temp | SPK_BIT : temp & ~SPK_BIT;
outb(temp, KBD_PORT);
}
art_exit();
}
Copyright (C) MovingEye Inc.
■サンプルプログラム
#include
#include
#include
#include
MovingEye Inc.
<stdio.h>
<stdlib.h>
<unistd.h>
<linux/art_task.h>
int main(int argc, char *argv[])
{
art_prio_t prio;
if (argc < 3 || (prio = atoi(argv[1])) < ART_PRIO_MIN ||
prio > ART_PRIO_MAX) {
fprintf(stderr, "usage: %s prio file arg ...\n", argv[0]);
return -1;
}
if (art_enter(prio, ART_TASK_RR, 0) == -1) {
perror("art_enter");
return -1;
}
if (execvp(argv[2], &argv[2]) == -1) {
perror("execvp");
return -1;
}
return 0;
}
Copyright (C) MovingEye Inc.
■周期処理による実時間プログラミング
MovingEye Inc.
• 周期実行の誤差が十分に小さい.
• ハードウェア割込の応答時間が長い.
ARTLinuxでは周期処理に基づく実時間処理を推奨.
ただし, イベント処理も可能.
• イベント処理
– 周辺デバイスが独自の「メトロノーム」によって動くシステム.
– 「メトロノーム」間の同期に割込が必要.
– プログラミングを複雑化しているのではないか?
• 周期処理
– プロセッサが「指揮者」となって全体を動かすシステム.
– プロセス間通信でも時刻による同期でプログラミングが可能.
– 応用範囲は意外と広いのではないか?
Copyright (C) MovingEye Inc.
■システムコールを用いない例
MovingEye Inc.
art_enter();
for (;;) {
art_wait();
/*
* 処理
*/
if (/* condition to finish */)
break;
}
art_exit();
本質的に周期的な処理であれば実装できる.
• モータサーボ
• 音声・動画の再生・キャプチャ
Copyright (C) MovingEye Inc.
■システムコールを用いる例
MovingEye Inc.
int fd;
fd = open();
art_enter();
for (;;) {
art_wait();
write(fd);
if (/* condition to finish */)
break;
}
art_exit();
アプリケーションの実行周期が, 割込ハンドラの実行周期の
整数倍なら実装できる.
openしたデバイスの割込ハンドラだけに優先度が継承され
るので, 設定する必要はない.
Copyright (C) MovingEye Inc.
■プロセス間通信を用いる例
char buf[];
write_thread()
{
art_enter(/* high priority */);
for (;;) {
art_wait();
for (int i)
buf[i] = f();
if (/* condition to finish */)
break;
}
art_exit();
}
MovingEye Inc.
read_thread()
{
art_enter(/* low priority */);
for (;;) {
art_wait();
for (int i)
g(buf[i]);
if (/* condition to finish */)
break;
}
art_exit();
}
通常のプログラミングでは, 共有データbufへのアクセス中はロック
をかける必要がある.
しかし, read_thread()の実行開始前に, write_thread()の
終了が保証されるので, ロックをかける必要はなくなる.
Copyright (C) MovingEye Inc.
■まとめ
•
ARTLinuxはハードリアルタイム処理機能を持つOSカー
ネルである.
–
–
•
割込応答時間がLinuxカーネルコードに依存しない.
タスクの周期実行の誤差が十分に小さい.
ARTLinuxはLinuxカーネルである.
–
•
MovingEye Inc.
アプリケーションのバイナリ互換性, デバイスドライバのソース互
換性がある.
周期実行基づくリアルタイムプログラミングは有効か?
URL: http://sourceforge.net/projects/art-linux/ で公開中.
Copyright (C) MovingEye Inc.