IoConnectInterrupt个人注释

/*
 * @implemented
 来看一下跟中断对象有关的两个对象:
 typedef struct _IO_INTERRUPT
{
    KINTERRUPT FirstInterrupt;
    PKINTERRUPT Interrupt[MAXIMUM_PROCESSORS];
    KSPIN_LOCK SpinLock;
} IO_INTERRUPT, *PIO_INTERRUPT;

 typedef struct _KINTERRUPT
 {
	 CSHORT Type;
	 CSHORT Size;
	 LIST_ENTRY InterruptListEntry;
	 PKSERVICE_ROUTINE ServiceRoutine;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	 PKSERVICE_ROUTINE MessageServiceRoutine;
	 ULONG MessageIndex;
#endif
	...
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	 ULONGLONG Rsvd1;
#endif
	 //指向INT_PROLOG代码段地址
	 ULONG DispatchCode[KINTERRUPT_DISPATCH_CODES];
 } KINTERRUPT, *PKINTERRUPT;
安装中断过程势必分配一个中断对象KINTERRUPT,对于单个CPU。
如果主机上有多个CPU,那就必须为每个CPU分配相同的
中断对象,这样,不同的CPU接到中断信号后才能有相同
的处理过程。
如果有这么多功能相同的却离散分布的中断对象,管理
起来比较麻烦,于是Reactos为这些具有相同处理过程的中断对象
分配一个统一的管理对象_IO_INTERRUPT,把同一类中断对象装入到
这个_IO_INTERRUPT结构中去

如此看来_KINTERRUPT是实际的处理者,而_IO_INTERRUPT更像一个管理者
 */
NTSTATUS
NTAPI
IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,
                   IN PKSERVICE_ROUTINE ServiceRoutine,
                   IN PVOID ServiceContext,
                   IN PKSPIN_LOCK SpinLock,
                   IN ULONG Vector,
                   IN KIRQL Irql,
                   IN KIRQL SynchronizeIrql,
                   IN KINTERRUPT_MODE InterruptMode,
                   IN BOOLEAN ShareVector,
                   IN KAFFINITY ProcessorEnableMask,
                   IN BOOLEAN FloatingSave)
{
    PKINTERRUPT Interrupt;
    PKINTERRUPT InterruptUsed;
	//IO_INTERRUPT:具有相同中断处理函数的CPU的集合
    PIO_INTERRUPT IoInterrupt;
    PKSPIN_LOCK SpinLockUsed;
    BOOLEAN FirstRun = TRUE;
    CCHAR Count = 0;
    KAFFINITY Affinity;
    PAGED_CODE();

    /* Assume failure */
    *InterruptObject = NULL;

    /* Get the affinity */
    Affinity = ProcessorEnableMask & KeActiveProcessors;
    while (Affinity)
    {
        /* Increase count */
        if (Affinity & 1) Count++;
        Affinity >>= 1;
    }

    /* Make sure we have a valid CPU count */
    if (!Count) return STATUS_INVALID_PARAMETER;

    /* Allocate the array of I/O Interrupts */
	/*
	Count>1 针对多CPU的情况. struct _IO_INTERRUPT IoInterrupt是用于管理多CPU中断处理的结构
	IoInterrupt->KINTERRUPT[0]->ISR
	                ->KINTERRUPT[1]->ISR
	                ->KINTERRUPT[2]->ISR
	这么说,在SMP结构中调用一次IoConnectInterrupt就会为所有具有中断处理能力的
	CPU都安装相同的中断处理过程(即中断对象)
	*/
	/*
	主要是分配IO_INTERRUPT--中断对象的管理者,其次才是在这个对象的尾部跟上诺干
	数量上和系统中具有该中断处理能力的CPU的中断对象

	当本函数后面KeInitializeInterrupt/KeConnectInterrupt调用完成后,将这个中断对象添加到
	IO_INTERRUPT管理者中
	*/
    IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
                                        (Count - 1) * sizeof(KINTERRUPT) +
                                        sizeof(IO_INTERRUPT),
                                        TAG_KINTERRUPT);
    if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES;

    /* Select which Spinlock to use */
    SpinLockUsed = SpinLock ? SpinLock : &IoInterrupt->SpinLock;

    /* We first start with a built-in Interrupt inside the I/O Structure */
    *InterruptObject = &IoInterrupt->FirstInterrupt;
    Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
    FirstRun = TRUE;

    /* Start with a fresh structure */
    RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT));

    /* Now create all the interrupts */
    Affinity = ProcessorEnableMask & KeActiveProcessors;
	//初始化IO_INTERRUPT中每个KINTERRUPT结构
    for (Count = 0; Affinity; Count++, Affinity >>= 1)
    {
        /* Check if it's enabled for this CPU */
		//Affinity & 1-->具有处理能力的CPU
        if (Affinity & 1)
        {
            /* Check which one we will use */
            InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;

            /* Initialize it */
            KeInitializeInterrupt(InterruptUsed,
                                  ServiceRoutine,
                                  ServiceContext,
                                  SpinLockUsed,
                                  Vector,
                                  Irql,
                                  SynchronizeIrql,
                                  InterruptMode,
                                  ShareVector,
                                  Count,
                                  FloatingSave);

            /* Connect it */
            if (!KeConnectInterrupt(InterruptUsed))
            {
                /* Check how far we got */
                if (FirstRun)
                {
                    /* We failed early so just free this */
                    ExFreePool(IoInterrupt);
                }
                else
                {
                    /* Far enough, so disconnect everything */
                    IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
                }

                /* And fail */
                return STATUS_INVALID_PARAMETER;
            }

            /* Now we've used up our First Run */
            if (FirstRun)
            {
            	//处理完FirstInterrupt,即将对其他CPU进行处理
                FirstRun = FALSE;
            }
            else
            {
                /* Move on to the next one */
				/*
				前面针对多处理器分配了多个中断处理对象,把经过处理的
				KINTERRUPT结构加入到IoInterrupt管理机构中
				(意即:这些CPU上已有这种中断处理程序)
				*/
                IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++;
            }
        }
    }

    /* Return Success */
    return STATUS_SUCCESS;
}


你可能感兴趣的:(windows,注释)