mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
cb6fc76b8b
Follow-up to commit 24a14abf2
(r57412).
HBelusca's comment:
> If this ExFreePoolWithTag() call was left commented, it's probably
> because, back in the day where I introduced it, there was a pool
> corruption that was detected, the source of which was unknown at
> that time. In retrospect, it is most probably the interrupt disconnect
> bug in IoDisconnectInterrupt() that was causing it. Now that this
> bug has been fixed just previously, it should be safe to re-enable
> pool freeing with tag.
233 lines
6.8 KiB
C
233 lines
6.8 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/io/iomgr/irq.c
|
|
* PURPOSE: I/O Wrappers (called Completion Ports) for Kernel Queues
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
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;
|
|
PIO_INTERRUPT IoInterrupt;
|
|
BOOLEAN FirstRun;
|
|
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 */
|
|
IoInterrupt = ExAllocatePoolZero(NonPagedPool,
|
|
(Count - 1) * sizeof(KINTERRUPT) +
|
|
sizeof(IO_INTERRUPT),
|
|
TAG_KINTERRUPT);
|
|
if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
/* Use the structure's spinlock, if none was provided */
|
|
if (!SpinLock)
|
|
{
|
|
SpinLock = &IoInterrupt->SpinLock;
|
|
KeInitializeSpinLock(SpinLock);
|
|
}
|
|
|
|
/* We first start with a built-in interrupt inside the I/O structure */
|
|
Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
|
|
FirstRun = TRUE;
|
|
|
|
/* Now create all the interrupts */
|
|
Affinity = ProcessorEnableMask & KeActiveProcessors;
|
|
for (Count = 0; Affinity; Count++, Affinity >>= 1)
|
|
{
|
|
/* Check if it's enabled for this CPU */
|
|
if (!(Affinity & 1))
|
|
continue;
|
|
|
|
/* Check which one we will use */
|
|
InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
|
|
|
|
/* Initialize it */
|
|
KeInitializeInterrupt(InterruptUsed,
|
|
ServiceRoutine,
|
|
ServiceContext,
|
|
SpinLock,
|
|
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 */
|
|
ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT);
|
|
}
|
|
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)
|
|
{
|
|
FirstRun = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Move on to the next one */
|
|
IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++;
|
|
}
|
|
}
|
|
|
|
/* Return success */
|
|
*InterruptObject = &IoInterrupt->FirstInterrupt;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
|
|
{
|
|
PIO_INTERRUPT IoInterrupt;
|
|
ULONG i;
|
|
|
|
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++)
|
|
{
|
|
/* Make sure one was registered */
|
|
if (!IoInterrupt->Interrupt[i])
|
|
continue;
|
|
|
|
/* Disconnect it */
|
|
KeDisconnectInterrupt(IoInterrupt->Interrupt[i]);
|
|
}
|
|
|
|
/* Free the I/O interrupt */
|
|
ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT);
|
|
}
|
|
|
|
NTSTATUS
|
|
IopConnectInterruptExFullySpecific(
|
|
_Inout_ PIO_CONNECT_INTERRUPT_PARAMETERS Parameters)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
/* Fallback to standard IoConnectInterrupt */
|
|
Status = IoConnectInterrupt(Parameters->FullySpecified.InterruptObject,
|
|
Parameters->FullySpecified.ServiceRoutine,
|
|
Parameters->FullySpecified.ServiceContext,
|
|
Parameters->FullySpecified.SpinLock,
|
|
Parameters->FullySpecified.Vector,
|
|
Parameters->FullySpecified.Irql,
|
|
Parameters->FullySpecified.SynchronizeIrql,
|
|
Parameters->FullySpecified.InterruptMode,
|
|
Parameters->FullySpecified.ShareVector,
|
|
Parameters->FullySpecified.ProcessorEnableMask,
|
|
Parameters->FullySpecified.FloatingSave);
|
|
DPRINT("IopConnectInterruptEx_FullySpecific: has failed with status %X", Status);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IoConnectInterruptEx(
|
|
_Inout_ PIO_CONNECT_INTERRUPT_PARAMETERS Parameters)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
switch (Parameters->Version)
|
|
{
|
|
case CONNECT_FULLY_SPECIFIED:
|
|
return IopConnectInterruptExFullySpecific(Parameters);
|
|
case CONNECT_FULLY_SPECIFIED_GROUP:
|
|
//TODO: We don't do anything for the group type
|
|
return IopConnectInterruptExFullySpecific(Parameters);
|
|
case CONNECT_MESSAGE_BASED:
|
|
DPRINT1("FIXME: Message based interrupts are UNIMPLEMENTED\n");
|
|
break;
|
|
case CONNECT_LINE_BASED:
|
|
DPRINT1("FIXME: Line based interrupts are UNIMPLEMENTED\n");
|
|
break;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
IoDisconnectInterruptEx(
|
|
_In_ PIO_DISCONNECT_INTERRUPT_PARAMETERS Parameters)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
//FIXME: This eventually will need to handle more cases
|
|
if (Parameters->ConnectionContext.InterruptObject)
|
|
IoDisconnectInterrupt(Parameters->ConnectionContext.InterruptObject);
|
|
}
|
|
|
|
/* EOF */
|