|
|
/*++
Copyright (c� 1999 Microsoft Corporation
Module Name:
preftchp.h
Abstract:
This module contains the private definitions for the kernel mode prefetcher for optimizing demand paging. Page faults for a scenario are logged and the next time scenario starts, these pages are prefetched efficiently via asynchronous paging I/O.
Author:
Stuart Sechrest (stuartse) Chuck Lenzmeier (chuckl) Cenk Ergan (cenke)
Revision History:
--*/
#ifndef _PREFTCHP_H
#define _PREFTCHP_H
//
// Define tags used in prefetcher routines.
//
#define CCPF_PREFETCHER_TAG 'fPcC'
#define CCPF_ALLOC_SCENARIO_TAG 'SPcC'
#define CCPF_ALLOC_TRACE_TAG 'TPcC'
#define CCPF_ALLOC_TRCBUF_TAG 'BPcC'
#define CCPF_ALLOC_SECTTBL_TAG 'sPcC'
#define CCPF_ALLOC_TRCDMP_TAG 'DPcC'
#define CCPF_ALLOC_QUERY_TAG 'qPcC'
#define CCPF_ALLOC_FILENAME_TAG 'FPcC'
#define CCPF_ALLOC_CONTEXT_TAG 'CPcC'
#define CCPF_ALLOC_INTRTABL_TAG 'IPcC'
#define CCPF_ALLOC_PREFSCEN_TAG 'pPcC'
#define CCPF_ALLOC_BOOTWRKR_TAG 'wPcC'
#define CCPF_ALLOC_VOLUME_TAG 'vPcC'
#define CCPF_ALLOC_READLIST_TAG 'LPcC'
#define CCPF_ALLOC_METADATA_TAG 'MPcC'
//
// Whether the scenario type is for a system-wide scenario, meaning that
// only it can be active while running.
//
#define CCPF_IS_SYSTEM_WIDE_SCENARIO_TYPE(ScenarioType) \
((ScenarioType) == PfSystemBootScenarioType)
//
// In the kernel, we have to look for named objects under this
// directory for them to visible to Win32 prefetcher service.
//
#define CCPF_BASE_NAMED_OBJ_ROOT_DIR L"\\BaseNamedObjects"
//
// This is the invalid index value used with section tables.
//
#define CCPF_INVALID_TABLE_INDEX (-1)
//
// This is the max number of file metadata that NTFS can prefetch
// at a time.
//
#define CCPF_MAX_FILE_METADATA_PREFETCH_COUNT 0x300
//
// Define structure to hold prefetcher parameters state.
//
typedef struct _CCPF_PREFETCHER_PARAMETERS {
//
// This is the named event that is used to signal the service that
// parameters have been updated.
//
HANDLE ParametersChangedEvent;
//
// This is the registry key containing prefetch parameters.
//
HANDLE ParametersKey;
//
// Fields used in registering for change notify on parameters
// registry key.
//
IO_STATUS_BLOCK RegistryWatchIosb; WORK_QUEUE_ITEM RegistryWatchWorkItem; ULONG RegistryWatchBuffer;
//
// System wide prefetching parameters. When using any parameters
// whose update may cause problems [e.g. strings], get the
// ParametersLock shared. When you need to update Parameters,
// after getting the ParametersLock exclusive, bump
// ParametersVersion before updating parameters.
//
PF_SYSTEM_PREFETCH_PARAMETERS Parameters; ERESOURCE ParametersLock; LONG ParametersVersion;
//
// Prefixes to registry values for different scenario types.
//
WCHAR *ScenarioTypePrefixes[PfMaxScenarioType];
//
// This is set to InitSafeBootMode during initialization.
//
ULONG SafeBootMode;
} CCPF_PREFETCHER_PARAMETERS, *PCCPF_PREFETCHER_PARAMETERS;
//
// Define structure to hold prefetcher's global state.
//
typedef struct _CCPF_PREFETCHER_GLOBALS {
//
// List of active traces and the lock to protect it. The number
// of items on this list is a global, since it is used by other
// kernel components to make a fast check.
//
LIST_ENTRY ActiveTraces; KSPIN_LOCK ActiveTracesLock;
//
// Pointer to the global trace if one is active. While there is a
// global trace active we don't trace & prefetch other scenarios.
// Boot tracing is an example of global trace.
//
struct _CCPF_TRACE_HEADER *SystemWideTrace;
//
// List and number of saved completed prefetch traces and lock to
// protect it.
//
LIST_ENTRY CompletedTraces; FAST_MUTEX CompletedTracesLock; LONG NumCompletedTraces;
//
// This is the named event that is used to signal the service that
// there are traces ready for it to get.
//
HANDLE CompletedTracesEvent;
//
// Prefetcher parameters.
//
CCPF_PREFETCHER_PARAMETERS Parameters;
} CCPF_PREFETCHER_GLOBALS, *PCCPF_PREFETCHER_GLOBALS;
//
// Reference count structure.
//
typedef struct _CCPF_REFCOUNT {
//
// When initialized or reset, this reference count starts from
// 1. When exclusive access is granted it stays at 0: even if it
// may get bumped by an AddRef by mistake, it will return to 0.
//
LONG RefCount;
//
// This is set when somebody wants to gain exclusive access to the
// protected structure.
//
LONG Exclusive;
} CCPF_REFCOUNT, *PCCPF_REFCOUNT;
//
// Define structures used for logging pagefaults:
//
//
// One of these is logged for every page fault.
//
typedef struct _CCPF_LOG_ENTRY {
//
// File offset of the page that was faulted.
//
ULONG FileOffset;
//
// Index into the section table in the trace header that helps us
// identify the file.
//
USHORT SectionId;
//
// Whether this page was faulted as an image page or data page.
//
BOOLEAN IsImage;
//
// Whether this is a fault that happened in the process in which
// the scenario is associated with.
//
BOOLEAN InProcess;
} CCPF_LOG_ENTRY, *PCCPF_LOG_ENTRY;
//
// CCPF_LOG_ENTRIES is a buffer of log entries with a small header containing
// an index to the highest used entry. This is used so that a trace can consist
// of several smaller trace buffers instead of one large, fixed-size buffer.
// The current index must be contained in the buffer in order to allow entries
// to be added without acquiring a spin lock.
//
typedef struct _CCPF_LOG_ENTRIES {
//
// Link used to put this buffer in the traces's buffer list.
//
LIST_ENTRY TraceBuffersLink;
//
// NumEntries is the current number of entries in the buffer. MaxEntries
// is the maximum number of entries that can be placed in the buffer.
// (Currently MaxEntries always equals CCPF_TRACE_BUFFER_MAX_ENTRIES.)
//
LONG NumEntries; LONG MaxEntries;
//
// The logged entries start here.
//
CCPF_LOG_ENTRY Entries[1];
} CCPF_LOG_ENTRIES, *PCCPF_LOG_ENTRIES;
//
// CCPF_TRACE_BUFFER_SIZE is the size of an allocated CCPF_LOG_ENTRIES structure
// (including the header). This should be a multiple of the page size.
//
#define CCPF_TRACE_BUFFER_SIZE 8192
//
// CCPF_TRACE_BUFFER_MAX_ENTRIES is the number of log entries that will fit in
// a trace buffer of size CCPF_TRACE_BUFFER_SIZE.
//
#define CCPF_TRACE_BUFFER_MAX_ENTRIES (((CCPF_TRACE_BUFFER_SIZE - sizeof(CCPF_LOG_ENTRIES)) / sizeof(CCPF_LOG_ENTRY)) + 1)
//
// This structure associates a SectionObjectPointer with a file name
// in the runtime trace buffer. There is a table of these in the trace
// header and every page fault has an index into this table denoting
// which file it is to.
//
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _CCPF_SECTION_INFO {
//
// Section info entries are kept in a hash. This field is
// InterlockedCompareExchange'd to denote that it is in use.
//
LONG EntryValid;
//
// Whether this section is used for file systems to map metafile.
//
ULONG Metafile:1; ULONG Unused:31;
//
// SectionObjectPointer used as a unique identifier to a file
// mapping. The same file may be mapped using a number of file
// objects, but the SectionObjectPointer fields of all those file
// objects will be the same.
//
PSECTION_OBJECT_POINTERS SectionObjectPointer;
//
// All references to all file objects for a file may be released,
// and a new file may be opened using the same memory block for
// its FCB at which point the SectionObjectPointer would no longer
// be unique. This would result in pagefaults getting logged under
// the entry for the file that was closed. The consequences would
// be misprefetching wrong pages from a couple of sections until
// the scenario corrects itself by looking at new traces. By
// keeping track of these two fields of the SectionObjectPointers
// to check for uniqueness we make this case very unlikely to
// happen. The other solutions we thought of to solve this issue
// 100% were too costly in terms of complication or efficiency.
//
//
// In order to avoid adding two entries to the table for the
// section when it is used as data first then image (or vice
// versa) it is assumed that it is still the same section if the
// current entry's Data/ImageSectionObject is NULL but the
// Data/ImageSectionObject of the section we are logging a new
// pagefault to is not. Then we try to update the NULL pointer
// with the new value using InterlockedCompareExchangePointer.
//
PVOID DataSectionObject; PVOID ImageSectionObject;
//
// This may point to a file object that we have referenced to
// ensure the section object stays around until we can get a name.
//
PFILE_OBJECT ReferencedFileObject;
//
// The name is set as soon as we can get a file name. We cannot
// access the file name while running at a high IRQL.
//
WCHAR *FileName;
//
// We queue a section to the get-file-name list using this field.
//
SINGLE_LIST_ENTRY GetNameLink;
} CCPF_SECTION_INFO, *PCCPF_SECTION_INFO;
//
// This structure contains information on a volume on which sections
// in the trace are located on.
//
typedef struct _CCPF_VOLUME_INFO { //
// Link in the trace's volume list.
//
LIST_ENTRY VolumeLink;
//
// Volume creation time and serial number used to identify the
// volume in case its NT/device path e.g. \Device\HarddiskVolume1
// changes.
//
LARGE_INTEGER CreationTime; ULONG SerialNumber;
//
// Current NT/device path for the volume and its length in
// characters excluding terminating NUL.
//
ULONG VolumePathLength; WCHAR VolumePath[1];
} CCPF_VOLUME_INFO, *PCCPF_VOLUME_INFO;
//
// This is the runtime trace header for a scenario.
//
typedef struct _CCPF_TRACE_HEADER {
//
// Magic number identifying this structure as a trace.
//
ULONG Magic;
//
// Link in the active traces list.
//
LIST_ENTRY ActiveTracesLink;
//
// Scenario id for which we are acquiring this trace.
//
PF_SCENARIO_ID ScenarioId;
//
// Type of this scenario.
//
PF_SCENARIO_TYPE ScenarioType;
//
// CurrentTraceBuffer is the active trace buffer.
//
PCCPF_LOG_ENTRIES CurrentTraceBuffer;
//
// This is the list of trace buffers for this trace.
// CurrentTraceBuffer is the last element. Both this list and
// CurrentTraceBuffer are protected by TraceBufferSpinLock.
//
LIST_ENTRY TraceBuffersList; ULONG NumTraceBuffers; KSPIN_LOCK TraceBufferSpinLock;
//
// This is the table for section info.
//
PCCPF_SECTION_INFO SectionInfoTable; LONG NumSections; LONG MaxSections; ULONG SectionTableSize;
//
// We don't log timestamps with page faults but it helps to know
// how many we are logging per given time. This information can be
// used to mark the end of a scenario.
//
KTIMER TraceTimer; LARGE_INTEGER TraceTimerPeriod; KDPC TraceTimerDpc; KSPIN_LOCK TraceTimerSpinLock; //
// This array contains the number of page faults logged per trace
// period.
//
ULONG FaultsPerPeriod[PF_MAX_NUM_TRACE_PERIODS]; LONG LastNumFaults; LONG CurPeriod; //
// NumFaults is the number of faults that have been logged so far, in all
// trace buffers. MaxFaults is the maximum number of page faults we will
// log, in all trace buffers.
//
LONG NumFaults; LONG MaxFaults;
//
// This workitem is queued to get names for file objects we are
// logging page faults to. First GetFileNameWorkItemQueued should
// be InterlockedCompareExchange'd from 0 to 1 and a reference
// should be acquired on the scenario. The workitem will free this
// reference just before it completes.
//
WORK_QUEUE_ITEM GetFileNameWorkItem; LONG GetFileNameWorkItemQueued;
//
// Sections for which we have to get names are pushed and popped
// to/from this slist.
//
SLIST_HEADER SectionsWithoutNamesList;
//
// Because we don't want to incur the cost of queuing a work item
// to get file names for every one or two sections, the worker we
// queue will wait on this event before returning. The event can
// be signaled when a new section comes, or when the scenario is
// ending.
//
KEVENT GetFileNameWorkerEvent;
//
// This is the process we are associated with.
//
PEPROCESS Process;
//
// This is the removal reference count protecting us.
//
CCPF_REFCOUNT RefCount;
//
// This work item can be queued to call the end trace function if
// the trace times out or we log to many entries etc. First
// EndTraceCalled should be InterlockedCompareExchange'd from 0 to
// 1.
//
WORK_QUEUE_ITEM EndTraceWorkItem;
//
// Before anybody calls end trace function, they have to
// InterlockedCompareExchange this from 0 to 1 to ensure this
// function gets called only once.
//
LONG EndTraceCalled;
//
// This is the list of volumes the sections we are tracing are
// located on. It is sorted lexically by the volume NT/device path.
//
LIST_ENTRY VolumeList; ULONG NumVolumes;
//
// This is the pointer to the built trace dump from this runtime
// trace structure and the status with which dumping failed if it
// did.
//
struct _CCPF_TRACE_DUMP *TraceDump; NTSTATUS TraceDumpStatus;
//
// System time when we started tracing.
//
LARGE_INTEGER LaunchTime;
} CCPF_TRACE_HEADER, *PCCPF_TRACE_HEADER;
//
// This structure is used to save completed traces in a list. The
// trace extends beyond this structure as necessary.
//
typedef struct _CCPF_TRACE_DUMP { //
// Link in the completed traces list.
//
LIST_ENTRY CompletedTracesLink; //
// Completed trace.
//
PF_TRACE_HEADER Trace;
} CCPF_TRACE_DUMP, *PCCPF_TRACE_DUMP;
//
// This structure contains information for a volume used during prefetching.
//
typedef struct _CCPF_PREFETCH_VOLUME_INFO {
//
// Link in the lists this volume gets put on.
//
LIST_ENTRY VolumeLink;
//
// Volume path.
//
WCHAR *VolumePath; ULONG VolumePathLength;
//
// Handle to the opened volume.
//
HANDLE VolumeHandle;
} CCPF_PREFETCH_VOLUME_INFO, *PCCPF_PREFETCH_VOLUME_INFO;
//
// This structure is used to keep track of prefetched pages & context.
//
//
// Note: This structure is used as a stack variable. Don't add events
// etc, without changing that.
//
typedef struct _CCPF_PREFETCH_HEADER {
//
// Pointer to prefetch instructions. The instructions should not
// be removed / freed until the prefetch header is cleaned up.
// E.g. VolumeNodes may point to volume paths in the scenario.
//
PPF_SCENARIO_HEADER Scenario;
//
// Nodes for the volumes we are going to prefetch from.
//
PCCPF_PREFETCH_VOLUME_INFO VolumeNodes;
//
// List of volumes we won't prefetch on.
//
LIST_ENTRY BadVolumeList;
//
// List of volumes we have opened. They are opened with the following
// flags: FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE
//
LIST_ENTRY OpenedVolumeList;
} CCPF_PREFETCH_HEADER, *PCCPF_PREFETCH_HEADER;
//
// Define types of prefetching CcPfPrefetchSections can be called to
// perform.
//
typedef enum _CCPF_PREFETCH_TYPE { CcPfPrefetchAllDataPages, CcPfPrefetchAllImagePages, CcPfPrefetchPartOfDataPages, CcPfPrefetchPartOfImagePages, CcPfMaxPrefetchType } CCPF_PREFETCH_TYPE, *PCCPF_PREFETCH_TYPE;
//
// This structure stands for the position in the prefetch
// instructions. It is used and updated by CcPfPrefetchSections when
// prefetching parts of a scenario at a time.
//
typedef struct _CCPF_PREFETCH_CURSOR { //
// Index of the current section and the page in that section.
//
ULONG SectionIdx; ULONG PageIdx; } CCPF_PREFETCH_CURSOR, *PCCPF_PREFETCH_CURSOR;
//
// This type is used in CcPfPrefetchSections.
//
typedef struct _SECTION *PSECTION;
//
// Define types of information CcPfQueryScenarioInformation can be
// asked to return.
//
typedef enum _CCPF_SCENARIO_INFORMATION_TYPE { CcPfBasicScenarioInformation, CcPfBootScenarioInformation, CcPfMaxScenarioInformationType } CCPF_SCENARIO_INFORMATION_TYPE, *PCCPF_SCENARIO_INFORMATION_TYPE;
//
// This structure contains basic scenario information.
//
typedef struct _CCPF_BASIC_SCENARIO_INFORMATION { //
// Number of pages that will be prefetched as data pages.
//
ULONG NumDataPages;
//
// Number of pages that will be prefetched as image pages.
//
ULONG NumImagePages;
//
// Number of sections for which only data pages will be
// prefetched.
//
ULONG NumDataOnlySections;
//
// Number of sections for which only image pages will be
// prefetched excluding the header page.
//
ULONG NumImageOnlySections;
//
// Number of ignored pages.
//
ULONG NumIgnoredPages;
//
// Number of ignored sections.
//
ULONG NumIgnoredSections;
} CCPF_BASIC_SCENARIO_INFORMATION, *PCCPF_BASIC_SCENARIO_INFORMATION;
//
// Routines used in the core prefetcher.
//
//
// Routines used in prefetch tracing.
//
NTSTATUS CcPfBeginTrace( IN PF_SCENARIO_ID *ScenarioId, IN PF_SCENARIO_TYPE ScenarioType, IN HANDLE ProcessHandle );
NTSTATUS CcPfActivateTrace( IN PCCPF_TRACE_HEADER Scenario );
NTSTATUS CcPfDeactivateTrace( IN PCCPF_TRACE_HEADER Scenario );
NTSTATUS CcPfEndTrace( IN PCCPF_TRACE_HEADER Trace );
NTSTATUS CcPfBuildDumpFromTrace( OUT PCCPF_TRACE_DUMP *TraceDump, IN PCCPF_TRACE_HEADER RuntimeTrace );
VOID CcPfCleanupTrace( IN PCCPF_TRACE_HEADER Trace );
VOID CcPfTraceTimerRoutine( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
NTSTATUS CcPfCancelTraceTimer( IN PCCPF_TRACE_HEADER Trace );
VOID CcPfEndTraceWorkerThreadRoutine( PVOID Parameter );
VOID CcPfGetFileNamesWorkerRoutine( PVOID Parameter );
LONG CcPfLookUpSection( PCCPF_SECTION_INFO Table, ULONG TableSize, PSECTION_OBJECT_POINTERS SectionObjectPointer, PLONG AvailablePosition );
NTSTATUS CcPfGetCompletedTrace ( PVOID Buffer, ULONG BufferSize, PULONG ReturnSize );
NTSTATUS CcPfUpdateVolumeList( PCCPF_TRACE_HEADER Trace, WCHAR *VolumePath, ULONG VolumePathLength ); //
// Routines used for prefetching and dealing with prefetch instructions.
//
NTSTATUS CcPfPrefetchScenario ( PPF_SCENARIO_HEADER Scenario );
NTSTATUS CcPfPrefetchSections( IN PCCPF_PREFETCH_HEADER PrefetchHeader, IN CCPF_PREFETCH_TYPE PrefetchType, OPTIONAL IN PCCPF_PREFETCH_CURSOR StartCursor, OPTIONAL ULONG TotalPagesToPrefetch, OPTIONAL OUT PULONG NumPagesPrefetched, OPTIONAL OUT PCCPF_PREFETCH_CURSOR EndCursor );
NTSTATUS CcPfPrefetchMetadata( IN PCCPF_PREFETCH_HEADER PrefetchHeader );
NTSTATUS CcPfPrefetchDirectoryContents( WCHAR *DirectoryPath, WCHAR DirectoryPathlength );
NTSTATUS CcPfPrefetchFileMetadata( HANDLE VolumeHandle, PFILE_PREFETCH FilePrefetch );
VOID CcPfInitializePrefetchHeader ( OUT PCCPF_PREFETCH_HEADER PrefetchHeader );
VOID CcPfCleanupPrefetchHeader ( IN PCCPF_PREFETCH_HEADER PrefetchHeader );
NTSTATUS CcPfGetPrefetchInstructions( IN PPF_SCENARIO_ID ScenarioId, IN PF_SCENARIO_TYPE ScenarioType, OUT PPF_SCENARIO_HEADER *Scenario );
NTSTATUS CcPfQueryScenarioInformation( IN PPF_SCENARIO_HEADER Scenario, IN CCPF_SCENARIO_INFORMATION_TYPE InformationType, OUT PVOID Buffer, IN ULONG BufferSize, OUT PULONG RequiredSize );
NTSTATUS CcPfOpenVolumesForPrefetch ( IN PCCPF_PREFETCH_HEADER PrefetchHeader );
PCCPF_PREFETCH_VOLUME_INFO CcPfFindPrefetchVolumeInfoInList( WCHAR *Path, PLIST_ENTRY List ); NTSTATUS CcPfGetSectionObject( IN PUNICODE_STRING FileName, IN LOGICAL ImageSection, OUT PVOID* SectionObject, OUT PFILE_OBJECT* FileObject, OUT HANDLE* FileHandle );
//
// Routines used for application launch prefetching.
//
BOOLEAN CcPfIsHostingApplication( IN PWCHAR ExecutableName );
NTSTATUS CcPfScanCommandLine( OUT PULONG PrefetchHint, OPTIONAL OUT PULONG HashId );
//
// Reference count functions:
//
VOID CcPfInitializeRefCount( PCCPF_REFCOUNT RefCount );
NTSTATUS FASTCALL CcPfAddRef( PCCPF_REFCOUNT RefCount );
VOID FASTCALL CcPfDecRef( PCCPF_REFCOUNT RefCount );
NTSTATUS FASTCALL CcPfAddRefEx( PCCPF_REFCOUNT RefCount, ULONG Count );
VOID FASTCALL CcPfDecRefEx( PCCPF_REFCOUNT RefCount, ULONG Count );
NTSTATUS CcPfAcquireExclusiveRef( PCCPF_REFCOUNT RefCount );
PCCPF_TRACE_HEADER CcPfReferenceProcessTrace( PEPROCESS Process );
PCCPF_TRACE_HEADER CcPfRemoveProcessTrace( PEPROCESS Process );
NTSTATUS CcPfAddProcessTrace( PEPROCESS Process, PCCPF_TRACE_HEADER Trace );
//
// Utility routines.
//
PWCHAR CcPfFindString ( PUNICODE_STRING SearchIn, PUNICODE_STRING SearchFor ); ULONG CcPfHashValue( PVOID Key, ULONG Len );
NTSTATUS CcPfIsVolumeMounted ( IN WCHAR *VolumePath, OUT BOOLEAN *VolumeMounted ); NTSTATUS CcPfQueryVolumeInfo ( IN WCHAR *VolumePath, OPTIONAL OUT HANDLE *VolumeHandleOut, OUT PLARGE_INTEGER CreationTime, OUT PULONG SerialNumber ); //
// Declarations and definitions for prefetcher parameters.
//
//
// Define location of registry key for prefetch parameters.
//
#define CCPF_PARAMETERS_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
//
// Maximum characters in registry value names for prefetch parameters.
//
#define CCPF_MAX_PARAMETER_NAME_LENGTH 80
//
// Maximum bytes needed to query a prefetch parameter from the
// registry. Currently our largest parameter would be the hosting
// application list.
//
#define CCPF_MAX_PARAMETER_VALUE_BUFFER ((PF_HOSTING_APP_LIST_MAX_CHARS * sizeof(WCHAR)) + sizeof(KEY_VALUE_PARTIAL_INFORMATION))
NTSTATUS CcPfParametersInitialize ( PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters ); VOID CcPfParametersSetDefaults ( PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters ); NTSTATUS CcPfParametersRead ( PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters ); NTSTATUS CcPfParametersSave ( PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters );
NTSTATUS CcPfParametersVerify ( PPF_SYSTEM_PREFETCH_PARAMETERS Parameters );
VOID CcPfParametersWatcher ( IN PVOID Context );
NTSTATUS CcPfParametersSetChangedEvent ( PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters );
NTSTATUS CcPfGetParameter ( HANDLE ParametersKey, WCHAR *ValueNameBuffer, ULONG ValueType, PVOID Value, ULONG *ValueSize );
NTSTATUS CcPfSetParameter ( HANDLE ParametersKey, WCHAR *ValueNameBuffer, ULONG ValueType, PVOID Value, ULONG ValueSize );
LOGICAL CcPfDetermineEnablePrefetcher( VOID );
//
// Declarations and definitions for boot prefetching.
//
//
// Value name under prefetcher parameters key where we store how long
// video initialization took during boot.
//
#define CCPF_VIDEO_INIT_TIME_VALUE_NAME L"VideoInitTime"
//
// How long (in milliseconds) video initialization could take max. This value
// is used to sanity check the value read from the registry.
//
#define CCPF_MAX_VIDEO_INIT_TIME (10 * 1000) // 10 seconds
//
// Value name under prefetcher parameters key where we store how many
// pages we should try to prefetch per second of video initialization.
//
#define CCPF_VIDEO_INIT_PAGES_PER_SECOND_VALUE_NAME L"VideoInitPagesPerSecond"
//
// Sanity check maximum value for video init pages per second.
//
#define CCPF_VIDEO_INIT_MAX_PAGES_PER_SECOND 128000
//
// How many pages will we try to prefetch in parallel to video initialization
// per second of it.
//
#define CCPF_VIDEO_INIT_DEFAULT_PAGES_PER_SECOND 1500
//
// Maximum number of chunks in which we will prefetch for boot.
//
#define CCPF_MAX_BOOT_PREFETCH_PHASES 16
//
// Different phases of boot we return page counts for in
// CCPF_BOOT_SCENARIO_INFORMATION.
//
typedef enum _CCPF_BOOT_SCENARIO_PHASE {
CcPfBootScenDriverInitPhase, CcPfBootScenSubsystemInitPhase, CcPfBootScenSystemProcInitPhase, CcPfBootScenServicesInitPhase, CcPfBootScenUserInitPhase, CcPfBootScenMaxPhase
} CCPF_BOOT_SCENARIO_PHASE, *PCCPF_BOOT_SCENARIO_PHASE;
//
// Define structure to hold boot prefetching state.
//
typedef struct _CCPF_BOOT_PREFETCHER {
//
// These events are signaled by the boot prefetch worker when
// it has completed prefetching for the specified phase.
//
KEVENT SystemDriversPrefetchingDone; KEVENT PreSmssPrefetchingDone; KEVENT VideoInitPrefetchingDone;
//
// This event will be signaled when we start initializing video
// on the console. Boot prefetcher waits on this event to perform
// prefetching parallel to video initialization.
//
KEVENT VideoInitStarted;
} CCPF_BOOT_PREFETCHER, *PCCPF_BOOT_PREFETCHER;
//
// This structure contains boot scenario information.
//
typedef struct _CCPF_BOOT_SCENARIO_INFORMATION {
//
// These are the number of data/image pages to prefetch for the
// different phase of boot.
//
ULONG NumDataPages[CcPfBootScenMaxPhase]; ULONG NumImagePages[CcPfBootScenMaxPhase]; } CCPF_BOOT_SCENARIO_INFORMATION, *PCCPF_BOOT_SCENARIO_INFORMATION;
//
// We will be prefetching data and image pages for boot in parts. Since the
// code is mostly same to prefetch the data and image pages, we keep track
// of where we left off and what to prefetch next in a common boot prefetch
// cursor structure and make two passes (first for data, then for image).
//
typedef struct _CCPF_BOOT_PREFETCH_CURSOR {
//
// Start & end cursors passed to prefetch sections function.
//
CCPF_PREFETCH_CURSOR StartCursor; CCPF_PREFETCH_CURSOR EndCursor;
//
// How to prefetch (e.g. part of data pages or part of image pages).
//
CCPF_PREFETCH_TYPE PrefetchType;
//
// How many pages to prefetch per phase.
//
ULONG NumPagesForPhase[CCPF_MAX_BOOT_PREFETCH_PHASES]; } CCPF_BOOT_PREFETCH_CURSOR, *PCCPF_BOOT_PREFETCH_CURSOR;
//
// Boot prefetching routines.
//
VOID CcPfBootWorker( PCCPF_BOOT_PREFETCHER BootPrefetcher );
NTSTATUS CcPfBootQueueEndTraceTimer ( PLARGE_INTEGER Timeout );
VOID CcPfEndBootTimerRoutine( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
//
// Debug routines.
//
#if CCPF_DBG
NTSTATUS CcPfWriteToFile( IN PVOID pData, IN ULONG Size, IN WCHAR *pFileName );
#endif // CCPF_DBG
//
// Define useful macros. As with all macros, must be careful of
// parameter reevalation. Don't use expressions as macro parameters.
//
#define CCPF_MAX(A,B) (((A) >= (B)) ? (A) : (B))
#define CCPF_MIN(A,B) (((A) <= (B)) ? (A) : (B))
//
// Define debugging macros:
//
//
// Define the component ID we use.
//
#define CCPFID DPFLTR_PREFETCHER_ID
//
// Define DbgPrintEx levels.
//
#define PFERR DPFLTR_ERROR_LEVEL
#define PFWARN DPFLTR_WARNING_LEVEL
#define PFTRC DPFLTR_TRACE_LEVEL
#define PFINFO DPFLTR_INFO_LEVEL
#define PFPREF 4
#define PFPRFD 5
#define PFPRFF 6
#define PFPRFZ 7
#define PFTRAC 8
#define PFTMR 9
#define PFNAME 10
#define PFNAMS 11
#define PFLKUP 12
#define PFBOOT 13
//
// DbgPrintEx levels 20 - 31 are reserved for the service.
//
//
// This may help you determine what to set the DbgPrintEx mask.
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
//
// CCPF_DBG can be defined if you want to turn on asserts and debug
// prints in prefetcher code but you do not want to have a checked
// kernel. Defining CCPF_DBG overrides defining DBG.
//
#if CCPF_DBG
NTSYSAPI VOID NTAPI RtlAssert( PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCHAR Message );
#define DBGPR(x) DbgPrintEx x
#define CCPF_ASSERT(x) if (!(x)) RtlAssert(#x, __FILE__, __LINE__, NULL )
#else // CCPF_DBG
//
// If CCPF_DBG is not defined, build with debug prints and asserts
// only on checked build.
//
#if DBG
#define DBGPR(x) DbgPrintEx x
#define CCPF_ASSERT(x) ASSERT(x)
#else // DBG
//
// On a free build we don't compile with debug prints or asserts.
//
#define DBGPR(x)
#define CCPF_ASSERT(x)
#endif // DBG
#endif // CCPF_DBG
#endif // _PREFTCHP_H
|