高精度カーネルタイマ hrtimer (hrtimer_nanosleep())のソースを追う

hrtimer_nanosleepはここ。
初期化後起動されるdo_nanosleepがnanosleep処理本体。
[kernel/hrtimer.c]

1580 long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
1581                const enum hrtimer_mode mode, const clockid_t clockid)
1582 {
1583     struct restart_block *restart;
1584     struct hrtimer_sleeper t;
1585     int ret = 0;
1586     unsigned long slack;
1587 
1588     slack = current->timer_slack_ns;
1589     if (rt_task(current))
1590         slack = 0;
1591 
1592     hrtimer_init_on_stack(&t.timer, clockid, mode);
1593     hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
1594     if (do_nanosleep(&t, mode))
1595         goto out;
...

hrttimer_init_sleeperでタイマが切れたあとの動作を設定している。
currentは「現在実行中の (task_struct タイプの) プロセス」を示すマクロ
[参考]→Linux プロセス管理の徹底調査
http://www.ibm.com/developerworks/jp/linux/library/l-linux-process-management/
その後、schedule()で実行権を手放している。
[kernel/hrtimer.c]

1514 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
1515 {
1516     hrtimer_init_sleeper(t, current);
1517 
1518     do {
1519         set_current_state(TASK_INTERRUPTIBLE);
1520         hrtimer_start_expires(&t->timer, mode);
1521         if (!hrtimer_active(&t->timer))
1522             t->task = NULL;
1523 
1524         if (likely(t->task))
1525             schedule();
1526 
1527         hrtimer_cancel(&t->timer);
1528         mode = HRTIMER_MODE_ABS;
1529 
1530     } while (t->task && !signal_pending(current));
1531 
1532     __set_current_state(TASK_RUNNING);
1533 
1534     return t->task == NULL;
1535 }

hrttimer_init_sleeperでは、タイマが切れたあとに実行されるコールバック関数を設定、自タスク情報を保存している。コールバック関数hrtimer_wakeupでは、保存したタスクを起床している。

1494 static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
1495 {
1496     struct hrtimer_sleeper *t =
1497         container_of(timer, struct hrtimer_sleeper, timer);
1498     struct task_struct *task = t->task;
1499 
1500     t->task = NULL;
1501     if (task)
1502         wake_up_process(task);
1503 
1504     return HRTIMER_NORESTART;
1505 }
1506 
1507 void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
1508 {
1509     sl->timer.function = hrtimer_wakeup;
1510     sl->task = task;
1511 }
1512 EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);

ハードウェアから割り込みがあってから、hrtimer_wakeupが起動されるまでの流れ、hrtimerの管理方法についても見てみたほうが良さそう。

◎hrtimerの精度について
hrtimerはtickに依存するカーネルタイマーより高精度なタイマ処理を目的に実装されたものらしい。
[参考]
高精度カーネルタイマ hrtimer のコールバックの仕組み(途中) - big-eyed-hamsterの日記
http://d.hatena.ne.jp/big-eyed-hamster/20091110/1257836767

精度の目安として、以下のようなプログラムでテストしてみた。

for (i = 0; i < 10; i++) {
        nanosleep(&req, NULL);   //1ms
        gettimeofday(&tv[i], NULL);
}

その結果。

[hoho@toto tmp]$ ./a.out
1357796057sec:947192usec
1357796057sec:948259usec
1357796057sec:949325usec
1357796057sec:950392usec
1357796057sec:951473usec
1357796057sec:952542usec
1357796057sec:953611usec
1357796057sec:954683usec
1357796057sec:955749usec
1357796057sec:956816usec

まぁ、だいたい1msくらいで来てるかな。
ちなみに、計測環境はfedora17,core i7,CPU負荷なしの状態でした。
深く考えずに作ったテキトーなソースな上に、CPU負荷とかキャッシュとかその他の考慮すべき事項はあるはずなので、この値から精度は言えないけどだいたいの目安です。
ちなみに、カーネルをビルドする時にHRTがONになっていないと、tick精度(4msくらい?)になっちゃう。

[参考]
LINUXのリアルタイム性能(周期実行の精度、前準備編) - arai9232の日記
http://d.hatena.ne.jp/arai9232/20110102/1293979908

Linux のスリープ処理、タイマ処理の詳細を見る - naoyaのはてなダイアリー
http://d.hatena.ne.jp/naoya/20080122/1200960926