セマフォの解放
セマフォの解放は簡単です。up関数が呼ばれて、取得の時と同じようにspin_lock_irqsave関数で、スピンロックおよび割り込み禁止して、まずlist_empty関数でセマフォ待ちタスクがないか調べます。sem->wait_listが待ちリストの先頭リストで、sem->wait_list->next==sem->wait_listなら待ちリスト無し。ということで、sem->count++でセマフォを解放しておしまいです。(セマフォ取得時はsem->count--)待ちリストが空でない場合、__up関数を呼び出します。
try_to_wake_up関数は指定したタスクのウエイクアップする処理ですが、マルチプロセス処理ではプロセス間のロードバランス処理でかなり複雑です。まあ要は、指定したタスクをランキューキューにつないで、そのタスクの状態をTASK_RUNNINGにすることのようです。ウエイトキューからの削除はウエイクアップされるタスクが実行された時に、そのタスク自身で行うようになっています。なぜ「try_to_wake_up関数でウエイトキューからの削除まで行わないのかな?」って調べてもわかりません。で勝手な解釈で、なんらかしかのステイタス情報の統計を取得する上で、このウエイトキューを参照する場合があるのだろうと。そうなると、このタスク動作できる状態になったわけで、実行権がうつるまで動作してないわけですから、ステイタス情報の統計を取得上での都合なのかなって。
void up(struct semaphore *sem) { unsigned long flags; spin_lock_irqsave(&sem->lock, flags); if (likely(list_empty(&sem->wait_list))) sem->count++; else __up(sem); spin_unlock_irqrestore(&sem->lock, flags); }up関数では、待ちリストの先頭項目を取得し、その項目を待ちリストから削除し、waiter->up = 1そして、wake_up_process関数でそのタスクを、TASK_RUNNING状態としてウエイクアップします。セマフォ取得でセマフォ取得待ちタスクでは、schedule_timeout関数を挟んで、waiter->up=1となるまでループしていました。まさにwaiter->up = 1することで、セマフォ待ちしているタスクに実行権が移ると、セマフォが取得できて、めでたしめでたし。ということのようです。
static noinline void __sched __up(struct semaphore *sem) { struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list, struct semaphore_waiter, list); list_del(&waiter->list); waiter->up = 1; wake_up_process(waiter->task); }
追伸
__up関数で、__schedマクロが付いています。実は___down関数にも付いていました。これは以下のようになっていて、なにやらこの関数はセクションとして.sched.textにロケーションされるようで・・・。コメントみるとwchan出力では表示しない。ようなことが書いてありますが・・・。たぶんps等でwchanで表示する場合セマフォ待ちのタスクは本関数の表示をさせないようにするため、そのような関数をまとめて配置させたら、そのアドレステーブルを作成したりとか処理上なんか都合がいいのでしょうね。よく分かりませんが。* Attach to any functions which should be ignored in wchan output. */ #define __sched __attribute__((__section__(".sched.text")))
try_to_wake_up関数は指定したタスクのウエイクアップする処理ですが、マルチプロセス処理ではプロセス間のロードバランス処理でかなり複雑です。まあ要は、指定したタスクをランキューキューにつないで、そのタスクの状態をTASK_RUNNINGにすることのようです。ウエイトキューからの削除はウエイクアップされるタスクが実行された時に、そのタスク自身で行うようになっています。なぜ「try_to_wake_up関数でウエイトキューからの削除まで行わないのかな?」って調べてもわかりません。で勝手な解釈で、なんらかしかのステイタス情報の統計を取得する上で、このウエイトキューを参照する場合があるのだろうと。そうなると、このタスク動作できる状態になったわけで、実行権がうつるまで動作してないわけですから、ステイタス情報の統計を取得上での都合なのかなって。