亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 26523 | 回復: 3
打印 上一主題 下一主題

[FreeBSD] freebsd9.2-ULE線程調度-保持cpu運行隊列間的平衡-sched_balance函數 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2014-06-29 23:02 |只看該作者 |倒序瀏覽
本帖最后由 71v5 于 2014-06-30 01:33 編輯

從帖子"freebsd9.2-何時調用mini_switch函數-線程時間片用完"的描述中可知,當statclock超時后,statclock_cnt函數
會調用調度程序相關的sched_clock函數進行相應的處理,sched_clock函數的一個任務就是檢查是否需要調用函數
sched_balance在cpu的運行隊列間遷移thread,以保持cpu運行隊列間的平衡,這里再摘取相關的代碼,這樣就會更清晰:
  1.   2174        /*
  2.   2175         * Handle a stathz tick.  This is really only relevant for timeshare
  3.   2176         * threads.
  4.   2177         */
  5.   2178        void
  6.   2179        sched_clock(struct thread *td)
  7.   2180        {
  8.   2181                struct tdq *tdq;
  9.   2182                struct td_sched *ts;
  10.   2183                /* 2185:tdq指向當前cpu對應的struct tdq對象 */
  11.   2184                THREAD_LOCK_ASSERT(td, MA_OWNED);
  12.   2185                tdq = TDQ_SELF();
  13.   2186        #ifdef SMP
  14.   2187                /***********************************************************************
  15.   2188                 * We run the long term load balancer infrequently on the first cpu.

  16.                    static struct tdq       *balance_tdq;
  17.                    static int balance_ticks;

  18.                    2190-2193:
  19.                    在ULE調度程序初始化階段,BSP會將balance_tdq設置為BSP對應的struct tdq
  20.                    數據對象的地址。
  21.                   
  22.                    balance_ticks為調用sched_balance函數在系統(tǒng)中cpu的運行隊列間遷移線程
  23.                    的周期,在ULE調度程序初始化階段設置,具體值是多少應該沒什么意義:
  24.                    balance_interval默認值為128.
  25.                    balance_ticks = max(balance_interval / 2, 1);
  26.                    balance_ticks += random() % balance_interval;

  27.                    當balance_ticks為零0時,函數sched_balance就要保持系統(tǒng)中cpu運行隊列
  28.                    間的平衡。

  29.                    只在BSP上執(zhí)行。
  30.   2189                 *************/
  31.   2190                if (balance_tdq == tdq) {
  32.   2191                        if (balance_ticks && --balance_ticks == 0)
  33.   2192                                sched_balance();
  34.   2193                }
  35. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  36. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  37.        }
復制代碼
這里為了簡化分析,做下面的假設:
1:系統(tǒng)中有兩個物理cpu,每個cpu有4個物理核心,logical cpu id分別為0,1,2,3,4,5,6,7,后面就
以cpu0,cpu1,cpu2等等標識這些logical cpu,其對應的運行隊列分別記為tdq_cpu[0],tdq_cpu[1],tdq_cpu[2]
,tdq_cpu[3]等等。

2:cpuset_t類型的大小為1字節(jié),并且bit位以從左到右的順序編號,那么:
   對于一個cpuset_t類型的cpumask變量,如果其編碼為11111111, 如果某個bit位設置為1,那么該bit位對應的cpu
   就被檢查,比如如果bit0被設置為1,就要檢查cpu0。


這里先簡要分析一下sched_lowest函數,大家可以參照sched_highest函數的分析看看sched_lowest函數到底怎么工作的。
[函數sched_lowest]:
  1. /******************************************************************************************
  2. * Find the cpu with the least load via the least loaded path that has a
  3. * lowpri greater than pri  pri.  A pri of -1 indicates any priority is
  4. * acceptable.
  5. *
  6.    參數描述:
  7.    cg:所要檢查的cpu_group。
  8.    mask:將要檢查的cpu集合。
  9.    pri: 該參數可以忽略。
  10.    maxload:該參數比較重要,一般設置為上一次調用函數sched_highest返回的cpu運行
  11.             隊列最高的cpu的的負載,在確定cpu運行隊列負載最小的cpu時,只有當
  12.             相應cpu運行隊列的負載小于或者等于maxload才會被檢查。
  13.    prefer: 上一次調用函數sched_highest返回的cpu的logical cpu id,當所檢查的
  14.             cpu和prefer相同時,將prefer運行隊列的負載減去一個常數。
  15.    
  16.    函數返回值:
  17.    -1:表示期間創(chuàng)建了好多thread,這些thread被添加到了cpu的運行隊列中,導致所檢查的
  18.        cpu運行隊列的負載都比maxload高。

  19.    非零:運行隊列負載最低的cpu的logical cpu id。

  20.    其實只要這些參數的含義弄明白,下來就是就是一些簡單的分析過程了。
  21. ************************************/
  22.    744        static inline int
  23.    745        sched_lowest(const struct cpu_group *cg, cpuset_t mask, int pri, int maxload,
  24.    746            int prefer)
  25.    747        {
  26.    748                struct cpu_search low;
  27.    749       
  28.    750                low.cs_cpu = -1;
  29.    751                low.cs_prefer = prefer;
  30.    752                low.cs_mask = mask;
  31.    753                low.cs_pri = pri;
  32.    754                low.cs_limit = maxload;
  33.    755                cpu_search_lowest(cg, &low);
  34.    756                return low.cs_cpu;
  35.    757        }
  36.    716  /*
  37.    717   * cpu_search instantiations must pass constants to maintain the inline
  38.    718   * optimization.
  39.    719   */
  40.    720  int
  41.    721  cpu_search_lowest(const struct cpu_group *cg, struct cpu_search *low)
  42.    722  {
  43.    723          return cpu_search(cg, low, NULL, CPU_SEARCH_LOWEST);
  44.    724  }
復制代碼
[ULE調度程序-sched_balance函數]:
  1.    842        static void
  2.    843        sched_balance(void)
  3.    844        {
  4.    845                struct tdq *tdq;
  5.    846       
  6.    847       
  7.    848
  8.    849
  9.    850
  10. /****************************************************************************************
  11. * Select a random time between .5 * balance_interval and
  12. * 1.5 * balance_interval.
  13. *
  14. * 變量reblance:表示是否要進行cpu運行隊列間的再平衡,初始值為1,可以通過
  15. * sysctl系統(tǒng)調用來更改。
  16. * static int rebalance = 1;

  17.    851-852:重新計算balance_ticks。
  18.    
  19.    853:如果不是SMP系統(tǒng)或者變量rebalance為0,就直接返回,因為沒有必要進行
  20.         cpu運行隊列的再平衡操作。
  21.    
  22.    855:因為只有BSP執(zhí)行sched_balance函數,而BSP的logical cpu id為0,所以
  23.         這里tdq的值就為&tdq_cpu[0]。
  24.    
  25.    857:以參數cpu_top調用函數sched_balance_group
  26.         參數cpu_top請參考帖子"freebsd9.2-ULE線程調度-創(chuàng)建數據結構來描述CPU拓撲信息"
  27. **************************/
  28.    851                balance_ticks = max(balance_interval / 2, 1);
  29.    852                balance_ticks += random() % balance_interval;
  30.    853                if (smp_started == 0 || rebalance == 0)
  31.    854                        return;
  32.    855                tdq = TDQ_SELF();
  33.    856                TDQ_UNLOCK(tdq);
  34.    857                sched_balance_group(cpu_top);
  35.    858                TDQ_LOCK(tdq);
  36.    859        }
復制代碼
[函數sched_balance_group]:
  1.    798        static void
  2.    799        sched_balance_group(struct cpu_group *cg)
  3.    800        {
  4. /********************************************************************************
  5. * 局部變量描述:
  6.    hamsk:在調用函數sched_highest檢查運行隊列負載最高的cpu時使用,該變量是一個
  7.           cpu位圖的集合,設置為1的bit位對應的cpu都會被檢查。

  8.    lmask:類似于hamsk,在檢查運行隊列負載最低的cpu時使用。

  9.    high:運行隊列負載最高的cpu的logical cpu id。
  10.    low:運行隊列負載最低的cpu的logical cpu id。
  11. **************************************/
  12.    801                cpuset_t hmask, lmask;
  13.    802                int high, low, anylow;
  14.    803       
  15. /***************************************************************************************************
  16. * 804:for循環(huán)前,將變量hmask的bit位全設置為1,表示檢查系統(tǒng)中全部的cpu。

  17.    805-839:一個無限for循環(huán),當下面任何一個條件滿足時,中止for循環(huán):
  18.    條件1:函數sched_highest返回值為-1,在一般情況下,如果返回值為-1,就表示所
  19.           檢查cpu運行隊列中可遷移thread的數目為0。

  20.    條件2:變量lmask中的bit位全部為0,表示沒有要檢查的cpu。

  21.    條件3:anylow變量為1,并且函數sched_lowest返回值為-1。

  22.    810:如果執(zhí)行到這里,就表示函數sched_highest執(zhí)行成功,這里假設函數sched_highest
  23.         返回值為6(high值為6),即cpu6的運行隊列tdq_cpu[6]的負載最高,宏CPU_CLR將變量hmask中的bit6
  24.         清零,這就意味著下一次調用sched_highest函數時將不會檢查cpu6。

  25.    811:將更新后的hmask變量copy到lmask變量中,函數sched_lowest將檢查lmask變量中包含
  26.         的cpu運行隊列的負載,選擇一個負載最低的cpu。

  27.    813-815:當變量lmask為空時,即變量lmask中的bit位全為零,表示沒有要檢查的cpu,此時
  28.             調用函數sched_lowest沒有意義,跳出for循環(huán)。

  29.    817-818:調用函數sched_lowest確定cpu運行隊列負載最低的cpu,這里假設函數sched_lowest的返回值
  30.             為2(low值為2),即cpu2的運行隊列tdq_cpu[2]的負載最低。

  31.    820-821:對應上面的條件3。
  32.   
  33.    823-824:當函數sched_lowest返回-1時,此時繼續(xù)for循環(huán),如果期間一些thread意外終止或者
  34.             主動執(zhí)行了exit操作,那么下一次檢查時,sched_lowest函數有可能返回有意義的值。

  35.    825-828:執(zhí)行到這里話,high為負載最高的cpu,low為負載最低的cpu,此時函數
  36.             sched_balance_pair執(zhí)行一個將thread從運行隊列tdq_cpu[6]遷移到運行隊列tdq_cpu[2]
  37.             中的操作,以下面的形式調用函數:
  38.             sched_balance_pair(&tdq_cpu[6], &tdq_cpu[2]);  
  39.    
  40.    826-828:如果函數sched_balance_pair返回1,將變量hmask中的bit2清零,這意味著下次for循環(huán)時將
  41.             不會檢查cpu6和cpu2。

  42.    830-837:如果函數sched_balance_pair返回0,此時將變量lmask中的bit2清零,同時將變量anylow
  43.             設置為0,跳轉到nextlow處繼續(xù)執(zhí)行,繼續(xù)確定下一個運行隊列負載最低的cpu。
  44. ***********************/
  45.    804                CPU_FILL(&hmask);
  46.    805                for (;;) {
  47.    806                        high = sched_highest(cg, hmask, 1);
  48.    807                        /* Stop if there is no more CPU with transferrable threads. */
  49.    808                        if (high == -1)
  50.    809                                break;
  51.    810                        CPU_CLR(high, &hmask);
  52.    811                        CPU_COPY(&hmask, &lmask);
  53.    812                        /* Stop if there is no more CPU left for low. */
  54.    813                        if (CPU_EMPTY(&lmask))
  55.    814                                break;
  56.    815                        anylow = 1;
  57.    816        nextlow:
  58.    817                        low = sched_lowest(cg, lmask, -1,
  59.    818                            TDQ_CPU(high)->tdq_load - 1, high);
  60.    819                        /* Stop if we looked well and found no less loaded CPU. */
  61.    820                        if (anylow && low == -1)
  62.    821                                break;
  63.    822                        /* Go to next high if we found no less loaded CPU. */
  64.    823                        if (low == -1)
  65.    824                                continue;
  66.    825                        /* Transfer thread from high to low. */
  67.    826                        if (sched_balance_pair(TDQ_CPU(high), TDQ_CPU(low))) {
  68.    827                                /* CPU that got thread can no longer be a donor. */
  69.    828                                CPU_CLR(low, &hmask);
  70.    829                        } else {
  71.    830                                /*
  72.    831                                 * If failed, then there is no threads on high
  73.    832                                 * that can run on this low. Drop low from low
  74.    833                                 * mask and look for different one.
  75.    834                                 */
  76.    835                                CPU_CLR(low, &lmask);
  77.    836                                anylow = 0;
  78.    837                                goto nextlow;
  79.    838                        }
  80.    839                }
  81.    840        }
復制代碼
[函數sched_balance_pair]-負責在兩個運行隊列間遷移thread:
  1. /********************************************************************
  2. * Transfer load between two imbalanced thread queues.
  3. *
  4.    參數描述:
  5.    high:負載最高的運行隊列,這里為tdq_cpu[6]。
  6.    low: 負載最低的運行隊列,這里為tdq_cpu[2]。

  7.    sched_balance_pair函數返回值的含義請參考一下下面對tdq_move函數
  8.    返回值的分析。
  9. ****************************/
  10.    889        static int
  11.    890        sched_balance_pair(struct tdq *high, struct tdq *low)
  12.    891        {
  13. /*********************************************************************************
  14. * 局部變量描述:
  15.    moved:可以遷移的thread的數目。
  16.    cpu:運行隊列l(wèi)ow對應的cpu的logical cpu id。

  17.    901-912:再次檢查遷移條件是否滿足,tdq_move函數見下面的分析。
  18.   
  19.    一般情況下if語句的前兩個條件都滿足,此時:

  20.    在函數tdq_move返回1時,檢查是否需要向運行隊列l(wèi)ow對應的cpu發(fā)出一個處理器間
  21.    中斷(IPI),后續(xù)有時間的話,將和大家分享一下處理器間中斷的發(fā)送過程以及相關
  22.    的處理。
  23. *******************************************/  
  24.    892                int moved;
  25.    893                int cpu;
  26.    894       
  27.    895                tdq_lock_pair(high, low);
  28.    896                moved = 0;
  29.    897                /*
  30.    898                 * Determine what the imbalance is and then adjust that to how many
  31.    899                 * threads we actually have to give up (transferable).
  32.    900                 */
  33.    901                if (high->tdq_transferable != 0 && high->tdq_load > low->tdq_load &&
  34.    902                    (moved = tdq_move(high, low)) > 0) {
  35.    903                        /*
  36.    904                         * In case the target isn't the current cpu IPI it to force a
  37.    905                         * reschedule with the new workload.
  38.    906                         */
  39.    907                        cpu = TDQ_ID(low);
  40.    908                        sched_pin();
  41.    909                        if (cpu != PCPU_GET(cpuid))
  42.    910                                ipi_cpu(cpu, IPI_PREEMPT);
  43.    911                        sched_unpin();
  44.    912                }
  45.    913                tdq_unlock_pair(high, low);
  46.    914                return (moved);
  47.    915        }
復制代碼
[函數tdq_move]:
  1. /*****************************************************************
  2. * Move a thread from one thread queue to another.
  3. *
  4.    參數描述:
  5.    from:線程將要從運行隊列from中移除。
  6.    to:線程將要添加到運行隊列to中。

  7.    根據函數的描述,tdq_move一次將只遷移一個thread,太可憐了吧,
  8.    之前看linux-2.6.18線程調度這塊實現時,都可以遷移一定數目的
  9.    thread了,不過bsd開發(fā)者可能有他們自己的想法,這里就是簡要
  10.    的點評一下。

  11.    下面簡要的分析一下tdq_move函數,后續(xù)有時間將和大家分享一下
  12.    如何將一個thread添加到運行隊列中,以及如何將一個thread從一個
  13.    運行隊列中移除。

  14.    這里只需要明白返回值的含義:
  15.    
  16.    0:運行隊列from中的thread不能遷移到運行隊列to中。

  17.    1:成功將一個thread從運行隊列from遷移到運行隊列to中。

  18. ************************/
  19.    920        static int
  20.    921        tdq_move(struct tdq *from, struct tdq *to)
  21.    922        {
  22.    923                struct td_sched *ts;
  23.    924                struct thread *td;
  24.    925                struct tdq *tdq;
  25.    926                int cpu;
  26.    927       
  27.    928                TDQ_LOCK_ASSERT(from, MA_OWNED);
  28.    929                TDQ_LOCK_ASSERT(to, MA_OWNED);
  29.    930       
  30. /******************************************************************
  31. * cpu:運行隊列to對應的cpu的logical cpu id。

  32.    描述thread的struct thread對象有下面一個成員:
  33.    td_cpuset:cpu掩碼的集合,即CPU affinity sets,一般情況下
  34.               該字段的值從父進程繼承,除非調用cpuset系統(tǒng)調用
  35.               進行修改,即線程thread只能在在td_cpuset中的cpu
  36.               上運行或者說成線程thread只能被添加到td_cpuset中的cpu
  37.               的運行隊列中。
  38.    函數tdq_steal依次檢查tdq_realtime,tdq_timeshare,tdq_idle
  39.    隊列中的全部thread,如果描述每個thread的struct thread對象
  40.    中的td_cpuset成員標識的cpu集合中都不包括運行隊列to對應的cpu,
  41.    那么函數tdq_steal將返回NULL,此時tdq_move函數返回0.
  42.    否則函數tdq_steal將返回描述一個線程的struct thread對象,此時
  43.    此時tdq_move函數返回1.

  44.    941-947:將線程td從運行隊列from中移除,同時將線程td添加到
  45.             運行隊列to中,以及更新線程td對應的struct thread對象
  46.             中的相關成員。  
  47. ******************************/   
  48.    931                tdq = from;
  49.    932                cpu = TDQ_ID(to);
  50.    933                td = tdq_steal(tdq, cpu);
  51.    934                if (td == NULL)
  52.    935                        return (0);
  53.    936                ts = td->td_sched;
  54.    937                /*
  55.    938                 * Although the run queue is locked the thread may be blocked.  Lock
  56.    939                 * it to clear this and acquire the run-queue lock.
  57.    940                 */
  58.    941                thread_lock(td);
  59.    942                /* Drop recursive lock on from acquired via thread_lock(). */
  60.    943                TDQ_UNLOCK(from);
  61.    944                sched_rem(td);
  62.    945                ts->ts_cpu = cpu;
  63.    946                td->td_lock = TDQ_LOCKPTR(to);
  64.    947                tdq_add(to, td, SRQ_YIELDING);
  65.    948                return (1);
  66.    949        }
復制代碼

論壇徽章:
0
2 [報告]
發(fā)表于 2015-04-13 18:31 |只看該作者
支持一下辛苦的樓主~頂了!

論壇徽章:
0
3 [報告]
發(fā)表于 2015-04-25 15:34 |只看該作者
我老媽很喜歡李宇春呢。。。。。。

論壇徽章:
0
4 [報告]
發(fā)表于 2015-04-30 17:03 |只看該作者
林子大了什么鳥沒有啊?祝踩的死全家!。。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯網協會會員  聯系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP