Fix definition of KINTERRUPT in ROS headers so that moving to NDK will be easier. Also fix KeDisconnectInterrupt to return the old state instead of VOID, and re-write the I/O Interrupt code to work with an array and first object for better speed

svn path=/trunk/; revision=16229
This commit is contained in:
Alex Ionescu 2005-06-22 23:10:15 +00:00
parent 9925309a13
commit d1258e99fa
5 changed files with 293 additions and 182 deletions

View file

@ -62,7 +62,7 @@ BOOLEAN STDCALL
KeConnectInterrupt(
PKINTERRUPT InterruptObject);
VOID STDCALL
BOOLEAN STDCALL
KeDisconnectInterrupt(
PKINTERRUPT InterruptObject);

View file

@ -1781,22 +1781,48 @@ typedef struct _LPC_PORT_BASIC_INFORMATION
} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION;
#if 0
typedef struct _KINTERRUPT
{
ULONG Vector;
KAFFINITY ProcessorEnableMask;
KSPIN_LOCK SpinLock;
PKSPIN_LOCK ActualLock;
BOOLEAN Shareable;
BOOLEAN FloatingSave;
CHAR ProcessorNumber;
PKSERVICE_ROUTINE ServiceRoutine;
PVOID ServiceContext;
LIST_ENTRY Entry;
KIRQL Irql;
KIRQL SynchLevel;
KINTERRUPT_MODE InterruptMode;
ULONG Vector; // Idem
KAFFINITY ProcessorEnableMask; // not needed
KSPIN_LOCK SpinLock; // Idem
PKSPIN_LOCK ActualLock; // Idem
BOOLEAN Shareable; // ShareVector
BOOLEAN FloatingSave; // Idem
CHAR ProcessorNumber; // Number
PKSERVICE_ROUTINE ServiceRoutine; // Idem
PVOID ServiceContext; // Idem
LIST_ENTRY Entry; // InteruptListEntry
KIRQL Irql; // Irql
KIRQL SynchLevel; // SynchronizeIrql
KINTERRUPT_MODE InterruptMode; // Mode
} KINTERRUPT;
#endif
typedef struct _KINTERRUPT
{
CSHORT Type;
CSHORT Size;
LIST_ENTRY InterruptListEntry;
PKSERVICE_ROUTINE ServiceRoutine;
PVOID ServiceContext;
KSPIN_LOCK SpinLock;
ULONG TickCount;
PKSPIN_LOCK ActualLock;
PVOID DispatchAddress;
ULONG Vector;
KIRQL Irql;
KIRQL SynchronizeIrql;
BOOLEAN FloatingSave;
BOOLEAN Connected;
CHAR Number;
UCHAR ShareVector;
KINTERRUPT_MODE Mode;
ULONG ServiceCount;
ULONG DispatchCount;
ULONG DispatchCode[106];
} KINTERRUPT, *PKINTERRUPT;
#ifndef __USE_W32API

View file

@ -14,23 +14,16 @@
#define NDEBUG
#include <internal/debug.h>
/* TYPES ********************************************************************/
typedef struct _IO_INTERRUPT
{
KINTERRUPT FirstInterrupt;
PKINTERRUPT Interrupt[MAXIMUM_PROCESSORS];
KSPIN_LOCK SpinLock;
} IO_INTERRUPT, *PIO_INTERRUPT;
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
NTSTATUS STDCALL
IoConnectInterrupt(PKINTERRUPT* InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
KAFFINITY ProcessorEnableMask,
BOOLEAN FloatingSave)
/*
* FUNCTION: Registers a driver's isr to be called when its device interrupts
* ARGUMENTS:
@ -57,106 +50,163 @@ IoConnectInterrupt(PKINTERRUPT* InterruptObject,
* the isr runs. Must be false for x86 drivers
* RETURNS: Status
* IRQL: PASSIVE_LEVEL
*/
{
PKINTERRUPT Interrupt;
ULONG i, count;
ASSERT_IRQL(PASSIVE_LEVEL);
DPRINT("IoConnectInterrupt(Vector %x)\n",Vector);
ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
if (ProcessorEnableMask == 0)
{
return STATUS_INVALID_PARAMETER;
}
for (i = 0, count = 0; i < KeNumberProcessors; i++)
{
if (ProcessorEnableMask & (1 << i))
{
count++;
}
}
/*
* Initialize interrupt object
*/
Interrupt=ExAllocatePoolWithTag(NonPagedPool,count*sizeof(KINTERRUPT),
TAG_KINTERRUPT);
if (Interrupt==NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
if (SpinLock == NULL)
{
SpinLock = &Interrupt[0].SpinLock;
KeInitializeSpinLock(SpinLock);
}
Interrupt[0].ProcessorEnableMask = ProcessorEnableMask;
for (i = 0, count = 0; i < KeNumberProcessors; i++)
{
if (ProcessorEnableMask & (1 << i))
{
KeInitializeInterrupt(&Interrupt[count],
ServiceRoutine,
ServiceContext,
SpinLock,
Vector,
Irql,
SynchronizeIrql,
InterruptMode,
ShareVector,
i,
FloatingSave);
if (!KeConnectInterrupt(&Interrupt[count]))
{
for (i = 0; i < count; i++)
{
if (ProcessorEnableMask & (1 << i))
{
KeDisconnectInterrupt(&Interrupt[i]);
}
}
ExFreePool(Interrupt);
return STATUS_INVALID_PARAMETER;
}
count++;
}
}
*InterruptObject = Interrupt;
return(STATUS_SUCCESS);
}
/*
*
* @implemented
*/
VOID STDCALL
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
NTSTATUS
STDCALL
IoConnectInterrupt(PKINTERRUPT* InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
KAFFINITY ProcessorEnableMask,
BOOLEAN FloatingSave)
{
PKINTERRUPT Interrupt;
PKINTERRUPT InterruptUsed;
PIO_INTERRUPT IoInterrupt;
PKSPIN_LOCK SpinLockUsed;
BOOLEAN FirstRun = TRUE;
ULONG i, count;
PAGED_CODE();
DPRINT1("IoConnectInterrupt(Vector %x)\n",Vector);
/* Convert the Mask */
ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
/* Make sure at least one CPU is on it */
if (!ProcessorEnableMask) return STATUS_INVALID_PARAMETER;
/* Determine the allocation */
for (i = 0, count = 0; i < KeNumberProcessors; i++)
{
if (ProcessorEnableMask & (1 << i)) count++;
}
/* Allocate the array of I/O Interrupts */
IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
(count - 1)* sizeof(KINTERRUPT) +
sizeof(IO_INTERRUPT),
TAG_KINTERRUPT);
if (!Interrupt) return(STATUS_INSUFFICIENT_RESOURCES);
/* Select which Spinlock to use */
if (SpinLock)
{
SpinLockUsed = SpinLock;
}
else
{
SpinLockUsed = &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 */
for (i = 0; i < KeNumberProcessors; i++)
{
/* Check if it's enabled for this CPU */
if (ProcessorEnableMask & (1 << i))
{
/* Check which one we will use */
InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
/* Initialize it */
KeInitializeInterrupt(InterruptUsed,
ServiceRoutine,
ServiceContext,
SpinLockUsed,
Vector,
Irql,
SynchronizeIrql,
InterruptMode,
ShareVector,
i,
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);
}
return STATUS_INVALID_PARAMETER;
}
/* Now we've used up our First Run */
if (FirstRun)
{
FirstRun = FALSE;
}
else
{
/* Move on to the next one */
IoInterrupt->Interrupt[i] = Interrupt++;
}
}
}
/* Return Success */
return STATUS_SUCCESS;
}
/*
* FUNCTION: Releases a drivers isr
* ARGUMENTS:
* InterruptObject = isr to release
*
* @implemented
*/
{
ULONG i, count;
VOID
STDCALL
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
for (i = 0, count = 0; i < KeNumberProcessors; i++)
{
ULONG i;
PIO_INTERRUPT IoInterrupt;
PAGED_CODE();
/* Get the I/O Interrupt */
IoInterrupt = CONTAINING_RECORD(InterruptObject,
IO_INTERRUPT,
FirstInterrupt);
/* Disconnect the first one */
KeDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
/* Now disconnect the others */
for (i = 0; i < KeNumberProcessors; i++)
{
if (InterruptObject[0].ProcessorEnableMask & (1 << i))
if (IoInterrupt->Interrupt[i])
{
KeDisconnectInterrupt(&InterruptObject[count]);
count++;
}
KeDisconnectInterrupt(&InterruptObject[i]);
}
}
ExFreePool(InterruptObject);
/* Free the I/O Interrupt */
ExFreePool(IoInterrupt);
}
/* EOF */

View file

@ -278,7 +278,7 @@ KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
while (current != &CurrentIsr->ListHead)
{
isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
oldlvl = KeAcquireInterruptSpinLock(isr);
if (isr->ServiceRoutine(isr, isr->ServiceContext))
{
@ -401,7 +401,7 @@ KeDumpIrqList(VOID)
KiAcquireSpinLock(&IsrTable[i][j].Lock);
current_entry = IsrTable[i][j].ListHead.Flink;
current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
while (current_entry!=&(IsrTable[i][j].ListHead))
{
if (printed == FALSE)
@ -411,7 +411,7 @@ KeDumpIrqList(VOID)
}
DPRINT(" Isr %x\n",current);
current_entry = current_entry->Flink;
current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
}
KiReleaseSpinLock(&IsrTable[i][j].Lock);
}
@ -422,7 +422,8 @@ KeDumpIrqList(VOID)
/*
* @implemented
*/
BOOLEAN STDCALL
BOOLEAN
STDCALL
KeConnectInterrupt(PKINTERRUPT InterruptObject)
{
KIRQL oldlvl,synch_oldlvl;
@ -440,11 +441,11 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
Vector -= IRQ_BASE;
ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors);
ASSERT (InterruptObject->Number < KeNumberProcessors);
KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber);
KeSetSystemAffinityThread(1 << InterruptObject->Number);
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->ProcessorNumber];
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
KiAcquireSpinLock(&CurrentIsr->Lock);
@ -454,8 +455,8 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
*/
if (!IsListEmpty(&CurrentIsr->ListHead))
{
ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,Entry);
if (InterruptObject->Shareable == FALSE || ListHead->Shareable==FALSE)
ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
{
KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl);
@ -468,13 +469,14 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);
Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->InterruptMode);
Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode);
if (Result)
{
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->Entry);
DPRINT("%x %x\n",InterruptObject->Entry.Flink, InterruptObject->Entry.Blink);
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->Entry.Blink);
}
InterruptObject->Connected = TRUE;
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
/*
@ -490,78 +492,112 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
return Result;
}
/*
* @implemented
*/
VOID STDCALL
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
/*
*
* FUNCTION: Releases a drivers isr
* ARGUMENTS:
* InterruptObject = isr to release
*/
BOOLEAN
STDCALL
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
{
KIRQL oldlvl,synch_oldlvl;
PISR_TABLE CurrentIsr;
KIRQL oldlvl,synch_oldlvl;
PISR_TABLE CurrentIsr;
BOOLEAN State;
DPRINT("KeDisconnectInterrupt\n");
DPRINT1("KeDisconnectInterrupt\n");
ASSERT (InterruptObject->Number < KeNumberProcessors);
ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors);
/* Set the affinity */
KeSetSystemAffinityThread(1 << InterruptObject->Number);
KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber);
/* Get the ISR Tabe */
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE]
[(ULONG)InterruptObject->Number];
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE][(ULONG)InterruptObject->ProcessorNumber];
/* Raise IRQL to required level and lock table */
KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
KiAcquireSpinLock(&CurrentIsr->Lock);
KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
KiAcquireSpinLock(&CurrentIsr->Lock);
/* Check if it's actually connected */
if ((State = InterruptObject->Connected))
{
/* Lock the Interrupt */
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
/* Remove this one, and check if all are gone */
RemoveEntryList(&InterruptObject->InterruptListEntry);
if (IsListEmpty(&CurrentIsr->ListHead))
{
/* Completely Disable the Interrupt */
HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
}
/* Disconnect it */
InterruptObject->Connected = FALSE;
/* Release the interrupt lock */
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
}
/* Release the table spinlock */
KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl);
RemoveEntryList(&InterruptObject->Entry);
if (IsListEmpty(&CurrentIsr->ListHead))
{
HalDisableSystemInterrupt(InterruptObject->Vector, 0);
}
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
/*
* Release the table spinlock
*/
KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl);
KeRevertToUserAffinityThread();
/* Go back to default affinity */
KeRevertToUserAffinityThread();
/* Return Old Interrupt State */
return State;
}
/*
* @implemented
*/
VOID
STDCALL
KeInitializeInterrupt(PKINTERRUPT InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
CHAR ProcessorNumber,
BOOLEAN FloatingSave)
KeInitializeInterrupt(PKINTERRUPT Interrupt,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
CHAR ProcessorNumber,
BOOLEAN FloatingSave)
{
InterruptObject->ServiceRoutine = ServiceRoutine;
InterruptObject->ServiceContext = ServiceContext;
InterruptObject->ActualLock = SpinLock;
InterruptObject->Vector = Vector;
InterruptObject->Irql = Irql;
InterruptObject->SynchLevel = SynchronizeIrql;
InterruptObject->InterruptMode = InterruptMode;
InterruptObject->Shareable = ShareVector;
InterruptObject->ProcessorNumber = ProcessorNumber;
InterruptObject->FloatingSave = FloatingSave;
/* Set the Interrupt Header */
Interrupt->Type = InterruptObject;
Interrupt->Size = sizeof(KINTERRUPT);
/* Check if we got a spinlock */
if (SpinLock)
{
Interrupt->ActualLock = SpinLock;
}
else
{
/* This means we'll be usin the built-in one */
KeInitializeSpinLock(&Interrupt->SpinLock);
Interrupt->ActualLock = &Interrupt->SpinLock;
}
/* Set the other settings */
Interrupt->ServiceRoutine = ServiceRoutine;
Interrupt->ServiceContext = ServiceContext;
Interrupt->Vector = Vector;
Interrupt->Irql = Irql;
Interrupt->SynchronizeIrql = SynchronizeIrql;
Interrupt->Mode = InterruptMode;
Interrupt->ShareVector = ShareVector;
Interrupt->Number = ProcessorNumber;
Interrupt->FloatingSave = FloatingSave;
/* Disconnect it at first */
Interrupt->Connected = FALSE;
}
VOID KePrintInterruptStatistic(VOID)

View file

@ -62,8 +62,7 @@ KeAcquireInterruptSpinLock(
{
KIRQL oldIrql;
//KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql);
KeRaiseIrql(Interrupt->SynchLevel, &oldIrql);
KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql);
KiAcquireSpinLock(Interrupt->ActualLock);
return oldIrql;
}