- Implemented KeAcquireInterruptSpinLock and KeReleaseInterruptSpinLock.
- Implemented the interrupt handling for smp machines.
Modified: trunk/reactos/include/ddk/kefuncs.h
Modified: trunk/reactos/include/ntos/zwtypes.h
Modified: trunk/reactos/ntoskrnl/io/irq.c
Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
_____
Modified: trunk/reactos/include/ddk/kefuncs.h
--- trunk/reactos/include/ddk/kefuncs.h 2005-01-01 11:22:12 UTC (rev
12689)
+++ trunk/reactos/include/ddk/kefuncs.h 2005-01-01 11:28:46 UTC (rev
12690)
@@ -149,17 +149,17 @@
EVENT_TYPE Type,
BOOLEAN State);
-NTSTATUS STDCALL KeInitializeInterrupt(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);
+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);
VOID STDCALL KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner);
@@ -367,6 +367,10 @@
BOOLEAN STDCALL
KeRosPrintAddress(PVOID address);
+NTSTATUS STDCALL
+KeSetAffinityThread(PKTHREAD Thread,
+ KAFFINITY Affinity);
+
LONG STDCALL
KeSetBasePriorityThread(struct _KTHREAD* Thread,
LONG Increment);
_____
Modified: trunk/reactos/include/ntos/zwtypes.h
--- trunk/reactos/include/ntos/zwtypes.h 2005-01-01 11:22:12 UTC
(rev 12689)
+++ trunk/reactos/include/ntos/zwtypes.h 2005-01-01 11:28:46 UTC
(rev 12690)
@@ -1818,13 +1818,17 @@
{
ULONG Vector;
KAFFINITY ProcessorEnableMask;
- PKSPIN_LOCK IrqLock;
+ 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;
} KINTERRUPT;
#ifndef __USE_W32API
_____
Modified: trunk/reactos/ntoskrnl/io/irq.c
--- trunk/reactos/ntoskrnl/io/irq.c 2005-01-01 11:22:12 UTC (rev
12689)
+++ trunk/reactos/ntoskrnl/io/irq.c 2005-01-01 11:28:46 UTC (rev
12690)
@@ -62,43 +62,70 @@
*/
{
PKINTERRUPT Interrupt;
- NTSTATUS Status = STATUS_SUCCESS;
+ 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,sizeof(KINTERRUPT),
+
Interrupt=ExAllocatePoolWithTag(NonPagedPool,count*sizeof(KINTERRUPT),
TAG_KINTERRUPT);
if (Interrupt==NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
- Status = KeInitializeInterrupt(Interrupt,
- ServiceRoutine,
- ServiceContext,
- SpinLock,
- Vector,
- Irql,
- SynchronizeIrql,
- InterruptMode,
- ShareVector,
- ProcessorEnableMask,
- FloatingSave);
- if (!NT_SUCCESS(Status))
+ if (SpinLock == NULL)
{
- ExFreePool(Interrupt);
- return Status;
+ SpinLock = &Interrupt[0].SpinLock;
+ KeInitializeSpinLock(SpinLock);
}
- if (!KeConnectInterrupt(Interrupt))
+ Interrupt[0].ProcessorEnableMask = ProcessorEnableMask;
+
+ for (i = 0, count = 0; i < KeNumberProcessors; i++)
{
- ExFreePool(Interrupt);
- return STATUS_INVALID_PARAMETER;
+ 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++)
+ {
+ KeDisconnectInterrupt(&Interrupt[i]);
+ }
+ ExFreePool(Interrupt);
+ return STATUS_INVALID_PARAMETER;
+ }
+ count++;
+ }
}
*InterruptObject = Interrupt;
@@ -118,7 +145,16 @@
* InterruptObject = isr to release
*/
{
- KeDisconnectInterrupt(InterruptObject);
+ ULONG i, count;
+
+ for (i = 0, count = 0; i < KeNumberProcessors; i++)
+ {
+ if (InterruptObject[0].ProcessorEnableMask & (1 << i))
+ {
+ KeDisconnectInterrupt(&InterruptObject[count]);
+ count++;
+ }
+ }
ExFreePool(InterruptObject);
}
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c
--- trunk/reactos/ntoskrnl/ke/i386/irq.c 2005-01-01 11:22:12 UTC
(rev 12689)
+++ trunk/reactos/ntoskrnl/ke/i386/irq.c 2005-01-01 11:28:46 UTC
(rev 12690)
@@ -1,6 +1,6 @@
/*
* ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
+ * Copyright (C) 1998 - 2005 ReactOS Team
*
* This program is free software; you can redistribute it and/or
modify
* it under the terms of the GNU General Public License as published
by
@@ -16,12 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: irq.c,v 1.56 2004/11/27 19:24:15 hbirr Exp $
+/* $Id$
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/irq.c
* PURPOSE: IRQ handling
* PROGRAMMER: David Welch (welch(a)mcmail.com)
+ * Hartmut Birr
* UPDATE HISTORY:
* 29/05/98: Created
*/
@@ -182,10 +183,20 @@
* be accessed at any irq level.
*/
-static LIST_ENTRY isr_table[NR_IRQS];
-static KSPIN_LOCK isr_lock[NR_IRQS];
-static KSPIN_LOCK isr_table_lock;
+typedef struct
+{
+ LIST_ENTRY ListHead;
+ KSPIN_LOCK Lock;
+ ULONG Count;
+}
+ISR_TABLE, *PISR_TABLE;
+#ifdef MP
+static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS];
+#else
+static ISR_TABLE IsrTable[NR_IRQS][1];
+#endif
+
#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L')
/* FUNCTIONS
****************************************************************/
@@ -196,8 +207,9 @@
VOID INIT_FUNCTION
KeInitInterrupts (VOID)
{
- int i;
+ int i, j;
+
/*
* Setup the IDT entries to point to the interrupt handlers
*/
@@ -206,10 +218,17 @@
KiIdt[IRQ_BASE+i].a=(irq_handler[i]&0xffff)+(KERNEL_CS<<16);
KiIdt[IRQ_BASE+i].b=(irq_handler[i]&0xffff0000)+PRESENT+
I486_INTERRUPT_GATE;
- InitializeListHead(&isr_table[i]);
- KeInitializeSpinLock(&isr_lock[i]);
+#ifdef MP
+ for (j = 0; j < MAXIMUM_PROCESSORS; j++)
+#else
+ j = 0;
+#endif
+ {
+ InitializeListHead(&IsrTable[i][j].ListHead);
+ KeInitializeSpinLock(&IsrTable[i][j].Lock);
+ IsrTable[i][j].Count = 0;
+ }
}
- KeInitializeSpinLock(&isr_table_lock);
}
STATIC VOID
@@ -266,21 +285,34 @@
{
PKINTERRUPT isr;
PLIST_ENTRY current;
+ KIRQL oldlvl;
+ PISR_TABLE CurrentIsr;
DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level);
/*
* Iterate the list until one of the isr tells us its device
interrupted
*/
- current = isr_table[vector - IRQ_BASE].Flink;
- isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
+ CurrentIsr = &IsrTable[vector -
IRQ_BASE][(ULONG)KeGetCurrentProcessorNumber()];
- while (current != &isr_table[vector - IRQ_BASE] &&
- !isr->ServiceRoutine(isr, isr->ServiceContext))
+ KiAcquireSpinLock(&CurrentIsr->Lock);
+
+ CurrentIsr->Count++;
+ current = CurrentIsr->ListHead.Flink;
+
+ while (current != &CurrentIsr->ListHead)
{
+ isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
+ oldlvl = KeAcquireInterruptSpinLock(isr);
+ if (isr->ServiceRoutine(isr, isr->ServiceContext))
+ {
+ KeReleaseInterruptSpinLock(isr, oldlvl);
+ break;
+ }
+ KeReleaseInterruptSpinLock(isr, oldlvl);
current = current->Flink;
- isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
}
+ KiReleaseSpinLock(&CurrentIsr->Lock);
}
VOID
@@ -382,19 +414,35 @@
{
PKINTERRUPT current;
PLIST_ENTRY current_entry;
- unsigned int i;
+ ULONG i, j;
+ KIRQL oldlvl;
+ BOOLEAN printed;
for (i=0;i<NR_IRQS;i++)
{
- DPRINT("For irq %x:\n",i);
- current_entry = isr_table[i].Flink;
- current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
- while (current_entry!=(&isr_table[i]))
+ printed = FALSE;
+ KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);
+
+ for (j=0; j < KeNumberProcessors; j++)
{
- DPRINT(" Isr %x\n",current);
- current_entry = current_entry->Flink;
- current =
CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
+ KiAcquireSpinLock(&IsrTable[i][j].Lock);
+
+ current_entry = IsrTable[i][j].ListHead.Flink;
+ current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
+ while (current_entry!=&(IsrTable[i][j].ListHead))
+ {
+ if (printed == FALSE)
+ {
+ printed = TRUE;
+ DPRINT("For irq %x:\n",i);
+ }
+ DPRINT(" Isr %x\n",current);
+ current_entry = current_entry->Flink;
+ current =
CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
+ }
+ KiReleaseSpinLock(&IsrTable[i][j].Lock);
}
+ KeLowerIrql(oldlvl);
}
}
@@ -404,10 +452,11 @@
BOOLEAN STDCALL
KeConnectInterrupt(PKINTERRUPT InterruptObject)
{
- KIRQL oldlvl;
- KIRQL synch_oldlvl;
+ KIRQL oldlvl,synch_oldlvl;
PKINTERRUPT ListHead;
ULONG Vector;
+ PISR_TABLE CurrentIsr;
+ BOOLEAN Result;
DPRINT("KeConnectInterrupt()\n");
@@ -418,45 +467,54 @@
Vector -= IRQ_BASE;
+ ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors);
+
+ KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber);
+
+ CurrentIsr =
&IsrTable[Vector][(ULONG)InterruptObject->ProcessorNumber];
+
+ KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
+ KiAcquireSpinLock(&CurrentIsr->Lock);
+
/*
- * Acquire the table spinlock
- */
- KeAcquireSpinLock(&isr_table_lock,&oldlvl);
-
- /*
* Check if the vector is already in use that we can share it
*/
- ListHead =
CONTAINING_RECORD(isr_table[Vector].Flink,KINTERRUPT,Entry);
- if (!IsListEmpty(&isr_table[Vector]) &&
- (InterruptObject->Shareable == FALSE ||
ListHead->Shareable==FALSE))
+ if (!IsListEmpty(&CurrentIsr->ListHead))
{
- KeReleaseSpinLock(&isr_table_lock,oldlvl);
- return FALSE;
+ ListHead =
CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,Entry);
+ if (InterruptObject->Shareable == FALSE ||
ListHead->Shareable==FALSE)
+ {
+ KiReleaseSpinLock(&CurrentIsr->Lock);
+ KeLowerIrql(oldlvl);
+ KeRevertToUserAffinityThread();
+ return FALSE;
+ }
}
- InterruptObject->IrqLock = &isr_lock[Vector];
+ synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
- KeRaiseIrql(InterruptObject->SynchLevel,&synch_oldlvl);
- KiAcquireSpinLock(InterruptObject->IrqLock);
- DPRINT("%x %x\n",isr_table[Vector].Flink,isr_table[Vector].Blink);
- if (IsListEmpty(&isr_table[Vector]))
+ DPRINT("%x %x\n",CurrentIsr->ListHead.Flink,
CurrentIsr->ListHeads.Blink);
+
+ Result = HalEnableSystemInterrupt(Vector + IRQ_BASE,
InterruptObject->Irql, InterruptObject->InterruptMode);
+ if (Result)
{
- HalEnableSystemInterrupt(Vector + IRQ_BASE, 0, 0);
+ InsertTailList(&CurrentIsr->ListHead,&InterruptObject->Entry);
+ DPRINT("%x %x\n",InterruptObject->Entry.Flink,
InterruptObject->Entry.Blink);
}
- InsertTailList(&isr_table[Vector],&InterruptObject->Entry);
- DPRINT("%x %x\n",InterruptObject->Entry.Flink,
- InterruptObject->Entry.Blink);
- KiReleaseSpinLock(InterruptObject->IrqLock);
- KeLowerIrql(synch_oldlvl);
-
+
+ KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
+
/*
* Release the table spinlock
*/
- KeReleaseSpinLock(&isr_table_lock,oldlvl);
+ KiReleaseSpinLock(&CurrentIsr->Lock);
+ KeLowerIrql(oldlvl);
KeDumpIrqList();
- return TRUE;
+ KeRevertToUserAffinityThread();
+
+ return Result;
}
@@ -471,24 +529,43 @@
* InterruptObject = isr to release
*/
{
- KIRQL oldlvl;
+ KIRQL oldlvl,synch_oldlvl;
+ PISR_TABLE CurrentIsr;
+
+ DPRINT("KeDisconnectInterrupt\n");
- KeRaiseIrql(InterruptObject->SynchLevel,&oldlvl);
- KiAcquireSpinLock(InterruptObject->IrqLock);
+ ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors);
+
+ KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber);
+
+ CurrentIsr = &IsrTable[InterruptObject->Vector -
IRQ_BASE][(ULONG)InterruptObject->ProcessorNumber];
+
+ KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
+ KiAcquireSpinLock(&CurrentIsr->Lock);
+
+ synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
+
RemoveEntryList(&InterruptObject->Entry);
- if (IsListEmpty(&isr_table[InterruptObject->Vector - IRQ_BASE]))
+ if (IsListEmpty(&CurrentIsr->ListHead))
{
HalDisableSystemInterrupt(InterruptObject->Vector, 0);
}
- KiReleaseSpinLock(InterruptObject->IrqLock);
+ KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
+
+ /*
+ * Release the table spinlock
+ */
+ KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl);
+
+ KeRevertToUserAffinityThread();
}
/*
* @implemented
*/
-NTSTATUS
+VOID
STDCALL
KeInitializeInterrupt(PKINTERRUPT InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
@@ -499,18 +576,37 @@
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
- KAFFINITY ProcessorEnableMask,
+ CHAR ProcessorNumber,
BOOLEAN FloatingSave)
{
+ InterruptObject->ServiceRoutine = ServiceRoutine;
InterruptObject->ServiceContext = ServiceContext;
- InterruptObject->ServiceRoutine = ServiceRoutine;
+ InterruptObject->ActualLock = SpinLock;
InterruptObject->Vector = Vector;
- InterruptObject->ProcessorEnableMask = ProcessorEnableMask;
+ InterruptObject->Irql = Irql;
InterruptObject->SynchLevel = SynchronizeIrql;
+ InterruptObject->InterruptMode = InterruptMode;
InterruptObject->Shareable = ShareVector;
+ InterruptObject->ProcessorNumber = ProcessorNumber;
InterruptObject->FloatingSave = FloatingSave;
+}
- return STATUS_SUCCESS;
+VOID KePrintInterruptStatistic(VOID)
+{
+ ULONG i, j;
+
+ for (j = 0; j < KeNumberProcessors; j++)
+ {
+ DPRINT1("CPU%d:\n", j);
+ for (i = 0; i < NR_IRQS; i++)
+ {
+ if (IsrTable[i][j].Count)
+ {
+ DPRINT1(" Irq %x(%d): %d\n", i, VECTOR2IRQ(i + IRQ_BASE),
IsrTable[i][j].Count);
+ }
+ }
+ }
}
+
/* EOF */
_____
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
--- trunk/reactos/ntoskrnl/ke/spinlock.c 2005-01-01 11:22:12 UTC
(rev 12689)
+++ trunk/reactos/ntoskrnl/ke/spinlock.c 2005-01-01 11:28:46 UTC
(rev 12690)
@@ -1,4 +1,4 @@
-/* $Id: spinlock.c,v 1.25 2004/12/24 17:06:58 navaraf Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -17,6 +17,7 @@
/* INCLUDES
****************************************************************/
#include <ntoskrnl.h>
+#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS
***************************************************************/
@@ -42,19 +43,17 @@
KIRQL oldlvl;
BOOLEAN ret;
- KeRaiseIrql(Interrupt->SynchLevel, &oldlvl);
- KiAcquireSpinLock(Interrupt->IrqLock);
+ oldlvl = KeAcquireInterruptSpinLock(Interrupt);
ret = SynchronizeRoutine(SynchronizeContext);
- KiReleaseSpinLock(Interrupt->IrqLock);
- KeLowerIrql(oldlvl);
+ KeReleaseInterruptSpinLock(Interrupt, oldlvl);
return(ret);
}
/*
- * @unimplemented
+ * @implemented
*/
KIRQL
STDCALL
@@ -62,8 +61,11 @@
IN PKINTERRUPT Interrupt
)
{
- UNIMPLEMENTED;
- return 0;
+ KIRQL oldIrql;
+
+ KeRaiseIrql(Interrupt->SynchLevel, &oldIrql);
+ KiAcquireSpinLock(Interrupt->ActualLock);
+ return oldIrql;
}
/*
@@ -195,7 +197,7 @@
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
STDCALL
@@ -204,7 +206,8 @@
IN KIRQL OldIrql
)
{
- UNIMPLEMENTED;
+ KiReleaseSpinLock(Interrupt->ActualLock);
+ KeLowerIrql(OldIrql);
}
/*