windows-nt/Source/XPSP1/NT/base/ntos/cache/preftchp.h

1362 lines
29 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c<EFBFBD> 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