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

  免費注冊 查看新帖 |

Chinaunix

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

[FreeBSD] freebsd9.2-處理器間中斷-接收處理 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2014-07-06 16:16 |只看該作者 |倒序瀏覽
[從"處理器間中斷-發(fā)送"中的描述可知]:
#define        IPI_BITMAP_VECTOR    249
#define IPI_PREEMPT          1
1:已經(jīng)給cpu5發(fā)送了一個中斷向量號為IPI_BITMAP_VECTOR的IPI。
2:并且數(shù)組元素cpu_ipi_pending[5]的第IPI_PREEMPT個bit位被設(shè)置為1。

[從"內(nèi)核如何實現(xiàn)IA32中斷處理"中的描述可知]:
中斷向量號為IPI_BITMAP_VECTOR對應(yīng)的中斷處理程序為函數(shù)IDTVEC(ipi_intr_bitmap_handler)。


此時,cpu5接收到了這個IPI,在執(zhí)行中斷處理程序IDTVEC(ipi_intr_bitmap_handler)前,cpu硬件單元要做一些處理,硬件單元所做的處理可以參考
"內(nèi)核如何實現(xiàn)IA32中斷處理"結(jié)尾的描述。

這里做下面的假設(shè):
1:接收到這個IPI時,cpu5運行在用戶態(tài)。
2:接收到這個IPI時,正在cpu5運行的線程對應(yīng)的struct thread對象簡記為cur_thread。
3:cpu硬件單元已經(jīng)完成了在執(zhí)行中斷處理程序之前的處理。

此時cpu5運行在內(nèi)核態(tài),開始執(zhí)行中斷處理程序IDTVEC(ipi_intr_bitmap_handler),線程cur_thread的內(nèi)核棧如下所示:
  1. ******************************* 內(nèi)核棧頂部 高地址方向
  2. *                             *
  3. *   struct pcb對象            *
  4. *                             *
  5. *                             *
  6. ******************************* <--cur_thread的td_pcb成員指向這里
  7. *                             *
  8. *   16bytes for vm            *        
  9. ******************************* <--cur_thread的內(nèi)核棧棧頂                        
  10. *   SS                        *
  11. *******************************
  12. *   ESP                       *
  13. *******************************
  14. *   EFLAGS                    *
  15. *******************************
  16. *   CS                        *
  17. *******************************
  18. *   EIP                       *     
  19. ******************************* <--執(zhí)行中斷處理程序IDTVEC(ipi_intr_bitmap_handler)時,esp指向這里
  20. *   SS                        *
  21. *******************************
  22. *   0                         *
  23. *******************************
  24. *   0                         *
  25. *******************************
  26. *   EAX                       *
  27. *******************************
  28. *   ECX                       *
  29. *******************************
  30. *   EDX                       *
  31. *******************************
  32. *   EBX                       *
  33. *******************************   通過struct trapframe類型的數(shù)據(jù)對象來描述
  34. *   ESP                       *
  35. *******************************
  36. *   EBP                       *
  37. *******************************
  38. *   ESI                       *
  39. *******************************
  40. *   EDI                       *
  41. *******************************
  42. *   DS                        *
  43. *******************************
  44. *   ES                        *
  45. *******************************
  46. *   FS                        *
  47. ******************************* <--宏P(guān)USH_FRAME和SET_KERNEL_SREGS執(zhí)行完后,esp指向這里
  48. *  addr(jmp        doreti)       *
  49. ******************************* <-- 執(zhí)行call ipi_bitmap_handler指令時esp指向這里
  50. *                             *
  51. *                             *
  52. *                             *
  53. *                             *
  54. *                             *
  55. *                             *
  56. *                             *
  57. *                             *
  58. *                             *
  59. *                             *
  60. *******************************------ 內(nèi)核棧底部 低地址方向
復(fù)制代碼
[IDTVEC(ipi_intr_bitmap_handler)]-中斷向量號IPI_BITMAP_VECTOR對應(yīng)的中斷處理程序:
  1.    304        IDTVEC(ipi_intr_bitmap_handler)       
  2. /*******************************************************************************
  3. * 305,宏P(guān)USH_FRAME,該宏如下所示:
  4.    將線程cur_thread的用戶態(tài)硬件上下文的一部分壓入內(nèi)核棧中。

  5.    306,宏SET_KERNEL_SREGS,如下所示:
  6.    設(shè)置內(nèi)核使用的段寄存器。

  7.    307:
  8.    清DF標(biāo)志,string operations increment the index registers (ESI and/or EDI).
  9. ******************************************************/
  10.    305                PUSH_FRAME
  11.    306                SET_KERNEL_SREGS
  12.    307                cld
  13.    308                
  14. /*******************************************************************
  15. * 309-310:
  16.    通過lapic訪問cpu5的local APIC寄存器組。

  17.    這里將對local APIC寄存器組中的EOI Register執(zhí)行一個寫操作,這是
  18.    APIC要求的,作為對這個寫操作的響應(yīng),cpu將:
  19.    Upon receiving an EOI, the APIC clears the highest
  20.    priority bit in the ISR and dispatches the next highest
  21.    priority interrupt to the processor
  22. **********************************************/
  23.    309                movl        lapic, %edx
  24.    310                movl        $0, LA_EOI(%edx)        /* End Of Interrupt to APIC */
  25.    311               
  26.    312                FAKE_MCOUNT(TF_EIP(%esp))
  27.    313       
  28. /**********************************************************************
  29. * 314:
  30.    通過上面內(nèi)核棧的布局,可以明顯的看出,函數(shù)ipi_bitmap_handler
  31.    的參數(shù)是一個struct trapframe類型的對象,而不是指向這個對象的指針。

  32.    316:
  33.    doreti函數(shù)完成返回中斷前的處理,這個暫時略過。
  34. *********************************/
  35.    314                call        ipi_bitmap_handler
  36.    315                MEXITCOUNT
  37.    316                jmp        doreti
  38.    317        #endif
復(fù)制代碼
[宏P(guān)USH_FRAME]:
  1. /*****************************************************************************************
  2. * Macros to create and destroy a trap frame.
  3.    pushal指令:
  4.    Pushes the contents of the general-purpose registers onto the stack. The registers
  5.    are stored on the stack in the following order: EAX, ECX, EDX, EBX, ESP (original
  6.    value), EBP, ESI, and EDI (if the current operand-size attribute is 32)。
  7. *********************************************/
  8.    145        #define        PUSH_FRAME                                                        \
  9.    146                pushl        $0 ;                /* dummy error code */                        \
  10.    147                pushl        $0 ;                /* dummy trap type */                        \
  11.    148                pushal ;                /* 8 ints */                                \
  12.    149                pushl        %ds ;                /* save data and extra segments ... */        \
  13.    150                pushl        %es ;                                                        \
  14.    151                pushl        %fs
復(fù)制代碼
[宏SET_KERNEL_SREGS]:
  1. /**********************************************************************************
  2. * Setup the kernel segment registers.
  3.    此時cpu5運行在內(nèi)核態(tài),段寄存器也要更改。
  4.    
  5.    173-175:
  6.    用內(nèi)核數(shù)據(jù)段的segment selector,即KDSEL加載DS,ES兩個寄存器,訪問內(nèi)核數(shù)據(jù)。

  7.    176-177:
  8.    用KPSEL加載FS寄存器,這樣就能訪問數(shù)據(jù)對象__pcpu[5],也是宏P(guān)CPU_*的基礎(chǔ)。   
  9. ******************************************/
  10.    172        #define        SET_KERNEL_SREGS                                                \
  11.    173                movl        $KDSEL, %eax ;        /* reload with kernel's data segment */        \
  12.    174                movl        %eax, %ds ;                                                \
  13.    175                movl        %eax, %es ;                                                \
  14.    176                movl        $KPSEL, %eax ;        /* reload with per-CPU data segment */        \
  15.    177                movl        %eax, %fs
復(fù)制代碼
[函數(shù)ipi_bitmap_handler]:
  1. /***********************************************************************
  2. * 參數(shù)描述:
  3.    frame:用來訪問保存在線程cur_thread內(nèi)核棧上用戶態(tài)硬件上下文。
  4. ****************************/
  5.   1355        void
  6.   1356        ipi_bitmap_handler(struct trapframe frame)
  7.   1357        {
  8. /***************************************************************************
  9. * 1360,cpu:PCPU_GET宏獲取當(dāng)前cpu的logical cpu id,這里為5.
  10. *******************************/
  11.   1358                struct trapframe *oldframe;
  12.   1359                struct thread *td;
  13.   1360                int cpu = PCPU_GET(cpuid);
  14.   1361                u_int ipi_bitmap;
  15. /**************************************************************************
  16. * 1364:td指向當(dāng)前正在運行線程的struct thread對象,這里為&cur_thread。

  17.    1365:
  18.    遞增td_intr_nesting_level,即遞增中斷嵌套層數(shù)。

  19.    1366-1367:
  20.    struct thread對象的td_intr_frame成員,freebsd8.3中沒有該成員,添加的
  21.    這個成員個人理解為,該成員在中斷處理程序中使用,用來訪問保存在線程
  22.    內(nèi)核棧上的硬件上下文。

  23.    1368:
  24.    函數(shù)atomic_readandclear_int返回數(shù)組元素cpu_ipi_pending[5]的值,然后
  25.    將其清零。
  26. *****************************/
  27.   1363                critical_enter();
  28.   1364                td = curthread;
  29.   1365                td->td_intr_nesting_level++;
  30.   1366                oldframe = td->td_intr_frame;
  31.   1367                td->td_intr_frame = &frame;
  32.   1368                ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]);
  33. /****************************************************************************
  34. * 三個特殊的IPI如下:
  35. * #define IPI_AST                0        
  36.    #define IPI_PREEMPT          1
  37.    #define IPI_HARDCLOCK        2

  38. * 1369-1386:
  39.    依次測試變量的ipi_bitmap的第1,0,2個比特位,檢查發(fā)送
  40.    的是上面三個特殊IPI的哪一個,并遞增相應(yīng)的計數(shù)器。

  41.    1369-1374:
  42.    發(fā)送的是IPI_PREEMPT,此時調(diào)用調(diào)度程序相關(guān)的sched_preempt函數(shù),當(dāng)
  43.    sched_preempt函數(shù)執(zhí)行完后,cpu5上的線程cur_thread被成功搶占。

  44.    1375-1380:
  45.    發(fā)送的是IPI_AST,此時不做處理。

  46.    1381-1386:
  47.    發(fā)送的是IPI_HARDCLOCK,此時調(diào)用函數(shù)hardclockintr。
  48. ******************************************************/
  49.   1369                if (ipi_bitmap & (1 << IPI_PREEMPT)) {
  50.   1370        #ifdef COUNT_IPIS
  51.   1371                        (*ipi_preempt_counts[cpu])++;
  52.   1372        #endif
  53.   1373                        sched_preempt(td);
  54.   1374                }
  55.   1375                if (ipi_bitmap & (1 << IPI_AST)) {
  56.   1376        #ifdef COUNT_IPIS
  57.   1377                        (*ipi_ast_counts[cpu])++;
  58.   1378        #endif
  59.   1379                        /* Nothing to do for AST */
  60.   1380                }
  61.   1381                if (ipi_bitmap & (1 << IPI_HARDCLOCK)) {
  62.   1382        #ifdef COUNT_IPIS
  63.   1383                        (*ipi_hardclock_counts[cpu])++;
  64.   1384        #endif
  65.   1385                        hardclockintr();
  66.   1386                }
  67. /********************************************************
  68. * 1387:將td_intr_frame成員恢復(fù)到之前的值。
  69.    1388:遞減td_intr_nesting_level,即中斷嵌套數(shù)減1.
  70. *******************************/
  71.   1387                td->td_intr_frame = oldframe;
  72.   1388                td->td_intr_nesting_level--;
  73.   1389                critical_exit();
  74.   1390        }
復(fù)制代碼
[ULE線程調(diào)度-sched_preempt函數(shù)]:
  1. /*******************************************************************
  2. * 函數(shù)sched_preempt就是調(diào)用mi_switch函數(shù)執(zhí)行一個線程切換,執(zhí)行
  3.    完后,線程cur_thread被成功搶占。

  4.    2130:tdq此時為&tdq_cpu[5].
  5.    2132:將tdq_ipipending設(shè)置為0,表示相應(yīng)的IPI已經(jīng)處理。

  6.    2133-2143:
  7.    再次檢查是否需要搶占線程cur_thread,這里簡單的比較兩個優(yōu)先級。
  8.    如果需要搶占,就設(shè)置合適的標(biāo)志來調(diào)用mi_switch函數(shù)完成線程切換。
  9. ***********************************/
  10.   2122        void
  11.   2123        sched_preempt(struct thread *td)
  12.   2124        {
  13.   2125                struct tdq *tdq;
  14.   2126       
  15.   2127                SDT_PROBE2(sched, , , surrender, td, td->td_proc);
  16.   2128       
  17.   2129                thread_lock(td);
  18.   2130                tdq = TDQ_SELF();
  19.   2131                TDQ_LOCK_ASSERT(tdq, MA_OWNED);
  20.   2132                tdq->tdq_ipipending = 0;
  21.   2133                if (td->td_priority > tdq->tdq_lowpri) {
  22.   2134                        int flags;
  23.   2135       
  24.   2136                        flags = SW_INVOL | SW_PREEMPT;
  25.   2137                        if (td->td_critnest > 1)
  26.   2138                                td->td_owepreempt = 1;
  27.   2139                        else if (TD_IS_IDLETHREAD(td))
  28.   2140                                mi_switch(flags | SWT_REMOTEWAKEIDLE, NULL);
  29.   2141                        else
  30.   2142                                mi_switch(flags | SWT_REMOTEPREEMPT, NULL);
  31.   2143                }
  32.   2144                thread_unlock(td);
  33.   2145        }]
復(fù)制代碼
您需要登錄后才可以回帖 登錄 | 注冊

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

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP