一個程序被喚醒,在linux中是調用try_to_wake_up函數,對于RT程序也不例外,對于一般程序而言,如果在一個cpu運作隊列上被喚醒的程序的優先級大于該cpu的目前程序,那麼就會發生搶占,而如果兩個程序都是RT程序則不會發生搶占,理由是cache的保持,如果發生搶占的話,被搶占的RT程序将丢失其所有的cache,可是這樣做合理嗎?
先看一下RT程序的特征,這種程序一旦運作,除非自願放棄cpu,一般是不會停止運作的,對于高優先級的RT程序總是優先運作,如果對于RT程序為了保持cache不搶占的話,除了cache的保持之外,其實是得不到任何優勢的,并且,在這種情況下還會造成RT程序的乒乓效應,也就是造成RT程序頻繁遷移,在很多RT程序争搶一個資源,比如lock的情況下,這種乒乓效應帶來的弊端更加明顯,低優先級的RT程序釋放了lock,喚醒了高優先級的RT程序,由于此時目前cpu上的程序仍然是低優先級的程序,所有被喚醒的高優先級程序不得不被遷移到别的cpu上執行,如果低優先級的程序沒有釋放資源,而由于另一個原因睡眠了,此時它的優先級可能已被提升,當它再度被另一RT程序喚醒的時候,即使它擁有高優先級也不得不遷移到另外的cpu上,這些遷移動作肯定會影響性能的。可以說,RT程序排程的無條件不搶占特性大大削弱了高優先級RT程序的優勢,高優先級RT程序除了在運作隊列的位置靠前之外,沒有多少優勢可言了。
确實,如果是由于非争搶資源被釋放原因的喚醒,那搶占正在運作的rt程序确實對于cache優化是一種抵消,然而要知道即使這樣我們也隻是損失了相對低優先級rt程序的性能,我們得到的是避免了一次高優先級rt程序的遷移。另一方面,當我們面對多個rt程序争搶資源這種類型的睡眠/喚醒時,搶占的優勢就明顯了,有時一個又有很高優先級的rt程序在運作中由于得不到資源而睡眠,這種睡眠時間一般不會太久,隻是一小會兒,它争搶的資源此時正在被一個低優先級的rt程序占據,此時它提升低優先級程序的優先級,以使它不被搶占地盡快完成資源的釋放,這一切都是為了高優先級程序不會睡得太久,于是資源盡可能早的被釋放了,高優先級程序被喚醒,此時應該知道,将此高優先級rt程序喚醒在它本來運作的cpu上是一個最佳的選擇。
這就是一個權衡的問題了,是保留cache還是最小化遷移,還是交給排程器吧,嚴格按照優先級排程會好一些,起碼能照顧高優先級的RT程序,使得高優先級的RT程序的優勢更加明顯。于是,新的2.6.37核心對此進行了改進,更新檔很簡單:
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -960,18 +960,18 @@ select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
if (unlikely(rt_task(rq->curr)) &&
+ rq->curr->prio < p->prio &&
(p->rt.nr_cpus_allowed > 1)) {
int cpu = find_lowest_rq(p);
@@ -1491,6 +1491,8 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
if (!task_running(rq, p) &&
!test_tsk_need_resched(rq->curr) &&
has_pushable_tasks(rq) &&
+ rt_task(rq->curr) &&
p->rt.nr_cpus_allowed > 1)
push_rt_tasks(rq);
}
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271146