From 8cb1d77efdb21ac56dac8432a531ce4bce46b4a3 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sat, 6 Nov 2004 04:12:59 +0000 Subject: [PATCH] Reimplimented IO Timers correctly. svn path=/trunk/; revision=11550 --- reactos/include/ddk/iotypes.h | 18 +-- reactos/ntoskrnl/include/internal/io.h | 12 +- reactos/ntoskrnl/io/device.c | 4 +- reactos/ntoskrnl/io/iomgr.c | 3 +- reactos/ntoskrnl/io/timer.c | 171 +++++++++++++++++++++---- reactos/ntoskrnl/ke/gmutex.c | 6 +- 6 files changed, 170 insertions(+), 44 deletions(-) diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index 6b3bd3cfdf9..a6f4698540e 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -1,4 +1,4 @@ -/* $Id: iotypes.h,v 1.68 2004/10/31 23:40:10 ion Exp $ +/* $Id: iotypes.h,v 1.69 2004/11/06 04:12:59 ion Exp $ * */ @@ -1065,15 +1065,15 @@ typedef VOID STDCALL_FUNC /* * PURPOSE: Special timer associated with each device - * NOTES: This is a guess */ -typedef struct _IO_TIMER -{ - KTIMER timer; - KDPC dpc; - PDEVICE_OBJECT DeviceObject; - PIO_TIMER_ROUTINE TimerRoutine; - PVOID Context; + #define IO_TYPE_TIMER 9 +typedef struct _IO_TIMER { + USHORT Type; /* Every IO Object has a Type */ + USHORT TimerEnabled; /* Tells us if the Timer is enabled or not */ + LIST_ENTRY IoTimerList; /* List of other Timers on the system */ + PIO_TIMER_ROUTINE TimerRoutine; /* The associated timer routine */ + PVOID Context; /* Context */ + PDEVICE_OBJECT DeviceObject; /* Driver that owns this IO Timer */ } IO_TIMER, *PIO_TIMER; typedef struct _IO_WORKITEM *PIO_WORKITEM; diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 95d98a13016..50664692d74 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: io.h,v 1.47 2004/10/23 17:32:50 navaraf Exp $ +/* $Id: io.h,v 1.48 2004/11/06 04:12:59 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -512,4 +512,14 @@ IopInvalidateDeviceRelations( IN PDEVICE_NODE DeviceNode, IN DEVICE_RELATION_TYPE Type); +/* timer.c */ +VOID +FASTCALL +IopInitTimerImplementation(VOID); + +VOID +STDCALL +IopRemoveTimerFromTimerList( + IN PIO_TIMER Timer +); #endif diff --git a/reactos/ntoskrnl/io/device.c b/reactos/ntoskrnl/io/device.c index 1082425d9d4..eba6c987cab 100644 --- a/reactos/ntoskrnl/io/device.c +++ b/reactos/ntoskrnl/io/device.c @@ -1,4 +1,4 @@ -/* $Id: device.c,v 1.82 2004/10/23 17:32:50 navaraf Exp $ +/* $Id: device.c,v 1.83 2004/11/06 04:12:59 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -188,7 +188,7 @@ IoDeleteDevice(PDEVICE_OBJECT DeviceObject) /* Remove the timer if it exists */ if (DeviceObject->Timer) { - IoStopTimer(DeviceObject); + IopRemoveTimerFromTimerList(DeviceObject->Timer); ExFreePool(DeviceObject->Timer); } diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 35c112054b8..8bf4e3fa396 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -1,4 +1,4 @@ -/* $Id: iomgr.c,v 1.52 2004/09/08 11:42:56 ekohl Exp $ +/* $Id: iomgr.c,v 1.53 2004/11/06 04:12:59 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -520,6 +520,7 @@ IoInit (VOID) IoInitVpbImplementation(); IoInitShutdownNotification(); IopInitErrorLog(); + IopInitTimerImplementation(); /* * Create link from '\DosDevices' to '\??' directory diff --git a/reactos/ntoskrnl/io/timer.c b/reactos/ntoskrnl/io/timer.c index e07d745f18b..7b878ff15b2 100644 --- a/reactos/ntoskrnl/io/timer.c +++ b/reactos/ntoskrnl/io/timer.c @@ -1,5 +1,4 @@ -/* $Id: timer.c,v 1.12 2004/08/15 16:39:03 chorns Exp $ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/timer.c @@ -7,29 +6,110 @@ * PROGRAMMER: David Welch (welch@mcmail.com) * UPDATE HISTORY: * Created 22/05/98 + * Reimplemented 05/11/04 - Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ #include -#define NDEBUG +//#define NDEBUG #include -/* GLBOALS *******************************************************************/ +/* GLOBALS *******************************************************************/ #define TAG_IO_TIMER TAG('I', 'O', 'T', 'M') +/* Timer Database */ +KSPIN_LOCK IopTimerLock; +LIST_ENTRY IopTimerQueueHead; + +/* Timer Firing */ +KDPC IopTimerDpc; +KTIMER IopTimer; + +/* Keep count of how many timers we have */ +ULONG IopTimerCount = 0; + /* FUNCTIONS *****************************************************************/ static VOID STDCALL -IoTimerCallback(IN PKDPC Dpc, +IopTimerDispatch(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { - PIO_TIMER Timer = (PIO_TIMER) DeferredContext; + KIRQL OldIrql; + PLIST_ENTRY TimerEntry; + PIO_TIMER Timer; + ULONG i; + + DPRINT("Dispatching IO Timers. There are: %x \n", IopTimerCount); + + /* Check if any Timers are actualyl enabled as of now */ + if (IopTimerCount) { + + /* Lock the Timers */ + KeAcquireSpinLock(&IopTimerLock, &OldIrql); + + /* Call the Timer Routine of each enabled Timer */ + for(TimerEntry = IopTimerQueueHead.Flink, i = IopTimerCount; + (TimerEntry != &IopTimerQueueHead) && i; + TimerEntry = TimerEntry->Flink) { - Timer->TimerRoutine(Timer->DeviceObject, Timer->Context); + Timer = CONTAINING_RECORD(TimerEntry, IO_TIMER, IoTimerList); + if (Timer->TimerEnabled) { + DPRINT("Dispatching a Timer Routine: %x for Device Object: %x \n", + Timer->TimerRoutine, + Timer->DeviceObject); + Timer->TimerRoutine(Timer->DeviceObject, Timer->Context); + i--; + } + } + + /* Unlock the Timers */ + KeReleaseSpinLock(&IopTimerLock, OldIrql); + } +} + +VOID +STDCALL +IopRemoveTimerFromTimerList( + IN PIO_TIMER Timer +) +{ + KIRQL OldIrql; + + /* Lock Timers */ + KeAcquireSpinLock(&IopTimerLock, &OldIrql); + + /* Remove Timer from the List and Drop the Timer Count if Enabled */ + RemoveEntryList(&Timer->IoTimerList); + if (Timer->TimerEnabled) IopTimerCount--; + + /* Unlock the Timers */ + KeReleaseSpinLock(&IopTimerLock, OldIrql); +} + +VOID +FASTCALL +IopInitTimerImplementation(VOID) +/* FUNCTION: Initializes the IO Timer Object Implementation + * RETURNS: NOTHING + */ +{ + LARGE_INTEGER ExpireTime; + + /* Initialize Timer List Lock */ + KeInitializeSpinLock(&IopTimerLock); + + /* Initialize Timer List */ + InitializeListHead(&IopTimerQueueHead); + + /* Initialize the DPC/Timer which will call the other Timer Routines */ + ExpireTime.QuadPart = -10000000; + KeInitializeDpc(&IopTimerDpc, IopTimerDispatch, NULL); + KeInitializeTimerEx(&IopTimer, SynchronizationTimer); + KeSetTimerEx(&IopTimer, ExpireTime, 1000, &IopTimerDpc); } /* @@ -51,16 +131,32 @@ IoInitializeTimer(PDEVICE_OBJECT DeviceObject, * RETURNS: Status */ { - DeviceObject->Timer = ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_TIMER), - TAG_IO_TIMER); - DeviceObject->Timer->DeviceObject = DeviceObject; - DeviceObject->Timer->TimerRoutine = TimerRoutine; - DeviceObject->Timer->Context = Context; - KeInitializeTimer(&(DeviceObject->Timer->timer)); - KeInitializeDpc(&(DeviceObject->Timer->dpc), - IoTimerCallback, DeviceObject->Timer); + DPRINT("IoInitializeTimer() called for Device Object: %x with Routine: %x \n", DeviceObject, TimerRoutine); + + /* Allocate Timer */ + if (!DeviceObject->Timer) { + DeviceObject->Timer = ExAllocatePoolWithTag(NonPagedPool, + sizeof(IO_TIMER), + TAG_IO_TIMER); + if (!DeviceObject->Timer) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set up the Timer Structure */ + DeviceObject->Timer->Type = IO_TYPE_TIMER; + DeviceObject->Timer->DeviceObject = DeviceObject; + } + + DeviceObject->Timer->TimerRoutine = TimerRoutine; + DeviceObject->Timer->Context = Context; + DeviceObject->Timer->TimerEnabled = FALSE; + + /* Add it to the Timer List */ + ExInterlockedInsertTailList(&IopTimerQueueHead, + &DeviceObject->Timer->IoTimerList, + &IopTimerLock); - return(STATUS_SUCCESS); + /* Return Success */ + DPRINT("IoInitializeTimer() Completed\n"); + return(STATUS_SUCCESS); } /* @@ -76,16 +172,22 @@ IoStartTimer(PDEVICE_OBJECT DeviceObject) * DeviceObject = Device whose timer is to be started */ { - LONGLONG lli; - LARGE_INTEGER li; - - lli = -1000000; - li = *(LARGE_INTEGER *)&lli; - - KeSetTimerEx(&DeviceObject->Timer->timer, - li, - 1000, - &(DeviceObject->Timer->dpc)); + KIRQL OldIrql; + + DPRINT("IoStartTimer for Device Object: %x\n", DeviceObject); + + /* Lock Timers */ + KeAcquireSpinLock(&IopTimerLock, &OldIrql); + + /* If the timer isn't already enabled, enable it and increase IO Timer Count*/ + if (!DeviceObject->Timer->TimerEnabled) { + DeviceObject->Timer->TimerEnabled = TRUE; + IopTimerCount++; + } + + /* Unlock Timers */ + KeReleaseSpinLock(&IopTimerLock, OldIrql); + DPRINT("IoStartTimer Completed for Device Object: %x New Count: %x \n", DeviceObject, IopTimerCount); } /* @@ -101,7 +203,22 @@ IoStopTimer(PDEVICE_OBJECT DeviceObject) * DeviceObject = Device whose timer is to be stopped */ { - KeCancelTimer(&(DeviceObject->Timer->timer)); + KIRQL OldIrql; + + DPRINT("IoStopTimer for Device Object: %x\n", DeviceObject); + + /* Lock Timers */ + KeAcquireSpinLock(&IopTimerLock, &OldIrql); + + /* If the timer is enabled, disable it and decrease IO Timer Count*/ + if (DeviceObject->Timer->TimerEnabled) { + DeviceObject->Timer->TimerEnabled = FALSE; + IopTimerCount--; + } + + /* Unlock Timers */ + KeReleaseSpinLock(&IopTimerLock, OldIrql); + DPRINT("IoStopTimer Completed for Device Object: %x New Count: %x \n", DeviceObject, IopTimerCount); } diff --git a/reactos/ntoskrnl/ke/gmutex.c b/reactos/ntoskrnl/ke/gmutex.c index 723b0edb13a..d405a00f0d9 100644 --- a/reactos/ntoskrnl/ke/gmutex.c +++ b/reactos/ntoskrnl/ke/gmutex.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: gmutex.c,v 1.1 2004/10/31 21:21:14 ea Exp $ +/* $Id: gmutex.c,v 1.2 2004/11/06 04:12:59 ion Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/gmutex.c @@ -34,13 +34,11 @@ /* FUNCTIONS *****************************************************************/ /* -KiWaitForGuardedMutexGate +KeAcquireGuardedMutex KeAcquireGuardedMutexUnsafe KeEnterGuardedRegion KeInitializeGuardedMutex KeReleaseGuardedMutexUnsafe -WmipTraceGuardedMutex -KeAcquireGuardedMutex KeTryToAcquireGuardedMutex KeReleaseGuardedMutex KeLeaveGuardedRegion