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

  免費注冊 查看新帖 |

Chinaunix

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

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

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2014-07-06 01:05 |只看該作者 |倒序瀏覽
有了前面"內(nèi)核如何實現(xiàn)IA32中斷處理"中的內(nèi)容作為準(zhǔn)備,依然將處理器間中斷簡稱為IPI,下面結(jié)合ULE線程調(diào)度來看一下IPI的發(fā)送過程。

先來看一下需要用到的數(shù)據(jù)結(jié)構(gòu):

[數(shù)組cpu_ipi_pending]-用來處理IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個特殊的IPI:
  1. /*****************************************************************************
  2. * Holds pending bitmap based IPIs per CPU 。
  3.    
  4.    數(shù)組cpu_ipi_pending和下面的IPI中斷向量號結(jié)合起來理解會更清楚:

  5.    #define        IPI_BITMAP_VECTOR        249

  6.    對于下面三個IPI的描述為"IPIs handled by IPI_BITMAPED_VECTOR":
  7.    #define IPI_AST                0        
  8.    #define IPI_PREEMPT          1
  9.    #define IPI_HARDCLOCK        2

  10.    IPI_AST:忽略,內(nèi)核中的描述"Nothing to do for AST"。

  11.    IPI_PREEMPT:需要搶占時發(fā)送。
  12.    
  13.    IPI_HARDCLOCK:
  14.    在SMP系統(tǒng)中,只有BSP上的APIC TIMER啟用,而其余AP上的APIC TIMER沒有啟用
  15.    時,當(dāng)BSP上的APIC TIMER超時后,就會向其余AP發(fā)送一個IPI_HARDCLOCK
  16.    類型的IPI。
  17.   
  18.    由此看見,當(dāng)發(fā)送類型為IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK的IPI時,
  19.    其實是通過中斷向量號為IPI_BITMAP_VECTOR對應(yīng)的中斷處理程序來處理的,
  20.    那么就需要通過一種方法,該方法能夠設(shè)置一個標(biāo)志,中斷向量號為
  21.    IPI_BITMAP_VECTOR對應(yīng)的中斷處理程序通過檢查相應(yīng)的標(biāo)志來確定發(fā)送的
  22.    是IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個IPI的哪一個,這個這個方法
  23.    就是使用數(shù)組cpu_ipi_pending。

  24.    系統(tǒng)中每個cpu在數(shù)組cpu_ipi_pending中都有相應(yīng)的元素,logical cpu id
  25.    作為數(shù)組cpu_ipi_pending的索引。

  26.    假設(shè)系統(tǒng)中某個cpu的logical cpu id為1,那么當(dāng)該cpu接收到一個
  27.    中斷向量號為IPI_BITMAP_VECTOR的中斷時,相應(yīng)的中斷處理程序就會檢查
  28.    數(shù)組元素cpu_ipi_pending[1]中IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK對應(yīng)
  29.    的bit位是否被設(shè)置為1,如果是,就進行相應(yīng)的處理。設(shè)置為1的任務(wù)由
  30.    發(fā)送IPI的cpu來完成。

  31.    通過上面的描述,可以看出,數(shù)組cpu_ipi_pending用來描述系統(tǒng)中某個cpu
  32.    是否有掛起的IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK的IPI。
  33. ********************************************/
  34.    198  static volatile u_int cpu_ipi_pending[MAXCPU];
復(fù)制代碼
[和IPI計數(shù)器相關(guān)的數(shù)組]-對cpu上接收到的IPI進行計數(shù):
  1. /*******************************************************************************
  2. * 只有在編譯內(nèi)核時選擇了COUNT_IPIS選項,下面的描述才有效。

  3.    161-169:
  4.    下面的數(shù)組對IPI進行計數(shù),每個數(shù)組都對應(yīng)一個IPI類型。
  5.    對于某一個特定數(shù)組,這里假設(shè)為數(shù)組數(shù)組ipi_invltlb_counts,系統(tǒng)中每個cpu
  6.    都在ipi_invltlb_counts數(shù)組中有相應(yīng)的元素,數(shù)組的索引為logical cpu id。

  7.    對于cpu0,當(dāng)cpu0接收到一個類型為IPI_INVLTLB的IPI時,相應(yīng)的中斷處理程序
  8.    就會遞增*ipi_invltlb_counts[0].


  9.    u_long intrcnt[INTRCNT_COUNT];
  10.    char intrnames[INTRCNT_COUNT * (MAXCOMLEN + 1)];
  11.    
  12.    初始化函數(shù)mp_ipi_intrcnt完成兩個主要任務(wù):
  13.    1:用intrcnt數(shù)組元素的地址初始化下面的指針數(shù)組。
  14.    2:使用類似"cpu%d:invltlb"這樣的字符串初始化上面的intrname數(shù)組,這里的%d
  15.       為cpu的logical cpu id。
  16. *********************************************/
  17.    161  static u_long *ipi_preempt_counts[MAXCPU];
  18.    162  static u_long *ipi_ast_counts[MAXCPU];
  19.    163  u_long *ipi_invltlb_counts[MAXCPU];
  20.    164  u_long *ipi_invlrng_counts[MAXCPU];
  21.    165  u_long *ipi_invlpg_counts[MAXCPU];
  22.    166  u_long *ipi_invlcache_counts[MAXCPU];
  23.    167  u_long *ipi_rendezvous_counts[MAXCPU];
  24.    168  u_long *ipi_lazypmap_counts[MAXCPU];
  25.    169  static u_long *ipi_hardclock_counts[MAXCPU];
復(fù)制代碼
[數(shù)組cpu_apic_ids和apic_cpuids]:
  1. /******************************************************************************************
  2. * #define        MAX_APIC_ID        0xfe
  3.    #define MAXCPU                32

  4.    下面兩個數(shù)組都是由函數(shù)assign_cpu_ids初始化的,該函數(shù)在初始化函數(shù)cpu_mp_start中被調(diào)用。

  5.    數(shù)組cpu_apic_ids的索引為logical cpu id,相應(yīng)數(shù)組元素的值為cpu的local APIC ID。
  6.    數(shù)組apic_cpuids的索引為cpu的local APIC ID,相應(yīng)數(shù)組元素的值為cpu的logical cpu id。  
  7. ********************************************/
  8.    194        int cpu_apic_ids[MAXCPU];
  9.    195        int apic_cpuids[MAX_APIC_ID + 1];
復(fù)制代碼
[struct tdq對象中的tdq_ipipending成員]:
  1. /******************************************************************************
  2. * tdq - per processor runqs and statistics.  All fields are protected by the
  3. * tdq_lock.  The load and lowpri may be accessed without to avoid excess
  4. * locking in sched_pickcpu();
  5.    對于SMP系統(tǒng):
  6.    每個cpu對應(yīng)的一個struct tdq數(shù)據(jù)對象,數(shù)組tdq_cpu以cpu的logical id為索引。
  7.    static struct tdq       tdq_cpu[MAXCPU];

  8.    對于非SMP系統(tǒng):
  9.    系統(tǒng)中只定義了一個struct tdq數(shù)據(jù)對象。
  10.    static struct tdq       tdq_cpu;

  11.    tdq_ipipending:表示是否有掛起的IPI。
  12. *****************************************************/
  13.    225  struct tdq {
  14. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  15.    236          u_char          tdq_ipipending;         /* IPI pending. */
  16. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  17.    246  } __aligned(64);
復(fù)制代碼
根據(jù)之前sched_add函數(shù)的描述,當(dāng)把一個線程td添加到系統(tǒng)中某個cpu(假設(shè)為cpu5)的運行隊列時,就會檢查td是否能夠搶占當(dāng)前
正在cpu5上運行的線程,如果可以搶占,就要給cpu5發(fā)送一個IPI。
[摘取sched_add函數(shù)的部分代碼]:
  1. /**************************************************************************************
  2. * Select the target thread queue and add a thread to it.  Request
  3. * preemption or IPI a remote processor if required.

  4.    參數(shù)描述:

  5.    td:標(biāo)識將要被添加到cpu運行隊列中的線程。

  6.    flags:傳遞給函數(shù)sched_add的標(biāo)志,相關(guān)標(biāo)志需要結(jié)合上下文分析,這里暫且略過。
  7. **************************************/
  8.   2342        
  9.   2343        void
  10.   2344        sched_add(struct thread *td, int flags)
  11.   2345        {
  12. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  13. /***************************************************************************************
  14. * 2365-2377:SMP系統(tǒng)
  15. *
  16. * Pick the destination cpu and if it isn't ours transfer to the
  17. * target cpu.

  18.    2370:函數(shù)sched_pickcpu為線程td挑選一個合適的cpu,局部變量smp_cpu保存了該
  19.          cpu的logical cpu id,這里假設(shè)為5。

  20.    2371:函數(shù)sched_setcpu主要完成下面的工作:
  21.          將和線程td相關(guān)聯(lián)的struct td_sched數(shù)據(jù)對象的ts_cpu成員設(shè)置為smp_cpu。
  22.          并返回logical cpu id為smp_cpu的運行隊列,這里假設(shè)為&tdq_cpu[5]。
  23. ***********************************/
  24.   2365        #ifdef SMP
  25. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  26.   2370                smp_cpu = sched_pickcpu(td, flags);
  27.   2371                tdq = sched_setcpu(td, smp_cpu, flags);
  28. /************************************************************************
  29. * 2373-2376:
  30.    如果smp_cpu和當(dāng)前cpu的logical cpu id不相等,那么就調(diào)用函數(shù)
  31.    tdq_notify檢查線程td是否能夠搶占當(dāng)前正在cpu logical id為smp_cpu
  32.    上運行的線程,如果可以,就發(fā)送一個IPI。
  33. *********************************************************/
  34.   2373                if (smp_cpu != PCPU_GET(cpuid)) {
  35.   2374                        tdq_notify(tdq, td);
  36.   2375                        return;
  37.   2376                }
  38. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  39.   2389        }
復(fù)制代碼
[摘取函數(shù)tdq_notify的部分代碼]:
  1. /*******************************************************************************
  2. * Notify a remote cpu of new work.  Sends an IPI if criteria are met.
  3.    對于logical cpu id為5的cpu,此時參數(shù)描述及相應(yīng)成員的取值如下:

  4.    參數(shù)描述:

  5.    tdq:為&tdq_cpu[5]。

  6.    td:已經(jīng)被添加到運行隊列tdq_cpu[5]的tdq_realtime隊列,tdq_timeshare隊列,

  7.        tdq_idle隊列三個隊列之一中的線程。

  8.    成員取值描述:
  9.    td->td_sched->ts_cpu的值為5。
  10. ***************************************************************************/           
  11.   1011        static void
  12.   1012        tdq_notify(struct tdq *tdq, struct thread *td)
  13.   1013        {
  14. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  15. /************************************************************
  16. * 1018-1019:
  17.    如果struct tdq對象的tdq_ipipending成員非零,表示此時正在
  18.    發(fā)送IPI,此時直接返回。
  19. *****************************************/
  20.   1018                if (tdq->tdq_ipipending)
  21.   1019                        return;
  22. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  23. /***************************************************************
  24. * 如果執(zhí)行到這里,就表示線程td將搶占線程ctd。
  25. * 1033:將struct tdq對象的tdq_ipipending成員設(shè)置為1。

  26.    1034:發(fā)送類型為IPI_PREEMPT的IPI。

  27.    變量cpu的值為5。
  28. ********************************************************/
  29.   1033                tdq->tdq_ipipending = 1;
  30.   1034                ipi_cpu(cpu, IPI_PREEMPT)
  31.   1035        }
復(fù)制代碼
從上面的描述中可以看出,調(diào)用函數(shù)ipi_cpu來發(fā)送一個IPI,函數(shù)ipi_cpu是內(nèi)核提供的用來發(fā)送IPI的接口。

[函數(shù)ipi_cpu]:
  1. /************************************************************************
  2. * send an IPI to a specific CPU.
  3.    參數(shù)描述:

  4.    cpu:接收IPI的cpu的logical cpu id,這里假設(shè)為5。

  5.    ipi:
  6.    一般情況下為中斷向量號。
  7.    當(dāng)發(fā)送IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個特殊的IPI時,對應(yīng)
  8.    的不是中斷向量號。

  9.    這里ipi的值為IPI_PREEMPT。

  10.    該函數(shù)實際上是函數(shù)ipi_send_cpu的一個簡單封裝。
  11. ********************************************/
  12.   1419        void
  13.   1420        ipi_cpu(int cpu, u_int ipi)
  14.   1421        {
  15.   1422       
  16. /***********************************************************************
  17. * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
  18. * of help in order to understand what is the source.
  19. * Set the mask of receiving CPUs for this purpose.

  20.    1428-1429:
  21.    #define        IPI_STOP_HARD        252    Stop CPU with a NMI.
  22.    忽略之間的處理。  

  23.    1432:ipi_send_cpu函數(shù)見下面的描述。                 
  24. *******************************/
  25.   1428                if (ipi == IPI_STOP_HARD)
  26.   1429                        CPU_SET_ATOMIC(cpu, &ipi_nmi_pending);
  27.   1430       
  28.   1431                CTR3(KTR_SMP, "%s: cpu: %d ipi: %x", __func__, cpu, ipi);
  29.   1432                ipi_send_cpu(cpu, ipi);
  30.   1433        }
復(fù)制代碼
[函數(shù)ipi_send_cpu]:
  1. /***************************************************************************************
  2. * Send an IPI to specified CPU handling the bitmap logic.
  3. * 參數(shù)描述:

  4.    cpu:接收IPI的cpu的logical cpu id,這里假設(shè)為5。   

  5.    ipi:
  6.    一般情況下為中斷向量號。
  7.    當(dāng)發(fā)送IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個IPI時,對應(yīng)
  8.    的不是中斷向量號。

  9.    這里ipi的值為IPI_PREEMPT。

  10.    函數(shù)ipi_send_cpu的任務(wù)就是針對IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個特殊的IPI
  11.    做相應(yīng)的處理。
  12. ***********************************
  13.   1190        static void
  14.   1191        ipi_send_cpu(int cpu, u_int ipi)
  15.   1192        {
  16.   1193                u_int bitmap, old_pending, new_pending;
  17.   1194       
  18.   1195                KASSERT(cpu_apic_ids[cpu] != -1, ("IPI to non-existent CPU %d", cpu));
  19. /***********************************************************************************************************
  20. * 1197-1207:
  21.    如果發(fā)送的是IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個特殊的IPI就進行相應(yīng)的處理。
  22.    
  23.    #define        IPI_AST                0        
  24.    #define      IPI_PREEMPT     1
  25.    #define      IPI_HARDCLOCK   2
  26.    #define IPI_BITMAP_LAST IPI_HARDCLOCK  2
  27.    #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
  28.    
  29.    1197:
  30.    宏IPI_IS_BITMAPED檢查ipi是否為IPI_AST或者IPI_PREEMPT或者IPI_HARDCLOCK,如果是,宏的值就為真。
  31.    這里為IPI_IS_BITMAPED(IPI_PREEMPT)   IPI_PREEMPT <= IPI_BITMAP_LAST,很明顯為真。

  32.    1198:變量bitmap為二進制10。

  33.    1199:此時重新設(shè)置變量ipi,將其設(shè)置為IPI_BITMAP_VECTOR,即中斷向量號249。

  34.    由此可以看出,當(dāng)發(fā)送IPI_AST,IPI_PREEMPT,IPI_HARDCLOCK三個特殊的IPI時,實際上發(fā)送的IPI的中斷向量號
  35.    都為IPI_BITMAP_VECTOR。

  36.    1200-1203,do-while循環(huán):
  37.    1201:old_pending保存的是當(dāng)前數(shù)組元素cpu_ipi_pending[5]的值。
  38.    1202:new_pending為將要賦值給數(shù)組元素cpu_ipi_pending[5]的新值。

  39.    do_while循環(huán)一直執(zhí)行,直到old_pending和cpu_ipi_pending[cpu]的值相等時為止,此時函數(shù)atomic_cmpset_int
  40.    返回1,數(shù)組元素cpu_ipi_pending[cpu]的值被更新為new_pending。
  41.   
  42.    因為APIC同時允許有兩個掛起的相同中斷,freebsd9.2貌似為了預(yù)防死鎖,一次只允許有一個掛起的中斷。

  43.    1205:如果old_pending非空,表示已經(jīng)發(fā)送了一個中斷向量號為IPI_BITMAP_VECTOR的IPI,但是cpu5還沒有處理。
  44.          此時直接返回。
  45. *************************************************/
  46.   1197                if (IPI_IS_BITMAPED(ipi)) {
  47.   1198                        bitmap = 1 << ipi;
  48.   1199                        ipi = IPI_BITMAP_VECTOR;
  49.   1200                        do {
  50.   1201                                old_pending = cpu_ipi_pending[cpu];
  51.   1202                                new_pending = old_pending | bitmap;
  52.   1203                        } while  (!atomic_cmpset_int(&cpu_ipi_pending[cpu],
  53.   1204                            old_pending, new_pending));       
  54.   1205                        if (old_pending)
  55.   1206                                return;
  56.   1207                }
  57. /**************************************************************
  58. * 1208:
  59.    logical cpu id是內(nèi)核用來標(biāo)識cpu的,但是發(fā)送IPI時,必須使用
  60.    指定cpu的local APIC ID,這里就要用到數(shù)組cpu_apic_ids。

  61.    數(shù)組元素cpu_apic_ids[5]的值為cpu5的local APIC ID。
  62.    
  63.    此時,變量ipi已經(jīng)被正確設(shè)置,調(diào)用函數(shù)lapic_ipi_vectored
  64.    發(fā)送IPI。
  65. *************************************/
  66.   1208                lapic_ipi_vectored(ipi, cpu_apic_ids[cpu]);
  67.   1209        }
復(fù)制代碼
[函數(shù)lapic_ipi_vectored]-該函數(shù)構(gòu)造將要寫入到ICR中的值,下面再看看ICR的格式,假設(shè)其為0,一般情況下,Reserved
字段的值先讀出,然后保證寫入原值即可,這里假設(shè)Reserved字段的值為0:
  1. /***************************************************************************
  2. * 參數(shù)描述:
  3.    vector:中斷向量號,這里為IPI_BITMAP_VECTOR,即中斷向量號249。
  4.    dest:cpu5的local APIC ID,這里假設(shè)為X,X為local APIC ID的二進制表示。
  5. *****************************
  6.   1441        void
  7.   1442        lapic_ipi_vectored(u_int vector, int dest)
  8.   1443        {
  9. /**********************************************************************
  10. * icrlo:將要寫入ICR低32位的值。
  11.    destfield:將要寫入ICR高32位中Destination Field字段的值。

  12.    1449-1459:執(zhí)行完后,icrlo的值為0x000000F9。
  13. *******************************/
  14.   1444                register_t icrlo, destfield;
  15.   1445       
  16.   1446                KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
  17.   1447                    ("%s: invalid vector %d", __func__, vector));
  18.   1448       
  19.   1449                icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
  20.   1450       
  21.   1451                /*
  22.   1452                 * IPI_STOP_HARD is just a "fake" vector used to send a NMI.
  23.   1453                 * Use special rules regard NMI if passed, otherwise specify
  24.   1454                 * the vector.
  25.   1455                 */
  26.   1456                if (vector == IPI_STOP_HARD)
  27.   1457                        icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
  28.   1458                else
  29.   1459                        icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
  30. /******************************************************************************************
  31. * 因為這里是發(fā)送給指定cpu的IPI,所以dest為目的cpu的local APIC ID。

  32.    1462-1464:IPI的目的地為僅包括發(fā)送此IPI的cpu,此時icrlo的值為0x000400F9。
  33.    1465-1467:IPI的目的地為系統(tǒng)中全部cpu,包括發(fā)送此IPI的cpu,此時icrlo的值為0x000800F9。
  34.    1468-1470:IPI的目的地為系統(tǒng)中除發(fā)送此IPI的cpu以外的cpu,此時icrlo的值為0x000C00F9。
  35.      
  36.    如果switch語句從上面任意三個case中的一個跳出,destfield的值不變,即為0。

  37.    針對這里討論的情況,destfield的值為X,icrlo的值為0x000000F9。   
  38. ************************************/
  39.   1460                destfield = 0;
  40.   1461                switch (dest) {
  41.   1462                case APIC_IPI_DEST_SELF:
  42.   1463                        icrlo |= APIC_DEST_SELF;
  43.   1464                        break;
  44.   1465                case APIC_IPI_DEST_ALL:
  45.   1466                        icrlo |= APIC_DEST_ALLISELF;
  46.   1467                        break;
  47.   1468                case APIC_IPI_DEST_OTHERS:
  48.   1469                        icrlo |= APIC_DEST_ALLESELF;
  49.   1470                        break;
  50.   1471                default:
  51.   1472                        KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
  52.   1473                            ("%s: invalid destination 0x%x", __func__, dest));
  53.   1474                        destfield = dest;
  54.   1475                }
  55.   1476       
  56. /*****************************************************************************************************
  57. * Wait for an earlier IPI to finish,檢查是否有更早的IPI沒有完成發(fā)送。
  58.    #define        BEFORE_SPIN        1000000
  59.    
  60.    ICR的字段Delivery Status:指示IPI的發(fā)送狀態(tài)。0:IPI已經(jīng)成功發(fā)送出去;1:還沒有完成IPI的發(fā)送。

  61.    函數(shù)lapic_ipi_wait執(zhí)行一個for循環(huán),不停的測試Delivery Status字段的值,如果在指定的時間內(nèi),該
  62.    字段的值變?yōu)?,就返回1;否則返回0,表示出現(xiàn)了某種問題。

  63.    這個指定的時間為BEFORE_SPIN * (指令pause的時鐘周期數(shù))。
  64. *******************************************/
  65.   1478                if (!lapic_ipi_wait(BEFORE_SPIN)) {
  66.   1479                        if (panicstr != NULL)
  67.   1480                                return;
  68.   1481                        else
  69.   1482                                panic("APIC: Previous IPI is stuck");
  70.   1483                }
  71. /*****************************************************************************************************
  72. * 1485:
  73.    函數(shù)lapic_ipi_raw完成IPI的發(fā)送,見下面的描述。
  74. ***********************/
  75.   1485                lapic_ipi_raw(icrlo, destfield);
  76. /*************************************************************************
  77. * 執(zhí)行到這里的話,IPI的發(fā)送已經(jīng)完成。
  78. *
  79. * 1487-1512之間的代碼只有在定義了DETECT_DEADLOCK才有意義,在有意義的
  80.    情況下,就是檢查一下此次發(fā)送的IPI是否完成發(fā)送。
  81. ***************************************/
  82.   1487        #ifdef DETECT_DEADLOCK
  83.   1488                /* Wait for IPI to be delivered. */ #define        AFTER_SPIN        1000
  84.   1489                if (!lapic_ipi_wait(AFTER_SPIN)) {
  85.   1490        #ifdef needsattention
  86.   1491                        /*
  87.   1492                         * XXX FIXME:
  88.   1493                         *
  89.   1494                         * The above function waits for the message to actually be
  90.   1495                         * delivered.  It breaks out after an arbitrary timeout
  91.   1496                         * since the message should eventually be delivered (at
  92.   1497                         * least in theory) and that if it wasn't we would catch
  93.   1498                         * the failure with the check above when the next IPI is
  94.   1499                         * sent.
  95.   1500                         *
  96.   1501                         * We could skip this wait entirely, EXCEPT it probably
  97.   1502                         * protects us from other routines that assume that the
  98.   1503                         * message was delivered and acted upon when this function
  99.   1504                         * returns.
  100.   1505                         */
  101.   1506                        printf("APIC: IPI might be stuck\n");
  102.   1507        #else /* !needsattention */
  103.   1508                        /* Wait until mesage is sent without a timeout. */
  104.   1509                        while (lapic->icr_lo & APIC_DELSTAT_PEND)
  105.   1510                                ia32_pause();
  106.   1511        #endif /* needsattention */
  107.   1512                }
  108.   1513        #endif /* DETECT_DEADLOCK */
  109.   1514        }
復(fù)制代碼
[函數(shù)lapic_ipi_raw]:
  1. /************************************************************************************
  2. * 參數(shù)描述:
  3.   
  4.    icrlo:將要寫到ICR低32位的值,針對這里討論的情況,值為0x000000F9。
  5.    
  6.    dest:目的cpu的local APIC ID或者為0,針對這里討論的情況,值為X。
  7. *************************/
  8.   1407        void
  9.   1408        lapic_ipi_raw(register_t icrlo, u_int dest)
  10.   1409        {
  11.   1410                register_t value, saveintr;
  12.   1411       
  13.   1412                /* XXX: Need more sanity checking of icrlo? */
  14.   1413                KASSERT(lapic != NULL, ("%s called too early", __func__));
  15.   1414                KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
  16.   1415                    ("%s: invalid dest field", __func__));
  17.   1416                KASSERT((icrlo & APIC_ICRLO_RESV_MASK) == 0,
  18.   1417                    ("%s: reserved bits set in ICR LO register", __func__));
  19.   1418       
  20. /***********************************************************************************
  21. * Set destination in ICR HI register if it is being used.

  22.    1420:函數(shù)intr_disable將當(dāng)前EFLAGS寄存器的值保存到變量中saveintr,之后清
  23.          EFLAGS寄存器的IF標(biāo)志,表示此時禁止中斷。
  24.    
  25.    針對這里討論的情況,將執(zhí)行1421-1426之間的語句。

  26.    變量lapic請參考"內(nèi)核如何實現(xiàn)IA32中斷處理"中的描述。

  27.    通過變量lapic訪問cpu5的local APIC寄存器組:
  28.    lapic->icr_hi:訪問ICR高32位。
  29.    
  30.    1422-1425:ICR高32位中的bit24-31被設(shè)置為X,bit0-23保持原來的值。
  31.      
  32.    執(zhí)行完后ICR中Destination Field字段的值為X,即這個IPI將發(fā)送給cpu5。
  33. ******************************************/
  34.   1420                saveintr = intr_disable();
  35.   1421                if ((icrlo & APIC_DEST_MASK) == APIC_DEST_DESTFLD) {
  36.   1422                        value = lapic->icr_hi;
  37.   1423                        value &= ~APIC_ID_MASK;
  38.   1424                        value |= dest << APIC_ID_SHIFT;
  39.   1425                        lapic->icr_hi = value;
  40.   1426                }
  41. /******************************************************************************************
  42. * 通過變量lapic訪問cpu5的local APIC寄存器組:
  43.    lapic->icr_lo:訪問ICR低32位。

  44.    1429-1431:執(zhí)行完后,value的值為0x000000F9。

  45.    1432:這個賦值操作就相當(dāng)于對ICR低32位執(zhí)行了一個寫操作,ICR的Vector字段的值為0xF9。
  46.          
  47.    此時,已經(jīng)向cpu5發(fā)出了一個IPI,該IPI的中斷向量號為IPI_BITMAP_VECTOR,當(dāng)cpu5
  48.    接收到這個中斷時,就按照"內(nèi)核如何實現(xiàn)IA32中斷處理"中最后描述的中斷處理機制進行處理。     

  49.    1432:用saveintr恢復(fù)EFLAGS寄存器。
  50. ****************************************/          
  51.   1428                /* Program the contents of the IPI and dispatch it. */
  52.   1429                value = lapic->icr_lo;
  53.   1430                value &= APIC_ICRLO_RESV_MASK;
  54.   1431                value |= icrlo;
  55.   1432                lapic->icr_lo = value;
  56.   1433                intr_restore(saveintr);
  57.   1434        }
復(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