Fix bug with registry loading on bootcd (Thanks Steven). Properly
implement Profile Objects with Ex/Ke architecture (structures are a
guess, and code is based on dwelch and some simple testing/common sense,
but not ready for primetime (NT doesnt even use theirs). Optimize Device
Queues a bit and use the inserted field properly.
Modified: branches/alex_devel_branch/reactos/include/ntos/zwtypes.h
Modified: branches/alex_devel_branch/reactos/ntoskrnl/cm/registry.c
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ex/profile.c
Modified:
branches/alex_devel_branch/reactos/ntoskrnl/include/internal/ke.h
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/kqueue.c
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/profile.c
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/timer.c
_____
Modified: branches/alex_devel_branch/reactos/include/ntos/zwtypes.h
--- branches/alex_devel_branch/reactos/include/ntos/zwtypes.h
2005-03-03 02:46:43 UTC (rev 13804)
+++ branches/alex_devel_branch/reactos/include/ntos/zwtypes.h
2005-03-03 03:57:59 UTC (rev 13805)
@@ -58,6 +58,7 @@
ProfileTime
} KPROFILE_SOURCE;
+
// file disposition values
#define FILE_SUPERSEDE 0x0000
_____
Modified: branches/alex_devel_branch/reactos/ntoskrnl/cm/registry.c
--- branches/alex_devel_branch/reactos/ntoskrnl/cm/registry.c
2005-03-03 02:46:43 UTC (rev 13804)
+++ branches/alex_devel_branch/reactos/ntoskrnl/cm/registry.c
2005-03-03 03:57:59 UTC (rev 13805)
@@ -248,10 +248,12 @@
{
PCHAR BaseAddress;
- /* Load Registry Hives */
- BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
- CmImportSystemHive(BaseAddress,
- CachedModules[SystemRegistry]->ModEnd -
(ULONG_PTR)BaseAddress);
+ /* Load Registry Hives. This one can be missing. */
+ if (CachedModules[SystemRegistry]) {
+ BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
+ CmImportSystemHive(BaseAddress,
+ CachedModules[SystemRegistry]->ModEnd -
(ULONG_PTR)BaseAddress);
+ }
BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
CmImportHardwareHive(BaseAddress,
_____
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ex/profile.c
--- branches/alex_devel_branch/reactos/ntoskrnl/ex/profile.c
2005-03-03 02:46:43 UTC (rev 13804)
+++ branches/alex_devel_branch/reactos/ntoskrnl/ex/profile.c
2005-03-03 03:57:59 UTC (rev 13805)
@@ -1,11 +1,10 @@
-/* $Id:$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
- * FILE: ntoskrnl/nt/profile.c
- * PURPOSE: Support for profiling
+ * FILE: ntoskrnl/ex/profile.c
+ * PURPOSE: Support for Executive Profile Objects
*
- * PROGRAMMERS: No programmer listed.
+ * PROGRAMMERS: Alex Ionescu
*/
/* INCLUDES
*****************************************************************/
@@ -13,369 +12,448 @@
#include <ntoskrnl.h>
#include <internal/debug.h>
-/* TYPES
********************************************************************/
+/* This structure is a *GUESS* -- Alex */
+typedef struct _EPROFILE {
+ PEPROCESS Process;
+ PVOID ImageBase;
+ ULONG ImageSize;
+ ULONG BucketSize;
+ PVOID Buffer;
+ ULONG BufferSize;
+ PKPROFILE KeProfile;
+ KPROFILE_SOURCE ProfileSource;
+ KAFFINITY Affinity;
+ PMDL Mdl;
+ PVOID LockedBuffer;
+} EPROFILE, *PEPROFILE;
/* GLOBALS
*******************************************************************/
POBJECT_TYPE EXPORTED ExProfileObjectType = NULL;
-static GENERIC_MAPPING ExpProfileMapping = {
- STANDARD_RIGHTS_READ,
- STANDARD_RIGHTS_WRITE,
- STANDARD_RIGHTS_EXECUTE,
- STANDARD_RIGHTS_ALL};
+static KMUTEX ExpProfileMutex;
-/*
- * Size of the profile hash table.
- */
-#define PROFILE_HASH_TABLE_SIZE (32)
+#define PROFILE_CONTROL 1
-/*
- * Table of lists of per-process profiling data structures hashed by
PID.
- */
-LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE];
+static GENERIC_MAPPING ExpProfileMapping = {
+ STANDARD_RIGHTS_READ | PROFILE_CONTROL,
+ STANDARD_RIGHTS_WRITE | PROFILE_CONTROL,
+ STANDARD_RIGHTS_EXECUTE | PROFILE_CONTROL,
+ STANDARD_RIGHTS_ALL};
-/*
- * Head of the list of profile data structures for the kernel.
- */
-LIST_ENTRY SystemProfileList;
-
-/*
- * Lock that protects the profiling data structures.
- */
-KSPIN_LOCK ProfileListLock;
-
-/*
- * Timer interrupts happen before we have initialized the profiling
- * data structures so just ignore them before that.
- */
-BOOLEAN ProfileInitDone = FALSE;
-
-VOID INIT_FUNCTION
-ExpInitializeProfileImplementation(VOID)
+VOID
+STDCALL
+ExpDeleteProfile(PVOID ObjectBody)
{
- ULONG i;
+ PEPROFILE Profile;
- InitializeListHead(&SystemProfileList);
+ /* Typecast the Object */
+ Profile = (PEPROFILE)ObjectBody;
+
+ /* Check if there if the Profile was started */
+ if (Profile->LockedBuffer) {
+
+ /* Stop the Profile */
+ KeStopProfile(Profile->KeProfile);
+
+ /* Unmap the Locked Buffer */
+ MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl);
+ MmUnlockPages(Profile->Mdl);
+ ExFreePool(Profile->Mdl);
+ }
- for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++)
- {
- InitializeListHead(&ProcessProfileListHashTable[i]);
+ /* Check if a Process is associated */
+ if (Profile->Process != NULL) {
+
+ /* Dereference it */
+ ObDereferenceObject(Profile->Process);
+ Profile->Process = NULL;
}
+}
- KeInitializeSpinLock(&ProfileListLock);
- ProfileInitDone = TRUE;
-
- ExProfileObjectType =
ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
- RtlpCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile",
NonPagedPool);
-
- ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F');
- ExProfileObjectType->PeakObjects = 0;
- ExProfileObjectType->PeakHandles = 0;
- ExProfileObjectType->TotalObjects = 0;
- ExProfileObjectType->TotalHandles = 0;
- ExProfileObjectType->PagedPoolCharge = 0;
- ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE);
- ExProfileObjectType->Mapping = &ExpProfileMapping;
- ExProfileObjectType->Dump = NULL;
- ExProfileObjectType->Open = NULL;
- ExProfileObjectType->Close = NULL;
- ExProfileObjectType->Delete = KiDeleteProfile;
- ExProfileObjectType->Parse = NULL;
- ExProfileObjectType->Security = NULL;
- ExProfileObjectType->QueryName = NULL;
- ExProfileObjectType->OkayToClose = NULL;
- ExProfileObjectType->Create = NULL;
-
- ObpCreateTypeObject(ExProfileObjectType);
+VOID
+INIT_FUNCTION
+ExpInitializeProfileImplementation(VOID)
+{
+ /* Initialize the Mutex to lock the States */
+ KeInitializeMutex(&ExpProfileMutex, 0x40);
+
+ /* Create the Object Type */
+ ExProfileObjectType =
ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+ RtlpCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile",
NonPagedPool);
+ ExProfileObjectType->Tag = TAG('P', 'R', 'O',
'F');
+ ExProfileObjectType->PeakObjects = 0;
+ ExProfileObjectType->PeakHandles = 0;
+ ExProfileObjectType->TotalObjects = 0;
+ ExProfileObjectType->TotalHandles = 0;
+ ExProfileObjectType->PagedPoolCharge = 0;
+ ExProfileObjectType->NonpagedPoolCharge = sizeof(EPROFILE);
+ ExProfileObjectType->Mapping = &ExpProfileMapping;
+ ExProfileObjectType->Dump = NULL;
+ ExProfileObjectType->Open = NULL;
+ ExProfileObjectType->Close = NULL;
+ ExProfileObjectType->Delete = ExpDeleteProfile;
+ ExProfileObjectType->Parse = NULL;
+ ExProfileObjectType->Security = NULL;
+ ExProfileObjectType->QueryName = NULL;
+ ExProfileObjectType->OkayToClose = NULL;
+ ExProfileObjectType->Create = NULL;
+ ObpCreateTypeObject(ExProfileObjectType);
}
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtCreateProfile(OUT PHANDLE ProfileHandle,
- IN HANDLE Process OPTIONAL,
- IN PVOID ImageBase,
- IN ULONG ImageSize,
- IN ULONG BucketSize,
- IN PVOID Buffer,
- IN ULONG BufferSize,
- IN KPROFILE_SOURCE ProfileSource,
- IN KAFFINITY Affinity)
+ IN HANDLE Process OPTIONAL,
+ IN PVOID ImageBase,
+ IN ULONG ImageSize,
+ IN ULONG BucketSize,
+ IN PVOID Buffer,
+ IN ULONG BufferSize,
+ IN KPROFILE_SOURCE ProfileSource,
+ IN KAFFINITY Affinity)
{
- HANDLE hProfile;
- PKPROFILE Profile;
- PEPROCESS pProcess;
- KPROCESSOR_MODE PreviousMode;
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS Status = STATUS_SUCCESS;
+ HANDLE hProfile;
+ PEPROFILE Profile;
+ PEPROCESS pProcess;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
+ PAGED_CODE();
- PreviousMode = ExGetPreviousMode();
-
- if(BufferSize == 0)
- {
- return STATUS_INVALID_PARAMETER_7;
- }
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(ProfileHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- ProbeForWrite(Buffer,
- BufferSize,
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ /* Easy way out */
+ if(BufferSize == 0) return STATUS_INVALID_PARAMETER_7;
+
+ /* Check the Parameters for validity */
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWrite(ProfileHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+
+ ProbeForWrite(Buffer,
+ BufferSize,
+ sizeof(ULONG));
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
- if(!NT_SUCCESS(Status))
- {
- return Status;
+ if(!NT_SUCCESS(Status)) return Status;
}
- }
- /*
- * Reference the associated process
- */
- if (Process != NULL)
- {
- Status = ObReferenceObjectByHandle(Process,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)&pProcess,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ /* Check if a process was specified */
+ if (Process) {
+
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Process,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&pProcess,
+ NULL);
+ if (!NT_SUCCESS(Status)) return(Status);
+
+ } else {
+
+ /* No process was specified, which means a System-Wide Profile
*/
+ pProcess = NULL;
+
+ /* For this, we need to check the Privilege */
+ if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege,
PreviousMode)) {
+
+ DPRINT1("NtCreateProfile: Caller requires the
SeSystemProfilePrivilege privilege!\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
}
- else
- {
- pProcess = NULL;
- if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege,
- PreviousMode))
- {
- DPRINT1("NtCreateProfile: Caller requires the
SeSystemProfilePrivilege privilege!\n");
- return STATUS_PRIVILEGE_NOT_HELD;
- }
- }
- /*
- * Check the parameters
- */
- if ((pProcess == NULL && ImageBase < (PVOID)KERNEL_BASE) ||
- (pProcess != NULL && ImageBase >= (PVOID)KERNEL_BASE))
- {
- return(STATUS_INVALID_PARAMETER_3);
- }
- if (((ImageSize >> BucketSize) * 4) >= BufferSize)
- {
- return(STATUS_BUFFER_TOO_SMALL);
- }
- if (ProfileSource != ProfileTime)
- {
- return(STATUS_INVALID_PARAMETER_9);
- }
- if (Affinity != 0)
- {
- return(STATUS_INVALID_PARAMETER_10);
- }
+ /* Create the object */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ Status = ObCreateObject(KernelMode,
+ ExProfileObjectType,
+ &ObjectAttributes,
+ PreviousMode,
+ NULL,
+ sizeof(EPROFILE),
+ 0,
+ 0,
+ (PVOID*)&Profile);
+ if (!NT_SUCCESS(Status)) return(Status);
- /*
- * Create the object
- */
- InitializeObjectAttributes(&ObjectAttributes,
+ /* Initialize it */
+ Profile->ImageBase = ImageBase;
+ Profile->ImageSize = ImageSize;
+ Profile->Buffer = Buffer;
+ Profile->BufferSize = BufferSize;
+ Profile->BucketSize = BucketSize;
+ Profile->LockedBuffer = NULL;
+ Profile->Affinity = Affinity;
+ Profile->Process = pProcess;
+
+ /* Insert into the Object Tree */
+ Status = ObInsertObject ((PVOID)Profile,
NULL,
+ PROFILE_CONTROL,
0,
NULL,
- NULL);
-
- Status = ObCreateObject(KernelMode,
- ExProfileObjectType,
- &ObjectAttributes,
- PreviousMode,
- NULL,
- sizeof(KPROFILE),
- 0,
- 0,
- (PVOID*)&Profile);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- /*
- * Initialize it
- */
- Profile->Base = ImageBase;
- Profile->Size = ImageSize;
- Profile->BucketShift = BucketSize;
- Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize);
- if(Profile->BufferMdl == NULL) {
- DPRINT("MmCreateMdl: Out of memory!");
- ObDereferenceObject (Profile);
- return(STATUS_NO_MEMORY);
- }
- MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess);
- Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl);
- Profile->BufferSize = BufferSize;
- Profile->ProcessorMask = Affinity;
- Profile->Started = FALSE;
- Profile->Process = pProcess;
-
- /*
- * Insert the profile into the profile list data structures
- */
- KiInsertProfile(Profile);
-
- Status = ObInsertObject ((PVOID)Profile,
- NULL,
- STANDARD_RIGHTS_ALL,
- 0,
- NULL,
- &hProfile);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (Profile);
- return Status;
+ &hProfile);
+ ObDereferenceObject(Profile);
+
+ /* Check for Success */
+ if (!NT_SUCCESS(Status)) {
+
+ /* Dereference Process on failure */
+ if (pProcess) ObDereferenceObject(pProcess);
+ return Status;
}
+
+ /* Copy the created handle back to the caller*/
+ _SEH_TRY {
+
+ *ProfileHandle = hProfile;
+
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
- /*
- * Copy the created handle back to the caller
- */
- _SEH_TRY
- {
- *ProfileHandle = hProfile;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- ObDereferenceObject(Profile);
-
- return Status;
+ /* Return Status */
+ return Status;
}
-NTSTATUS STDCALL
-NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
- OUT PULONG Interval)
+NTSTATUS
+STDCALL
+NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter,
+ OUT PLARGE_INTEGER PerformanceFrequency
OPTIONAL)
{
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ LARGE_INTEGER PerfFrequency;
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(Interval,
- sizeof(ULONG),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ /* Check the Parameters for validity */
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWrite(PerformanceCounter,
+ sizeof(LARGE_INTEGER),
+ sizeof(ULONG));
+
+ ProbeForWrite(PerformanceFrequency,
+ sizeof(LARGE_INTEGER),
+ sizeof(ULONG));
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
- if(!NT_SUCCESS(Status))
- {
- return Status;
+ if(!NT_SUCCESS(Status)) return Status;
}
- }
- if (ProfileSource == ProfileTime)
- {
- ULONG ReturnInterval;
-
- /* FIXME: What units does this use, for now nanoseconds */
- ReturnInterval = 100;
-
- _SEH_TRY
- {
- *Interval = ReturnInterval;
- }
- _SEH_HANDLE
- {
+ _SEH_TRY {
+
+ /* Query the Kernel */
+ *PerformanceCounter =
KeQueryPerformanceCounter(&PerfFrequency);
+
+ /* Return Frequency if requested */
+ if(PerformanceFrequency) {
+
+ *PerformanceFrequency = PerfFrequency;
+ }
+ } _SEH_HANDLE {
+
Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- return Status;
- }
- return STATUS_INVALID_PARAMETER_2;
-}
+
+ } _SEH_END;
-NTSTATUS STDCALL
-NtSetIntervalProfile(IN ULONG Interval,
- IN KPROFILE_SOURCE Source)
-{
- return(STATUS_NOT_IMPLEMENTED);
+ return Status;
}
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtStartProfile(IN HANDLE ProfileHandle)
{
- PKPROFILE Profile;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PEPROFILE Profile;
+ PKPROFILE KeProfile;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PVOID TempLockedBuffer;
+ NTSTATUS Status;
- PAGED_CODE();
+ PAGED_CODE();
- PreviousMode = ExGetPreviousMode();
-
- Status = ObReferenceObjectByHandle(ProfileHandle,
- STANDARD_RIGHTS_ALL,
- ExProfileObjectType,
- PreviousMode,
- (PVOID*)&Profile,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(ProfileHandle,
+ PROFILE_CONTROL,
+ ExProfileObjectType,
+ PreviousMode,
+ (PVOID*)&Profile,
+ NULL);
+ if (!NT_SUCCESS(Status)) return(Status);
+
+ /* To avoid a Race, wait on the Mutex */
+ KeWaitForSingleObject(&ExpProfileMutex,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
+ /* The Profile can still be enabled though, so handle that */
+ if (Profile->LockedBuffer) {
+
+ /* Release our lock, dereference and return */
+ KeReleaseMutex(&ExpProfileMutex, FALSE);
+ ObDereferenceObject(Profile);
+ return STATUS_PROFILING_NOT_STOPPED;
}
- Profile->Started = TRUE;
- ObDereferenceObject(Profile);
- return(STATUS_SUCCESS);
+
+ /* Allocate a Kernel Profile Object. */
+ KeProfile = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(EPROFILE),
+ TAG('P', 'r', 'o',
'f'));
+
+ /* Allocate the Mdl Structure */
+ Profile->Mdl = MmCreateMdl(NULL, Profile->Buffer,
Profile->BufferSize);
+
+ /* Probe and Lock for Write Access */
+ MmProbeAndLockPages(Profile->Mdl, PreviousMode, IoWriteAccess);
+
+ /* Map the pages */
+ TempLockedBuffer = MmMapLockedPages(Profile->Mdl, KernelMode);
+
+ /* Initialize the Kernel Profile Object */
+ Profile->KeProfile = KeProfile;
+ KeInitializeProfile(KeProfile,
+ (PKPROCESS)Profile->Process,
+ Profile->ImageBase,
+ Profile->ImageSize,
+ Profile->BucketSize,
+ Profile->ProfileSource,
+ Profile->Affinity);
+
+ /* Start the Profiling */
+ KeStartProfile(KeProfile, TempLockedBuffer);
+
+ /* Now it's safe to save this */
+ Profile->LockedBuffer = TempLockedBuffer;
+
+ /* Release mutex, dereference and return */
+ KeReleaseMutex(&ExpProfileMutex, FALSE);
+ ObDereferenceObject(Profile);
+ return STATUS_SUCCESS;
}
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtStopProfile(IN HANDLE ProfileHandle)
{
- PKPROFILE Profile;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PEPROFILE Profile;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status;
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
+ PAGED_CODE();
- Status = ObReferenceObjectByHandle(ProfileHandle,
- STANDARD_RIGHTS_ALL,
- ExProfileObjectType,
- PreviousMode,
- (PVOID*)&Profile,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(ProfileHandle,
+ PROFILE_CONTROL,
+ ExProfileObjectType,
+ PreviousMode,
+ (PVOID*)&Profile,
+ NULL);
+ if (!NT_SUCCESS(Status)) return(Status);
+
+ /* Get the Mutex */
+ KeWaitForSingleObject(&ExpProfileMutex,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
+ /* Make sure the Profile Object is really Started */
+ if (!Profile->LockedBuffer) {
+
+ Status = STATUS_PROFILING_NOT_STARTED;
+ goto Exit;
}
- Profile->Started = FALSE;
- ObDereferenceObject(Profile);
- return(STATUS_SUCCESS);
+
+ /* Stop the Profile */
+ KeStopProfile(Profile->KeProfile);
+
+ /* Unlock the Buffer */
+ MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl);
+ MmUnlockPages(Profile->Mdl);
+ ExFreePool(Profile->KeProfile);
+
+ /* Clear the Locked Buffer pointer, meaning the Object is Stopped
*/
+ Profile->LockedBuffer = NULL;
+
+Exit:
+ /* Release Mutex, Dereference and Return */
+ KeReleaseMutex(&ExpProfileMutex, FALSE);
+ ObDereferenceObject(Profile);
+ return Status;
}
+NTSTATUS
+STDCALL
+NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
+ OUT PULONG Interval)
+{
+ KPROCESSOR_MODE PreviousMode= ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG ReturnInterval;
+
+ PAGED_CODE();
+
+ /* Check the Parameters for validity */
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWrite(Interval,
+ sizeof(ULONG),
+ sizeof(ULONG));
+
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Query the Interval */
+ ReturnInterval = KeQueryIntervalProfile(ProfileSource);
+ /* Return the data */
+ _SEH_TRY {
+
+ *Interval = ReturnInterval;
+
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+
+ /* Return Success */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+STDCALL
+NtSetIntervalProfile(IN ULONG Interval,
+ IN KPROFILE_SOURCE Source)
+{
+ /* Let the Kernel do the job */
+ KeSetIntervalProfile(Interval, Source);
+
+ /* Nothing can go wrong */
+ return STATUS_SUCCESS;
+}
_____
Modified:
branches/alex_devel_branch/reactos/ntoskrnl/include/internal/ke.h
--- branches/alex_devel_branch/reactos/ntoskrnl/include/internal/ke.h
2005-03-03 02:46:43 UTC (rev 13804)
+++ branches/alex_devel_branch/reactos/ntoskrnl/include/internal/ke.h
2005-03-03 03:57:59 UTC (rev 13805)
@@ -64,56 +64,26 @@
/* next file
***************************************************************/
-typedef struct _KPROCESS_PROFILE
-/*
- * List of the profile data structures associated with a process.
- */
-{
- LIST_ENTRY ProfileListHead;
- LIST_ENTRY ListEntry;
- HANDLE Pid;
-} KPROCESS_PROFILE, *PKPROCESS_PROFILE;
+typedef struct _KPROFILE_SOURCE_OBJECT {
+ KPROFILE_SOURCE Source;
+ LIST_ENTRY ListEntry;
+} KPROFILE_SOURCE_OBJECT, *PKPROFILE_SOURCE_OBJECT;
-typedef struct _KPROFILE
/*
* Describes a contiguous region of process memory that is being
profiled.
*/
-{
- CSHORT Type;
- CSHORT Name;
-
- /* Entry in the list of profile data structures for this process. */
- LIST_ENTRY ListEntry;
-
- /* Base of the region being profiled. */
- PVOID Base;
-
- /* Size of the region being profiled. */
- ULONG Size;
-
- /* Shift of offsets from the region to buckets in the profiling
buffer. */
- ULONG BucketShift;
-
- /* MDL which described the buffer that receives profiling data. */
- struct _MDL *BufferMdl;
-
- /* System alias for the profiling buffer. */
- PULONG Buffer;
-
- /* Size of the buffer for profiling data. */
- ULONG BufferSize;
-
- /*
- * Mask of processors for which profiling data should be collected.
- * Currently unused.
- */
- ULONG ProcessorMask;
-
- /* TRUE if profiling has been started for this region. */
- BOOLEAN Started;
-
- /* Pointer (and reference) to the process which is being profiled. */
- struct _EPROCESS *Process;
+typedef struct _KPROFILE {
+ CSHORT Type;
+ CSHORT Size;
+ LIST_ENTRY ListEntry;
+ PVOID RegionStart;
+ ULONG RegionEnd;
+ ULONG BucketShift;
+ PVOID Buffer;
+ CSHORT Source;
+ ULONG Affinity;
+ BOOLEAN Active;
+ struct _KPROCESS *Process;
} KPROFILE, *PKPROFILE;
/* Cached modules from the loader block */
@@ -130,8 +100,36 @@
VOID STDCALL
DbgBreakPointNoBugCheck(VOID);
+STDCALL
VOID
+KeInitializeProfile(struct _KPROFILE* Profile,
+ struct _KPROCESS* Process,
+ PVOID ImageBase,
+ ULONG ImageSize,
+ ULONG BucketSize,
+ KPROFILE_SOURCE ProfileSource,
+ KAFFINITY Affinity);
+
STDCALL
+VOID
+KeStartProfile(struct _KPROFILE* Profile,
+ PVOID Buffer);
+
+STDCALL
+VOID
+KeStopProfile(struct _KPROFILE* Profile);
+
+STDCALL
+ULONG
+KeQueryIntervalProfile(KPROFILE_SOURCE ProfileSource);
+
+STDCALL
+VOID
+KeSetIntervalProfile(KPROFILE_SOURCE ProfileSource,
+ ULONG Interval);
+
+VOID
+STDCALL
KeProfileInterrupt(
PKTRAP_FRAME TrapFrame
);
@@ -143,14 +141,6 @@
IN KPROFILE_SOURCE Source
);
-VOID KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip);
-VOID KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip);
-VOID KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE
Profile);
-VOID KiInsertProfile(PKPROFILE Profile);
-VOID KiRemoveProfile(PKPROFILE Profile);
-VOID STDCALL KiDeleteProfile(PVOID ObjectBody);
-
-
VOID STDCALL KeUpdateSystemTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
_____
Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/kqueue.c
--- branches/alex_devel_branch/reactos/ntoskrnl/ke/kqueue.c
2005-03-03 02:46:43 UTC (rev 13804)
+++ branches/alex_devel_branch/reactos/ntoskrnl/ke/kqueue.c
2005-03-03 03:57:59 UTC (rev 13805)
@@ -1,11 +1,13 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: ReactOS kernel
* FILE: ntoskrnl/ke/kqueue.c
* PURPOSE: Implement device queues
*
- * PROGRAMMERS: David Welch (welch(a)mcmail.com)
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net) - Several
optimizations and implement
+ * usage of Inserted
flag + reformat and
+ * add debug output.
+ * David Welch (welch(a)mcmail.com)
*/
/* INCLUDES
****************************************************************/
@@ -16,216 +18,255 @@
/* FUNCTIONS
*****************************************************************/
+/*
+ * @implemented
+ *
+ * FUNCTION: Intializes a device queue
+ * ARGUMENTS:
+ * DeviceQueue = Device queue to initialize
+ */
+VOID
+STDCALL
+KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
+{
+ /* Initialize the Header */
+ DeviceQueue->Type = DeviceQueueObject;
+ DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
+
+ /* Initialize the Listhead and Spinlock */
+ InitializeListHead(&DeviceQueue->DeviceListHead);
+ KeInitializeSpinLock(&DeviceQueue->Lock);
+
+ /* Set it as busy */
+ DeviceQueue->Busy=FALSE;
+}
+
/*
* @implemented
+ *
+ * FUNCTION: Inserts an entry in a device queue
+ * ARGUMENTS:
+ * DeviceQueue = Queue to insert the entry in
+ * DeviceQueueEntry = Entry to insert
+ * RETURNS: False is the device queue wasn't busy
+ * True otherwise
*/
[truncated at 1000 lines; 947 more skipped]