|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
prefetch.h
Abstract:
This module contains the prefetcher definitions that are shared between the kernel mode component and the user mode service.
Author:
Stuart Sechrest (stuartse) Cenk Ergan (cenke) Chuck Leinzmeier (chuckl)
Revision History:
*/
#ifndef _PREFETCH_H #define _PREFETCH_H
// // Prefetcher version. Be sure to update this after making any changes // to any defines or structures in this file. When in doubt, update // the version. //
#define PF_CURRENT_VERSION 17
// // Magic numbers to identify scenario dump files. //
#define PF_SCENARIO_MAGIC_NUMBER 0x41434353 #define PF_TRACE_MAGIC_NUMBER 0x43435341 #define PF_SYSINFO_MAGIC_NUMBER 0x6B756843
// // Define various limits used in sanity checking a prefetch scenario. // Do not use these limits except for sanity checking. Most of these are // very large values that are overkills. //
#define PF_MAXIMUM_PAGES (128*1024) #define PF_MAXIMUM_LOG_ENTRIES PF_MAXIMUM_PAGES #define PF_MAXIMUM_SECTION_PAGES 8192 // ISSUE-2002/02/21-ScottMa -- The following maximum is also used for // obtaining the VolumePath. Should they be the same value? #define PF_MAXIMUM_SECTION_FILE_NAME_LENGTH 1024 #define PF_MAXIMUM_FILE_NAME_DATA_SIZE (4*1024*1024) #define PF_MAXIMUM_TIMER_PERIOD (-1i64 * 10 * 60 * 1000 * 1000 * 10) #define PF_MAXIMUM_ACTIVE_TRACES 4096 #define PF_MAXIMUM_SAVED_TRACES 4096
// // This is the maximum size a scenario can grow to. //
#define PF_MAXIMUM_SCENARIO_SIZE (16*1024*1024)
// // This is the maximum size a trace file can grow to. It is a function // of the limits above. //
#define PF_MAXIMUM_TRACE_SIZE PF_MAXIMUM_SCENARIO_SIZE
// // Maximum allowed sections in a scenario should fit into a USHORT, // sizeof the SectionId field in log entries. //
#define PF_MAXIMUM_SECTIONS 16384
// // Maximum number of unique directories the files for a scenario can // be in. This is a sanity check constant. //
#define PF_MAXIMUM_DIRECTORIES (PF_MAXIMUM_SECTIONS * 32)
// // Minimum size in pages for new scenarios. Smaller traces will be discarded. //
#define PF_MIN_SCENARIO_PAGES 32
// // Define various types of prefetch scenarios (starting from 0). //
typedef enum _PF_SCENARIO_TYPE { PfApplicationLaunchScenarioType, PfSystemBootScenarioType, PfMaxScenarioType, } PF_SCENARIO_TYPE;
// // Define structure used to identify traces and prefetch instructions // for a scenario. For application launch scenarios, it consists of // the first characters in the executable image's name (NUL // terminated) and a hash of its full path including the image // name. Both path and image name are uppercased. On a file system // with case sensitive names executables at the same path with the // same name except for case will get the same id. //
#define PF_SCEN_ID_MAX_CHARS 29
typedef struct _PF_SCENARIO_ID { WCHAR ScenName[PF_SCEN_ID_MAX_CHARS + 1]; ULONG HashId; } PF_SCENARIO_ID, *PPF_SCENARIO_ID;
// // This is the scenario name and hash code value for the boot scenario. //
#define PF_BOOT_SCENARIO_NAME L"NTOSBOOT" #define PF_BOOT_SCENARIO_HASHID 0xB00DFAAD
// // Extension for the prefetch files. //
#define PF_PREFETCH_FILE_EXTENSION L"pf"
// // A scenario id can be converted to a file name using the following // sprintf format, using ScenName, HashId and prefetch file extension. //
#define PF_SCEN_FILE_NAME_FORMAT L"%ws-%08X.%ws"
// // This is the maximum number of characters in a scenario file name // (not path) given the format and definitions above with some head // room. //
#define PF_MAX_SCENARIO_FILE_NAME 50
// // Define the number of periods over which we track page faults for a // scenario. The duration of the periods depend on the scenario type. //
#define PF_MAX_NUM_TRACE_PERIODS 10
// // Define maximum number of characters for the relative path from // system root to where prefetch files can be found. //
#define PF_MAX_PREFETCH_ROOT_PATH 32
// // Define maximum number of characters for the list of known hosting // applications. //
#define PF_HOSTING_APP_LIST_MAX_CHARS 128
// // Define invalid page index used to terminate a section's page record // lists in scenarios. //
#define PF_INVALID_PAGE_IDX (-1)
// // Define the number of launches of the scenario we keep track of for // usage history of pages. In every page record there is a bit field // of this size. Do not grow this over 32, size of (ULONG). //
#define PF_PAGE_HISTORY_SIZE 8
// // Define the maximum and minimum scenario sensitivity. A page has to be // used in this many of the launches in the history for it to be prefetch. //
#define PF_MAX_SENSITIVITY PF_PAGE_HISTORY_SIZE #define PF_MIN_SENSITIVITY 1
// // Define structure for kernel trace dumps. The dump is all in a // single contiguous buffer at the top of which is the trace header // structure. The trace header contains offsets to an array of log // entries in the buffer and to a list of section info // structures. Section info structures come one after the other // containing file names. There is a log entry for every page // fault. Every log entry has a SectionId that is the number of the // section info structure that contains the name of the file the fault // was to. These are followed by variable sized volumeinfo entries // that describe the volumes on which the sections in the trace are // located. //
// // NOTE: Do not forget about alignment issues on 64 bit platforms as // you modify these structures or add new ones. //
// // One of these is logged for every page fault. //
typedef struct _PF_LOG_ENTRY {
// // File offset of the page that was faulted. // ULONG FileOffset;
// // Index into the section info 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 active. We may log faults in special system // process as a part of this scenario. //
// FUTURE-2002/02/21-ScottMa -- This field is never set in the kernel.
BOOLEAN InProcess;
} PF_LOG_ENTRY, *PPF_LOG_ENTRY;
// // This structure associates a page fault with a file name. // Note that because we lay these structures right after each other in // the trace buffer, if you add a new field which has an alignment // greater than 2 bytes, we'll hit alignment problems. //
typedef struct _PF_SECTION_INFO {
// // Number of characters in the file name, excluding terminating NUL. //
USHORT FileNameLength;
// // Whether this section is for filesystem metafile (e.g. directory.) //
USHORT Metafile:1; USHORT Unused:15;
// // Variable length file name buffer including terminating NUL. //
WCHAR FileName[1];
} PF_SECTION_INFO, *PPF_SECTION_INFO;
// // This structure describes a volume on which the sections in the // trace are on. //
typedef struct _PF_VOLUME_INFO {
// // 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];
} PF_VOLUME_INFO, *PPF_VOLUME_INFO;
// // This is the trace header. //
typedef struct _PF_TRACE_HEADER {
// // Prefetcher version. //
ULONG Version;
// // Magic number identifying this as a trace. //
ULONG MagicNumber;
// // Total size of the trace buffer in bytes. //
ULONG Size;
// // Scenario id for which this trace was acquired. //
PF_SCENARIO_ID ScenarioId;
// // Type of this scenario. //
PF_SCENARIO_TYPE ScenarioType;
// FUTURE-2002/02/20-ScottMa -- Consider reordering the following two // groups of fields to better reflect the in-memory structure of the // trace. Sections should appear first, followed by Entries, then // followed by Volumes.
// // Offset from the start of the trace buffer where logged // entries can be found and the number of them. // ULONG TraceBufferOffset; ULONG NumEntries;
// // Offset from the start of the trace buffer where the section and // file name information is located. // ULONG SectionInfoOffset; ULONG NumSections;
// // Offset from the start of the trace buffer where the volume // information is located, the number of volumes and the total // size of the volume information block. // ULONG VolumeInfoOffset; ULONG NumVolumes; ULONG VolumeInfoSize;
// // Distribution of the pagefaults over the duration of the trace. // PeriodLength is in 100ns. //
LONGLONG PeriodLength; ULONG FaultsPerPeriod[PF_MAX_NUM_TRACE_PERIODS];
// // System time when we started tracing this scenario as // returned by KeQuerySystemTime. //
LARGE_INTEGER LaunchTime;
} PF_TRACE_HEADER, *PPF_TRACE_HEADER;
// // Define structure for prefetch scenario instructions. The // instructions are all in a single contiguous buffer at the top of // which is the scenario header structure. The header contains offsets // to arrays of section and page records as well as a file name data // buffer. Every section contains an offset into the file name data // buffer where the file name for that section is located. It also has // an index into the page record table where the first page for that // section is located. Subsequent pages of the section are linked // through indices embedded in the page records. // // This data is followed by the file system metadata prefetch // instructions so opening the files will not be as expensive. These // instructions consist of metadata records that describe the metadata // that needs to be prefetched on the volumes containing the files to // be prefetched. //
// // NOTE: Do not forget about alignment issues on 64 bit platforms as // you modify these structures or add new ones. //
// // Define structure used for describing pages to be prefetched. //
typedef struct _PF_PAGE_RECORD { // // Index of the next page for this section in the page record // table or PF_INVALID_PAGE_IDX to terminate the list. //
LONG NextPageIdx;
// // File offset of the page that was faulted. //
ULONG FileOffset;
// // Whether we should just ignore this page record. //
ULONG IsIgnore:1;
// // Whether this page was faulted as an image page. //
ULONG IsImage:1;
// // Whether this page was faulted as a data page. //
ULONG IsData:1;
// // The following fields are only used by the service: //
// // Whether this page was used in the last PF_PAGE_HISTORY_SIZE // launches of the scenario. The least significant bit stands for // the most recent launch. If a bit is on, it means the page was // used in that launch. //
ULONG UsageHistory:PF_PAGE_HISTORY_SIZE;
// // Whether this page was prefetched in the last PF_PAGE_HISTORY_SIZE // launches of the scenario. The least significant bit stands for // the most recent launch. If a bit is on, it means the page was // prefetched in that launch. //
ULONG PrefetchHistory:PF_PAGE_HISTORY_SIZE;
} PF_PAGE_RECORD, *PPF_PAGE_RECORD;
// // Define structure used for describing sections to prefetch from. //
typedef struct _PF_SECTION_RECORD { // // Index of the first page for this section in the page record // table or PF_INVALID_PAGE_IDX to terminate the list. That page // will contain the index for the next page etc. // LONG FirstPageIdx;
// // Total number of page records for this section. //
ULONG NumPages;
// // Byte offset relative to the beginning of the file name data // block where the file path for this section can be found, and // the number of characters in the file path excluding NUL. //
ULONG FileNameOffset; ULONG FileNameLength;
// // Do we just ignore this section record. //
ULONG IsIgnore:1;
// // Was this section accessed through an image mapping. //
ULONG IsImage:1;
// // Was this section accessed through a data mapping. // ULONG IsData:1;
} PF_SECTION_RECORD, *PPF_SECTION_RECORD;
// // Define a counted string structure. It can be used to put paths one // after the other in the scenario/trace file. Its count coming before // the string would help us verify that the strings are terminated and // within bounds. The string is still NUL terminated. //
typedef struct _PF_COUNTED_STRING { // // Number of characters excluding the terminating NUL. Making this // a USHORT helps alignment when stacking counted strings one // after the other. //
USHORT Length; // // The NUL terminated string. // WCHAR String[1];
} PF_COUNTED_STRING, *PPF_COUNTED_STRING;
// // Define structure used for describing the filesystem metadata that // should be prefetched before prefetching the scenario. //
typedef struct _PF_METADATA_RECORD {
// // Byte offset relative to the beginning of metadata prefetch info // for the NUL terminated volume name on which the metadata to // prefetch resides. VolumeNameLength is in characters excluding // the terminating NUL. // ULONG VolumeNameOffset; ULONG VolumeNameLength;
// // In case volume's NT/device path changes, these magics are used // to identify the volume. // LARGE_INTEGER CreationTime; ULONG SerialNumber; // // Byte offset relative to the beginning of metadata prefetch info // for the input buffer to FSCTL to prefetch the metadata and its size. //
ULONG FilePrefetchInfoOffset; ULONG FilePrefetchInfoSize;
// // Byte offset relative to the beginning of metadata prefetch info // for the full paths of directories (PF_COUNTED_STRING's) that // need to be prefetched on this volume. The paths come one after // the other in the buffer. //
ULONG DirectoryPathsOffset; ULONG NumDirectories;
} PF_METADATA_RECORD, *PPF_METADATA_RECORD;
// // This is the scenario header. //
typedef struct _PF_SCENARIO_HEADER { // // Prefetcher version. //
ULONG Version;
// // Magic number identifying this as a scenario. //
ULONG MagicNumber;
// // This is the version of the prefetcher maintenance service that // generated this file. //
ULONG ServiceVersion;
// // Total size of the scenario. //
ULONG Size;
// // Scenario id identifying the scenario. //
PF_SCENARIO_ID ScenarioId;
// // Type of this scenario. //
PF_SCENARIO_TYPE ScenarioType;
// // Offset from the start of the scenario buffer where the section // info table is located. // ULONG SectionInfoOffset; ULONG NumSections;
// // Offset from the start of the scenario buffer where the page // records are located. //
ULONG PageInfoOffset; ULONG NumPages;
// // Offset from the start of the scenario buffer where file names // are located. //
ULONG FileNameInfoOffset; ULONG FileNameInfoSize;
// // Offset from the start of the scenario buffer where file system // metadata prefetch record table is located, number of these // structures and the size of the whole metadata prefetch // information. //
ULONG MetadataInfoOffset; ULONG NumMetadataRecords; ULONG MetadataInfoSize;
// // The following three fields are used to determine if a scenario // is getting launched too frequently (e.g. multiple times a // second/minute) for prefetching to be useful. //
// // This is the KeQuerySystemTime time of the last launch of this // scenario for which these scenario instructions were updated. //
LARGE_INTEGER LastLaunchTime;
// // If this much time (in 100ns) has not passed since last launch // time, we should not prefetch this scenario. //
LARGE_INTEGER MinRePrefetchTime;
// // If this much time (in 100ns) has not passed since last launch // time, we should not trace this scenario. //
LARGE_INTEGER MinReTraceTime;
// // The following fields are used only by the service: //
// // Number of times this scenario has been launched. //
ULONG NumLaunches;
// // A page should be used at least this many times in the last // PF_PAGE_HISTORY_SIZE launches to be prefetched. Otherwise the // ignore bit on the page is set. The kernel does not have look at // this variable. The sensitivity is adjusted dynamically by the // service according to the hit rate of the prefetched pages. //
ULONG Sensitivity;
} PF_SCENARIO_HEADER, *PPF_SCENARIO_HEADER;
// // Definitions for the interface between the kernel and the service. //
// // This is the name of the event that will be signaled by the kernel // when there are new scenario traces for the service. //
#define PF_COMPLETED_TRACES_EVENT_NAME L"\\BaseNamedObjects\\PrefetchTracesReady" #define PF_COMPLETED_TRACES_EVENT_WIN32_NAME L"PrefetchTracesReady"
// // This is the name of the event that gets signaled by the kernel when // parameters have changed. //
#define PF_PARAMETERS_CHANGED_EVENT_NAME L"\\BaseNamedObjects\\PrefetchParametersChanged" #define PF_PARAMETERS_CHANGED_EVENT_WIN32_NAME L"PrefetchParametersChanged"
// // Define sub information classes for SystemPrefetcherInformation. //
typedef enum _PREFETCHER_INFORMATION_CLASS { PrefetcherRetrieveTrace = 1, PrefetcherSystemParameters, PrefetcherBootPhase, } PREFETCHER_INFORMATION_CLASS;
// // This is the input structure to NtQuerySystemInformation / // NtSetSystemInformation for the SystemPrefetcherInformation // information class. //
typedef struct _PREFETCHER_INFORMATION { // // These two fields help make sure caller does not make bogus // requests and keep track of version for this kernel interface. //
ULONG Version; ULONG Magic;
// // Sub information class. //
PREFETCHER_INFORMATION_CLASS PrefetcherInformationClass;
// // Input / Output buffer and its length. //
PVOID PrefetcherInformation; ULONG PrefetcherInformationLength;
} PREFETCHER_INFORMATION, *PPREFETCHER_INFORMATION;
// // Define boot phase id's for use with PrefetcherBootPhase information // subclass. //
typedef enum _PF_BOOT_PHASE_ID { PfKernelInitPhase = 0, PfBootDriverInitPhase = 90, PfSystemDriverInitPhase = 120, PfSessionManagerInitPhase = 150, PfSMRegistryInitPhase = 180, PfVideoInitPhase = 210, PfPostVideoInitPhase = 240, PfBootAcceptedRegistryInitPhase = 270, PfUserShellReadyPhase = 300, PfMaxBootPhaseId = 900, } PF_BOOT_PHASE_ID, *PPF_BOOT_PHASE_ID;
// // Define system wide prefetch parameters structure. //
// // Whether a particular type of prefetching is enabled, disabled or // just not specified. //
typedef enum _PF_ENABLE_STATUS { PfSvNotSpecified, PfSvEnabled, PfSvDisabled, PfSvMaxEnableStatus } PF_ENABLE_STATUS, *PPF_ENABLE_STATUS;
// // Define limits structure for different prefetch types. //
typedef struct _PF_TRACE_LIMITS { // // Maximum number of pages that can be logged. //
ULONG MaxNumPages; // // Maximum number of sections that can be logged. //
ULONG MaxNumSections;
// // Period for the trace timer. The trace times out after // PF_MAX_NUM_TRACE_PERIODS. This is in 100ns. It should be // negative denoting to the system that periods are relative. // LONGLONG TimerPeriod;
} PF_TRACE_LIMITS, *PPF_TRACE_LIMITS;
// // System wide prefetch parameters structure. //
typedef struct _PF_SYSTEM_PREFETCH_PARAMETERS {
// // Whether different types of prefetching are enabled or not. // PF_ENABLE_STATUS EnableStatus[PfMaxScenarioType];
// // Limits for different prefetch types. //
PF_TRACE_LIMITS TraceLimits[PfMaxScenarioType];
// // Maximum number of active prefetch traces. //
ULONG MaxNumActiveTraces;
// // Maximum number of saved completed prefetch traces. // Note that this should be greater than the number of boot phases, // since the service won't be started until later in boot. //
// ISSUE-2002/02/20-ScottMa -- The default value for this parameter is 8, // but there appear to be 9 boot phases. Should the default be raised?
ULONG MaxNumSavedTraces;
// // Path to directory relative to system root where prefetch // instructions can be found. //
WCHAR RootDirPath[PF_MAX_PREFETCH_ROOT_PATH];
// ISSUE-2002/02/21-ScottMa -- The comment below should indicate that the // hosting applications string must be UPCASEd and there should not be // spaces after each comma.
// // Comma seperated list of hosting applications (e.g. dllhost.exe, mmc.exe, // rundll32.exe ...) for which we create scenario ID's based on command line // as well. //
WCHAR HostingApplicationList[PF_HOSTING_APP_LIST_MAX_CHARS];
} PF_SYSTEM_PREFETCH_PARAMETERS, *PPF_SYSTEM_PREFETCH_PARAMETERS;
// // Useful macros. //
// // Macros for alignment. Assumptions are that alignments are a power // of 2 and allocators (malloc, heap, pool etc) allocate chunks with // bigger alignment than what you need. You should verify these by // using asserts and the "power of two" macro below. //
// // Determines whether the value is a power of two. Zero is not a power // of 2. The value should be of an unsigned type that supports bit // operations, e.g. not a pointer. //
#define PF_IS_POWER_OF_TWO(Value) \ ((Value) && !((Value) & (Value - 1)))
// // Return value is the Pointer increased to be aligned with // Alignment. Alignment must be a power of 2. //
#define PF_ALIGN_UP(Pointer, Alignment) \ ((PVOID)(((ULONG_PTR)(Pointer) + (Alignment) - 1) & (~((ULONG_PTR)(Alignment) - 1))))
// // Verification code shared with the kernel mode component. This code // has to be kept in sync copy & paste. //
BOOLEAN PfWithinBounds( PVOID Pointer, PVOID Base, ULONG Length );
BOOLEAN PfVerifyScenarioId ( PPF_SCENARIO_ID ScenarioId );
BOOLEAN PfVerifyScenarioBuffer( PPF_SCENARIO_HEADER Scenario, ULONG BufferSize, PULONG FailedCheck );
BOOLEAN PfVerifyTraceBuffer( PPF_TRACE_HEADER Trace, ULONG BufferSize, PULONG FailedCheck );
#endif // _PREFETCH_H
|