Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1361 lines
29 KiB

  1. /*++
  2. Copyright (c 1999 Microsoft Corporation
  3. Module Name:
  4. preftchp.h
  5. Abstract:
  6. This module contains the private definitions for the kernel mode
  7. prefetcher for optimizing demand paging. Page faults for a
  8. scenario are logged and the next time scenario starts, these pages
  9. are prefetched efficiently via asynchronous paging I/O.
  10. Author:
  11. Stuart Sechrest (stuartse)
  12. Chuck Lenzmeier (chuckl)
  13. Cenk Ergan (cenke)
  14. Revision History:
  15. --*/
  16. #ifndef _PREFTCHP_H
  17. #define _PREFTCHP_H
  18. //
  19. // Define tags used in prefetcher routines.
  20. //
  21. #define CCPF_PREFETCHER_TAG 'fPcC'
  22. #define CCPF_ALLOC_SCENARIO_TAG 'SPcC'
  23. #define CCPF_ALLOC_TRACE_TAG 'TPcC'
  24. #define CCPF_ALLOC_TRCBUF_TAG 'BPcC'
  25. #define CCPF_ALLOC_SECTTBL_TAG 'sPcC'
  26. #define CCPF_ALLOC_TRCDMP_TAG 'DPcC'
  27. #define CCPF_ALLOC_QUERY_TAG 'qPcC'
  28. #define CCPF_ALLOC_FILENAME_TAG 'FPcC'
  29. #define CCPF_ALLOC_CONTEXT_TAG 'CPcC'
  30. #define CCPF_ALLOC_INTRTABL_TAG 'IPcC'
  31. #define CCPF_ALLOC_PREFSCEN_TAG 'pPcC'
  32. #define CCPF_ALLOC_BOOTWRKR_TAG 'wPcC'
  33. #define CCPF_ALLOC_VOLUME_TAG 'vPcC'
  34. #define CCPF_ALLOC_READLIST_TAG 'LPcC'
  35. #define CCPF_ALLOC_METADATA_TAG 'MPcC'
  36. //
  37. // Whether the scenario type is for a system-wide scenario, meaning that
  38. // only it can be active while running.
  39. //
  40. #define CCPF_IS_SYSTEM_WIDE_SCENARIO_TYPE(ScenarioType) \
  41. ((ScenarioType) == PfSystemBootScenarioType)
  42. //
  43. // In the kernel, we have to look for named objects under this
  44. // directory for them to visible to Win32 prefetcher service.
  45. //
  46. #define CCPF_BASE_NAMED_OBJ_ROOT_DIR L"\\BaseNamedObjects"
  47. //
  48. // This is the invalid index value used with section tables.
  49. //
  50. #define CCPF_INVALID_TABLE_INDEX (-1)
  51. //
  52. // This is the max number of file metadata that NTFS can prefetch
  53. // at a time.
  54. //
  55. #define CCPF_MAX_FILE_METADATA_PREFETCH_COUNT 0x300
  56. //
  57. // Define structure to hold prefetcher parameters state.
  58. //
  59. typedef struct _CCPF_PREFETCHER_PARAMETERS {
  60. //
  61. // This is the named event that is used to signal the service that
  62. // parameters have been updated.
  63. //
  64. HANDLE ParametersChangedEvent;
  65. //
  66. // This is the registry key containing prefetch parameters.
  67. //
  68. HANDLE ParametersKey;
  69. //
  70. // Fields used in registering for change notify on parameters
  71. // registry key.
  72. //
  73. IO_STATUS_BLOCK RegistryWatchIosb;
  74. WORK_QUEUE_ITEM RegistryWatchWorkItem;
  75. ULONG RegistryWatchBuffer;
  76. //
  77. // System wide prefetching parameters. When using any parameters
  78. // whose update may cause problems [e.g. strings], get the
  79. // ParametersLock shared. When you need to update Parameters,
  80. // after getting the ParametersLock exclusive, bump
  81. // ParametersVersion before updating parameters.
  82. //
  83. PF_SYSTEM_PREFETCH_PARAMETERS Parameters;
  84. ERESOURCE ParametersLock;
  85. LONG ParametersVersion;
  86. //
  87. // Prefixes to registry values for different scenario types.
  88. //
  89. WCHAR *ScenarioTypePrefixes[PfMaxScenarioType];
  90. //
  91. // This is set to InitSafeBootMode during initialization.
  92. //
  93. ULONG SafeBootMode;
  94. } CCPF_PREFETCHER_PARAMETERS, *PCCPF_PREFETCHER_PARAMETERS;
  95. //
  96. // Define structure to hold prefetcher's global state.
  97. //
  98. typedef struct _CCPF_PREFETCHER_GLOBALS {
  99. //
  100. // List of active traces and the lock to protect it. The number
  101. // of items on this list is a global, since it is used by other
  102. // kernel components to make a fast check.
  103. //
  104. LIST_ENTRY ActiveTraces;
  105. KSPIN_LOCK ActiveTracesLock;
  106. //
  107. // Pointer to the global trace if one is active. While there is a
  108. // global trace active we don't trace & prefetch other scenarios.
  109. // Boot tracing is an example of global trace.
  110. //
  111. struct _CCPF_TRACE_HEADER *SystemWideTrace;
  112. //
  113. // List and number of saved completed prefetch traces and lock to
  114. // protect it.
  115. //
  116. LIST_ENTRY CompletedTraces;
  117. FAST_MUTEX CompletedTracesLock;
  118. LONG NumCompletedTraces;
  119. //
  120. // This is the named event that is used to signal the service that
  121. // there are traces ready for it to get.
  122. //
  123. HANDLE CompletedTracesEvent;
  124. //
  125. // Prefetcher parameters.
  126. //
  127. CCPF_PREFETCHER_PARAMETERS Parameters;
  128. } CCPF_PREFETCHER_GLOBALS, *PCCPF_PREFETCHER_GLOBALS;
  129. //
  130. // Reference count structure.
  131. //
  132. typedef struct _CCPF_REFCOUNT {
  133. //
  134. // When initialized or reset, this reference count starts from
  135. // 1. When exclusive access is granted it stays at 0: even if it
  136. // may get bumped by an AddRef by mistake, it will return to 0.
  137. //
  138. LONG RefCount;
  139. //
  140. // This is set when somebody wants to gain exclusive access to the
  141. // protected structure.
  142. //
  143. LONG Exclusive;
  144. } CCPF_REFCOUNT, *PCCPF_REFCOUNT;
  145. //
  146. // Define structures used for logging pagefaults:
  147. //
  148. //
  149. // One of these is logged for every page fault.
  150. //
  151. typedef struct _CCPF_LOG_ENTRY {
  152. //
  153. // File offset of the page that was faulted.
  154. //
  155. ULONG FileOffset;
  156. //
  157. // Index into the section table in the trace header that helps us
  158. // identify the file.
  159. //
  160. USHORT SectionId;
  161. //
  162. // Whether this page was faulted as an image page or data page.
  163. //
  164. BOOLEAN IsImage;
  165. //
  166. // Whether this is a fault that happened in the process in which
  167. // the scenario is associated with.
  168. //
  169. BOOLEAN InProcess;
  170. } CCPF_LOG_ENTRY, *PCCPF_LOG_ENTRY;
  171. //
  172. // CCPF_LOG_ENTRIES is a buffer of log entries with a small header containing
  173. // an index to the highest used entry. This is used so that a trace can consist
  174. // of several smaller trace buffers instead of one large, fixed-size buffer.
  175. // The current index must be contained in the buffer in order to allow entries
  176. // to be added without acquiring a spin lock.
  177. //
  178. typedef struct _CCPF_LOG_ENTRIES {
  179. //
  180. // Link used to put this buffer in the traces's buffer list.
  181. //
  182. LIST_ENTRY TraceBuffersLink;
  183. //
  184. // NumEntries is the current number of entries in the buffer. MaxEntries
  185. // is the maximum number of entries that can be placed in the buffer.
  186. // (Currently MaxEntries always equals CCPF_TRACE_BUFFER_MAX_ENTRIES.)
  187. //
  188. LONG NumEntries;
  189. LONG MaxEntries;
  190. //
  191. // The logged entries start here.
  192. //
  193. CCPF_LOG_ENTRY Entries[1];
  194. } CCPF_LOG_ENTRIES, *PCCPF_LOG_ENTRIES;
  195. //
  196. // CCPF_TRACE_BUFFER_SIZE is the size of an allocated CCPF_LOG_ENTRIES structure
  197. // (including the header). This should be a multiple of the page size.
  198. //
  199. #define CCPF_TRACE_BUFFER_SIZE 8192
  200. //
  201. // CCPF_TRACE_BUFFER_MAX_ENTRIES is the number of log entries that will fit in
  202. // a trace buffer of size CCPF_TRACE_BUFFER_SIZE.
  203. //
  204. #define CCPF_TRACE_BUFFER_MAX_ENTRIES (((CCPF_TRACE_BUFFER_SIZE - sizeof(CCPF_LOG_ENTRIES)) / sizeof(CCPF_LOG_ENTRY)) + 1)
  205. //
  206. // This structure associates a SectionObjectPointer with a file name
  207. // in the runtime trace buffer. There is a table of these in the trace
  208. // header and every page fault has an index into this table denoting
  209. // which file it is to.
  210. //
  211. typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _CCPF_SECTION_INFO {
  212. //
  213. // Section info entries are kept in a hash. This field is
  214. // InterlockedCompareExchange'd to denote that it is in use.
  215. //
  216. LONG EntryValid;
  217. //
  218. // Whether this section is used for file systems to map metafile.
  219. //
  220. ULONG Metafile:1;
  221. ULONG Unused:31;
  222. //
  223. // SectionObjectPointer used as a unique identifier to a file
  224. // mapping. The same file may be mapped using a number of file
  225. // objects, but the SectionObjectPointer fields of all those file
  226. // objects will be the same.
  227. //
  228. PSECTION_OBJECT_POINTERS SectionObjectPointer;
  229. //
  230. // All references to all file objects for a file may be released,
  231. // and a new file may be opened using the same memory block for
  232. // its FCB at which point the SectionObjectPointer would no longer
  233. // be unique. This would result in pagefaults getting logged under
  234. // the entry for the file that was closed. The consequences would
  235. // be misprefetching wrong pages from a couple of sections until
  236. // the scenario corrects itself by looking at new traces. By
  237. // keeping track of these two fields of the SectionObjectPointers
  238. // to check for uniqueness we make this case very unlikely to
  239. // happen. The other solutions we thought of to solve this issue
  240. // 100% were too costly in terms of complication or efficiency.
  241. //
  242. //
  243. // In order to avoid adding two entries to the table for the
  244. // section when it is used as data first then image (or vice
  245. // versa) it is assumed that it is still the same section if the
  246. // current entry's Data/ImageSectionObject is NULL but the
  247. // Data/ImageSectionObject of the section we are logging a new
  248. // pagefault to is not. Then we try to update the NULL pointer
  249. // with the new value using InterlockedCompareExchangePointer.
  250. //
  251. PVOID DataSectionObject;
  252. PVOID ImageSectionObject;
  253. //
  254. // This may point to a file object that we have referenced to
  255. // ensure the section object stays around until we can get a name.
  256. //
  257. PFILE_OBJECT ReferencedFileObject;
  258. //
  259. // The name is set as soon as we can get a file name. We cannot
  260. // access the file name while running at a high IRQL.
  261. //
  262. WCHAR *FileName;
  263. //
  264. // We queue a section to the get-file-name list using this field.
  265. //
  266. SINGLE_LIST_ENTRY GetNameLink;
  267. } CCPF_SECTION_INFO, *PCCPF_SECTION_INFO;
  268. //
  269. // This structure contains information on a volume on which sections
  270. // in the trace are located on.
  271. //
  272. typedef struct _CCPF_VOLUME_INFO {
  273. //
  274. // Link in the trace's volume list.
  275. //
  276. LIST_ENTRY VolumeLink;
  277. //
  278. // Volume creation time and serial number used to identify the
  279. // volume in case its NT/device path e.g. \Device\HarddiskVolume1
  280. // changes.
  281. //
  282. LARGE_INTEGER CreationTime;
  283. ULONG SerialNumber;
  284. //
  285. // Current NT/device path for the volume and its length in
  286. // characters excluding terminating NUL.
  287. //
  288. ULONG VolumePathLength;
  289. WCHAR VolumePath[1];
  290. } CCPF_VOLUME_INFO, *PCCPF_VOLUME_INFO;
  291. //
  292. // This is the runtime trace header for a scenario.
  293. //
  294. typedef struct _CCPF_TRACE_HEADER {
  295. //
  296. // Magic number identifying this structure as a trace.
  297. //
  298. ULONG Magic;
  299. //
  300. // Link in the active traces list.
  301. //
  302. LIST_ENTRY ActiveTracesLink;
  303. //
  304. // Scenario id for which we are acquiring this trace.
  305. //
  306. PF_SCENARIO_ID ScenarioId;
  307. //
  308. // Type of this scenario.
  309. //
  310. PF_SCENARIO_TYPE ScenarioType;
  311. //
  312. // CurrentTraceBuffer is the active trace buffer.
  313. //
  314. PCCPF_LOG_ENTRIES CurrentTraceBuffer;
  315. //
  316. // This is the list of trace buffers for this trace.
  317. // CurrentTraceBuffer is the last element. Both this list and
  318. // CurrentTraceBuffer are protected by TraceBufferSpinLock.
  319. //
  320. LIST_ENTRY TraceBuffersList;
  321. ULONG NumTraceBuffers;
  322. KSPIN_LOCK TraceBufferSpinLock;
  323. //
  324. // This is the table for section info.
  325. //
  326. PCCPF_SECTION_INFO SectionInfoTable;
  327. LONG NumSections;
  328. LONG MaxSections;
  329. ULONG SectionTableSize;
  330. //
  331. // We don't log timestamps with page faults but it helps to know
  332. // how many we are logging per given time. This information can be
  333. // used to mark the end of a scenario.
  334. //
  335. KTIMER TraceTimer;
  336. LARGE_INTEGER TraceTimerPeriod;
  337. KDPC TraceTimerDpc;
  338. KSPIN_LOCK TraceTimerSpinLock;
  339. //
  340. // This array contains the number of page faults logged per trace
  341. // period.
  342. //
  343. ULONG FaultsPerPeriod[PF_MAX_NUM_TRACE_PERIODS];
  344. LONG LastNumFaults;
  345. LONG CurPeriod;
  346. //
  347. // NumFaults is the number of faults that have been logged so far, in all
  348. // trace buffers. MaxFaults is the maximum number of page faults we will
  349. // log, in all trace buffers.
  350. //
  351. LONG NumFaults;
  352. LONG MaxFaults;
  353. //
  354. // This workitem is queued to get names for file objects we are
  355. // logging page faults to. First GetFileNameWorkItemQueued should
  356. // be InterlockedCompareExchange'd from 0 to 1 and a reference
  357. // should be acquired on the scenario. The workitem will free this
  358. // reference just before it completes.
  359. //
  360. WORK_QUEUE_ITEM GetFileNameWorkItem;
  361. LONG GetFileNameWorkItemQueued;
  362. //
  363. // Sections for which we have to get names are pushed and popped
  364. // to/from this slist.
  365. //
  366. SLIST_HEADER SectionsWithoutNamesList;
  367. //
  368. // Because we don't want to incur the cost of queuing a work item
  369. // to get file names for every one or two sections, the worker we
  370. // queue will wait on this event before returning. The event can
  371. // be signaled when a new section comes, or when the scenario is
  372. // ending.
  373. //
  374. KEVENT GetFileNameWorkerEvent;
  375. //
  376. // This is the process we are associated with.
  377. //
  378. PEPROCESS Process;
  379. //
  380. // This is the removal reference count protecting us.
  381. //
  382. CCPF_REFCOUNT RefCount;
  383. //
  384. // This work item can be queued to call the end trace function if
  385. // the trace times out or we log to many entries etc. First
  386. // EndTraceCalled should be InterlockedCompareExchange'd from 0 to
  387. // 1.
  388. //
  389. WORK_QUEUE_ITEM EndTraceWorkItem;
  390. //
  391. // Before anybody calls end trace function, they have to
  392. // InterlockedCompareExchange this from 0 to 1 to ensure this
  393. // function gets called only once.
  394. //
  395. LONG EndTraceCalled;
  396. //
  397. // This is the list of volumes the sections we are tracing are
  398. // located on. It is sorted lexically by the volume NT/device path.
  399. //
  400. LIST_ENTRY VolumeList;
  401. ULONG NumVolumes;
  402. //
  403. // This is the pointer to the built trace dump from this runtime
  404. // trace structure and the status with which dumping failed if it
  405. // did.
  406. //
  407. struct _CCPF_TRACE_DUMP *TraceDump;
  408. NTSTATUS TraceDumpStatus;
  409. //
  410. // System time when we started tracing.
  411. //
  412. LARGE_INTEGER LaunchTime;
  413. } CCPF_TRACE_HEADER, *PCCPF_TRACE_HEADER;
  414. //
  415. // This structure is used to save completed traces in a list. The
  416. // trace extends beyond this structure as necessary.
  417. //
  418. typedef struct _CCPF_TRACE_DUMP {
  419. //
  420. // Link in the completed traces list.
  421. //
  422. LIST_ENTRY CompletedTracesLink;
  423. //
  424. // Completed trace.
  425. //
  426. PF_TRACE_HEADER Trace;
  427. } CCPF_TRACE_DUMP, *PCCPF_TRACE_DUMP;
  428. //
  429. // This structure contains information for a volume used during prefetching.
  430. //
  431. typedef struct _CCPF_PREFETCH_VOLUME_INFO {
  432. //
  433. // Link in the lists this volume gets put on.
  434. //
  435. LIST_ENTRY VolumeLink;
  436. //
  437. // Volume path.
  438. //
  439. WCHAR *VolumePath;
  440. ULONG VolumePathLength;
  441. //
  442. // Handle to the opened volume.
  443. //
  444. HANDLE VolumeHandle;
  445. } CCPF_PREFETCH_VOLUME_INFO, *PCCPF_PREFETCH_VOLUME_INFO;
  446. //
  447. // This structure is used to keep track of prefetched pages & context.
  448. //
  449. //
  450. // Note: This structure is used as a stack variable. Don't add events
  451. // etc, without changing that.
  452. //
  453. typedef struct _CCPF_PREFETCH_HEADER {
  454. //
  455. // Pointer to prefetch instructions. The instructions should not
  456. // be removed / freed until the prefetch header is cleaned up.
  457. // E.g. VolumeNodes may point to volume paths in the scenario.
  458. //
  459. PPF_SCENARIO_HEADER Scenario;
  460. //
  461. // Nodes for the volumes we are going to prefetch from.
  462. //
  463. PCCPF_PREFETCH_VOLUME_INFO VolumeNodes;
  464. //
  465. // List of volumes we won't prefetch on.
  466. //
  467. LIST_ENTRY BadVolumeList;
  468. //
  469. // List of volumes we have opened. They are opened with the following
  470. // flags: FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE
  471. //
  472. LIST_ENTRY OpenedVolumeList;
  473. } CCPF_PREFETCH_HEADER, *PCCPF_PREFETCH_HEADER;
  474. //
  475. // Define types of prefetching CcPfPrefetchSections can be called to
  476. // perform.
  477. //
  478. typedef enum _CCPF_PREFETCH_TYPE {
  479. CcPfPrefetchAllDataPages,
  480. CcPfPrefetchAllImagePages,
  481. CcPfPrefetchPartOfDataPages,
  482. CcPfPrefetchPartOfImagePages,
  483. CcPfMaxPrefetchType
  484. } CCPF_PREFETCH_TYPE, *PCCPF_PREFETCH_TYPE;
  485. //
  486. // This structure stands for the position in the prefetch
  487. // instructions. It is used and updated by CcPfPrefetchSections when
  488. // prefetching parts of a scenario at a time.
  489. //
  490. typedef struct _CCPF_PREFETCH_CURSOR {
  491. //
  492. // Index of the current section and the page in that section.
  493. //
  494. ULONG SectionIdx;
  495. ULONG PageIdx;
  496. } CCPF_PREFETCH_CURSOR, *PCCPF_PREFETCH_CURSOR;
  497. //
  498. // This type is used in CcPfPrefetchSections.
  499. //
  500. typedef struct _SECTION *PSECTION;
  501. //
  502. // Define types of information CcPfQueryScenarioInformation can be
  503. // asked to return.
  504. //
  505. typedef enum _CCPF_SCENARIO_INFORMATION_TYPE {
  506. CcPfBasicScenarioInformation,
  507. CcPfBootScenarioInformation,
  508. CcPfMaxScenarioInformationType
  509. } CCPF_SCENARIO_INFORMATION_TYPE, *PCCPF_SCENARIO_INFORMATION_TYPE;
  510. //
  511. // This structure contains basic scenario information.
  512. //
  513. typedef struct _CCPF_BASIC_SCENARIO_INFORMATION {
  514. //
  515. // Number of pages that will be prefetched as data pages.
  516. //
  517. ULONG NumDataPages;
  518. //
  519. // Number of pages that will be prefetched as image pages.
  520. //
  521. ULONG NumImagePages;
  522. //
  523. // Number of sections for which only data pages will be
  524. // prefetched.
  525. //
  526. ULONG NumDataOnlySections;
  527. //
  528. // Number of sections for which only image pages will be
  529. // prefetched excluding the header page.
  530. //
  531. ULONG NumImageOnlySections;
  532. //
  533. // Number of ignored pages.
  534. //
  535. ULONG NumIgnoredPages;
  536. //
  537. // Number of ignored sections.
  538. //
  539. ULONG NumIgnoredSections;
  540. } CCPF_BASIC_SCENARIO_INFORMATION, *PCCPF_BASIC_SCENARIO_INFORMATION;
  541. //
  542. // Routines used in the core prefetcher.
  543. //
  544. //
  545. // Routines used in prefetch tracing.
  546. //
  547. NTSTATUS
  548. CcPfBeginTrace(
  549. IN PF_SCENARIO_ID *ScenarioId,
  550. IN PF_SCENARIO_TYPE ScenarioType,
  551. IN HANDLE ProcessHandle
  552. );
  553. NTSTATUS
  554. CcPfActivateTrace(
  555. IN PCCPF_TRACE_HEADER Scenario
  556. );
  557. NTSTATUS
  558. CcPfDeactivateTrace(
  559. IN PCCPF_TRACE_HEADER Scenario
  560. );
  561. NTSTATUS
  562. CcPfEndTrace(
  563. IN PCCPF_TRACE_HEADER Trace
  564. );
  565. NTSTATUS
  566. CcPfBuildDumpFromTrace(
  567. OUT PCCPF_TRACE_DUMP *TraceDump,
  568. IN PCCPF_TRACE_HEADER RuntimeTrace
  569. );
  570. VOID
  571. CcPfCleanupTrace(
  572. IN PCCPF_TRACE_HEADER Trace
  573. );
  574. VOID
  575. CcPfTraceTimerRoutine(
  576. IN PKDPC Dpc,
  577. IN PVOID DeferredContext,
  578. IN PVOID SystemArgument1,
  579. IN PVOID SystemArgument2
  580. );
  581. NTSTATUS
  582. CcPfCancelTraceTimer(
  583. IN PCCPF_TRACE_HEADER Trace
  584. );
  585. VOID
  586. CcPfEndTraceWorkerThreadRoutine(
  587. PVOID Parameter
  588. );
  589. VOID
  590. CcPfGetFileNamesWorkerRoutine(
  591. PVOID Parameter
  592. );
  593. LONG
  594. CcPfLookUpSection(
  595. PCCPF_SECTION_INFO Table,
  596. ULONG TableSize,
  597. PSECTION_OBJECT_POINTERS SectionObjectPointer,
  598. PLONG AvailablePosition
  599. );
  600. NTSTATUS
  601. CcPfGetCompletedTrace (
  602. PVOID Buffer,
  603. ULONG BufferSize,
  604. PULONG ReturnSize
  605. );
  606. NTSTATUS
  607. CcPfUpdateVolumeList(
  608. PCCPF_TRACE_HEADER Trace,
  609. WCHAR *VolumePath,
  610. ULONG VolumePathLength
  611. );
  612. //
  613. // Routines used for prefetching and dealing with prefetch instructions.
  614. //
  615. NTSTATUS
  616. CcPfPrefetchScenario (
  617. PPF_SCENARIO_HEADER Scenario
  618. );
  619. NTSTATUS
  620. CcPfPrefetchSections(
  621. IN PCCPF_PREFETCH_HEADER PrefetchHeader,
  622. IN CCPF_PREFETCH_TYPE PrefetchType,
  623. OPTIONAL IN PCCPF_PREFETCH_CURSOR StartCursor,
  624. OPTIONAL ULONG TotalPagesToPrefetch,
  625. OPTIONAL OUT PULONG NumPagesPrefetched,
  626. OPTIONAL OUT PCCPF_PREFETCH_CURSOR EndCursor
  627. );
  628. NTSTATUS
  629. CcPfPrefetchMetadata(
  630. IN PCCPF_PREFETCH_HEADER PrefetchHeader
  631. );
  632. NTSTATUS
  633. CcPfPrefetchDirectoryContents(
  634. WCHAR *DirectoryPath,
  635. WCHAR DirectoryPathlength
  636. );
  637. NTSTATUS
  638. CcPfPrefetchFileMetadata(
  639. HANDLE VolumeHandle,
  640. PFILE_PREFETCH FilePrefetch
  641. );
  642. VOID
  643. CcPfInitializePrefetchHeader (
  644. OUT PCCPF_PREFETCH_HEADER PrefetchHeader
  645. );
  646. VOID
  647. CcPfCleanupPrefetchHeader (
  648. IN PCCPF_PREFETCH_HEADER PrefetchHeader
  649. );
  650. NTSTATUS
  651. CcPfGetPrefetchInstructions(
  652. IN PPF_SCENARIO_ID ScenarioId,
  653. IN PF_SCENARIO_TYPE ScenarioType,
  654. OUT PPF_SCENARIO_HEADER *Scenario
  655. );
  656. NTSTATUS
  657. CcPfQueryScenarioInformation(
  658. IN PPF_SCENARIO_HEADER Scenario,
  659. IN CCPF_SCENARIO_INFORMATION_TYPE InformationType,
  660. OUT PVOID Buffer,
  661. IN ULONG BufferSize,
  662. OUT PULONG RequiredSize
  663. );
  664. NTSTATUS
  665. CcPfOpenVolumesForPrefetch (
  666. IN PCCPF_PREFETCH_HEADER PrefetchHeader
  667. );
  668. PCCPF_PREFETCH_VOLUME_INFO
  669. CcPfFindPrefetchVolumeInfoInList(
  670. WCHAR *Path,
  671. PLIST_ENTRY List
  672. );
  673. NTSTATUS
  674. CcPfGetSectionObject(
  675. IN PUNICODE_STRING FileName,
  676. IN LOGICAL ImageSection,
  677. OUT PVOID* SectionObject,
  678. OUT PFILE_OBJECT* FileObject,
  679. OUT HANDLE* FileHandle
  680. );
  681. //
  682. // Routines used for application launch prefetching.
  683. //
  684. BOOLEAN
  685. CcPfIsHostingApplication(
  686. IN PWCHAR ExecutableName
  687. );
  688. NTSTATUS
  689. CcPfScanCommandLine(
  690. OUT PULONG PrefetchHint,
  691. OPTIONAL OUT PULONG HashId
  692. );
  693. //
  694. // Reference count functions:
  695. //
  696. VOID
  697. CcPfInitializeRefCount(
  698. PCCPF_REFCOUNT RefCount
  699. );
  700. NTSTATUS
  701. FASTCALL
  702. CcPfAddRef(
  703. PCCPF_REFCOUNT RefCount
  704. );
  705. VOID
  706. FASTCALL
  707. CcPfDecRef(
  708. PCCPF_REFCOUNT RefCount
  709. );
  710. NTSTATUS
  711. FASTCALL
  712. CcPfAddRefEx(
  713. PCCPF_REFCOUNT RefCount,
  714. ULONG Count
  715. );
  716. VOID
  717. FASTCALL
  718. CcPfDecRefEx(
  719. PCCPF_REFCOUNT RefCount,
  720. ULONG Count
  721. );
  722. NTSTATUS
  723. CcPfAcquireExclusiveRef(
  724. PCCPF_REFCOUNT RefCount
  725. );
  726. PCCPF_TRACE_HEADER
  727. CcPfReferenceProcessTrace(
  728. PEPROCESS Process
  729. );
  730. PCCPF_TRACE_HEADER
  731. CcPfRemoveProcessTrace(
  732. PEPROCESS Process
  733. );
  734. NTSTATUS
  735. CcPfAddProcessTrace(
  736. PEPROCESS Process,
  737. PCCPF_TRACE_HEADER Trace
  738. );
  739. //
  740. // Utility routines.
  741. //
  742. PWCHAR
  743. CcPfFindString (
  744. PUNICODE_STRING SearchIn,
  745. PUNICODE_STRING SearchFor
  746. );
  747. ULONG
  748. CcPfHashValue(
  749. PVOID Key,
  750. ULONG Len
  751. );
  752. NTSTATUS
  753. CcPfIsVolumeMounted (
  754. IN WCHAR *VolumePath,
  755. OUT BOOLEAN *VolumeMounted
  756. );
  757. NTSTATUS
  758. CcPfQueryVolumeInfo (
  759. IN WCHAR *VolumePath,
  760. OPTIONAL OUT HANDLE *VolumeHandleOut,
  761. OUT PLARGE_INTEGER CreationTime,
  762. OUT PULONG SerialNumber
  763. );
  764. //
  765. // Declarations and definitions for prefetcher parameters.
  766. //
  767. //
  768. // Define location of registry key for prefetch parameters.
  769. //
  770. #define CCPF_PARAMETERS_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
  771. //
  772. // Maximum characters in registry value names for prefetch parameters.
  773. //
  774. #define CCPF_MAX_PARAMETER_NAME_LENGTH 80
  775. //
  776. // Maximum bytes needed to query a prefetch parameter from the
  777. // registry. Currently our largest parameter would be the hosting
  778. // application list.
  779. //
  780. #define CCPF_MAX_PARAMETER_VALUE_BUFFER ((PF_HOSTING_APP_LIST_MAX_CHARS * sizeof(WCHAR)) + sizeof(KEY_VALUE_PARTIAL_INFORMATION))
  781. NTSTATUS
  782. CcPfParametersInitialize (
  783. PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters
  784. );
  785. VOID
  786. CcPfParametersSetDefaults (
  787. PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters
  788. );
  789. NTSTATUS
  790. CcPfParametersRead (
  791. PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters
  792. );
  793. NTSTATUS
  794. CcPfParametersSave (
  795. PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters
  796. );
  797. NTSTATUS
  798. CcPfParametersVerify (
  799. PPF_SYSTEM_PREFETCH_PARAMETERS Parameters
  800. );
  801. VOID
  802. CcPfParametersWatcher (
  803. IN PVOID Context
  804. );
  805. NTSTATUS
  806. CcPfParametersSetChangedEvent (
  807. PCCPF_PREFETCHER_PARAMETERS PrefetcherParameters
  808. );
  809. NTSTATUS
  810. CcPfGetParameter (
  811. HANDLE ParametersKey,
  812. WCHAR *ValueNameBuffer,
  813. ULONG ValueType,
  814. PVOID Value,
  815. ULONG *ValueSize
  816. );
  817. NTSTATUS
  818. CcPfSetParameter (
  819. HANDLE ParametersKey,
  820. WCHAR *ValueNameBuffer,
  821. ULONG ValueType,
  822. PVOID Value,
  823. ULONG ValueSize
  824. );
  825. LOGICAL
  826. CcPfDetermineEnablePrefetcher(
  827. VOID
  828. );
  829. //
  830. // Declarations and definitions for boot prefetching.
  831. //
  832. //
  833. // Value name under prefetcher parameters key where we store how long
  834. // video initialization took during boot.
  835. //
  836. #define CCPF_VIDEO_INIT_TIME_VALUE_NAME L"VideoInitTime"
  837. //
  838. // How long (in milliseconds) video initialization could take max. This value
  839. // is used to sanity check the value read from the registry.
  840. //
  841. #define CCPF_MAX_VIDEO_INIT_TIME (10 * 1000) // 10 seconds
  842. //
  843. // Value name under prefetcher parameters key where we store how many
  844. // pages we should try to prefetch per second of video initialization.
  845. //
  846. #define CCPF_VIDEO_INIT_PAGES_PER_SECOND_VALUE_NAME L"VideoInitPagesPerSecond"
  847. //
  848. // Sanity check maximum value for video init pages per second.
  849. //
  850. #define CCPF_VIDEO_INIT_MAX_PAGES_PER_SECOND 128000
  851. //
  852. // How many pages will we try to prefetch in parallel to video initialization
  853. // per second of it.
  854. //
  855. #define CCPF_VIDEO_INIT_DEFAULT_PAGES_PER_SECOND 1500
  856. //
  857. // Maximum number of chunks in which we will prefetch for boot.
  858. //
  859. #define CCPF_MAX_BOOT_PREFETCH_PHASES 16
  860. //
  861. // Different phases of boot we return page counts for in
  862. // CCPF_BOOT_SCENARIO_INFORMATION.
  863. //
  864. typedef enum _CCPF_BOOT_SCENARIO_PHASE {
  865. CcPfBootScenDriverInitPhase,
  866. CcPfBootScenSubsystemInitPhase,
  867. CcPfBootScenSystemProcInitPhase,
  868. CcPfBootScenServicesInitPhase,
  869. CcPfBootScenUserInitPhase,
  870. CcPfBootScenMaxPhase
  871. } CCPF_BOOT_SCENARIO_PHASE, *PCCPF_BOOT_SCENARIO_PHASE;
  872. //
  873. // Define structure to hold boot prefetching state.
  874. //
  875. typedef struct _CCPF_BOOT_PREFETCHER {
  876. //
  877. // These events are signaled by the boot prefetch worker when
  878. // it has completed prefetching for the specified phase.
  879. //
  880. KEVENT SystemDriversPrefetchingDone;
  881. KEVENT PreSmssPrefetchingDone;
  882. KEVENT VideoInitPrefetchingDone;
  883. //
  884. // This event will be signaled when we start initializing video
  885. // on the console. Boot prefetcher waits on this event to perform
  886. // prefetching parallel to video initialization.
  887. //
  888. KEVENT VideoInitStarted;
  889. } CCPF_BOOT_PREFETCHER, *PCCPF_BOOT_PREFETCHER;
  890. //
  891. // This structure contains boot scenario information.
  892. //
  893. typedef struct _CCPF_BOOT_SCENARIO_INFORMATION {
  894. //
  895. // These are the number of data/image pages to prefetch for the
  896. // different phase of boot.
  897. //
  898. ULONG NumDataPages[CcPfBootScenMaxPhase];
  899. ULONG NumImagePages[CcPfBootScenMaxPhase];
  900. } CCPF_BOOT_SCENARIO_INFORMATION, *PCCPF_BOOT_SCENARIO_INFORMATION;
  901. //
  902. // We will be prefetching data and image pages for boot in parts. Since the
  903. // code is mostly same to prefetch the data and image pages, we keep track
  904. // of where we left off and what to prefetch next in a common boot prefetch
  905. // cursor structure and make two passes (first for data, then for image).
  906. //
  907. typedef struct _CCPF_BOOT_PREFETCH_CURSOR {
  908. //
  909. // Start & end cursors passed to prefetch sections function.
  910. //
  911. CCPF_PREFETCH_CURSOR StartCursor;
  912. CCPF_PREFETCH_CURSOR EndCursor;
  913. //
  914. // How to prefetch (e.g. part of data pages or part of image pages).
  915. //
  916. CCPF_PREFETCH_TYPE PrefetchType;
  917. //
  918. // How many pages to prefetch per phase.
  919. //
  920. ULONG NumPagesForPhase[CCPF_MAX_BOOT_PREFETCH_PHASES];
  921. } CCPF_BOOT_PREFETCH_CURSOR, *PCCPF_BOOT_PREFETCH_CURSOR;
  922. //
  923. // Boot prefetching routines.
  924. //
  925. VOID
  926. CcPfBootWorker(
  927. PCCPF_BOOT_PREFETCHER BootPrefetcher
  928. );
  929. NTSTATUS
  930. CcPfBootQueueEndTraceTimer (
  931. PLARGE_INTEGER Timeout
  932. );
  933. VOID
  934. CcPfEndBootTimerRoutine(
  935. IN PKDPC Dpc,
  936. IN PVOID DeferredContext,
  937. IN PVOID SystemArgument1,
  938. IN PVOID SystemArgument2
  939. );
  940. //
  941. // Debug routines.
  942. //
  943. #if CCPF_DBG
  944. NTSTATUS
  945. CcPfWriteToFile(
  946. IN PVOID pData,
  947. IN ULONG Size,
  948. IN WCHAR *pFileName
  949. );
  950. #endif // CCPF_DBG
  951. //
  952. // Define useful macros. As with all macros, must be careful of
  953. // parameter reevalation. Don't use expressions as macro parameters.
  954. //
  955. #define CCPF_MAX(A,B) (((A) >= (B)) ? (A) : (B))
  956. #define CCPF_MIN(A,B) (((A) <= (B)) ? (A) : (B))
  957. //
  958. // Define debugging macros:
  959. //
  960. //
  961. // Define the component ID we use.
  962. //
  963. #define CCPFID DPFLTR_PREFETCHER_ID
  964. //
  965. // Define DbgPrintEx levels.
  966. //
  967. #define PFERR DPFLTR_ERROR_LEVEL
  968. #define PFWARN DPFLTR_WARNING_LEVEL
  969. #define PFTRC DPFLTR_TRACE_LEVEL
  970. #define PFINFO DPFLTR_INFO_LEVEL
  971. #define PFPREF 4
  972. #define PFPRFD 5
  973. #define PFPRFF 6
  974. #define PFPRFZ 7
  975. #define PFTRAC 8
  976. #define PFTMR 9
  977. #define PFNAME 10
  978. #define PFNAMS 11
  979. #define PFLKUP 12
  980. #define PFBOOT 13
  981. //
  982. // DbgPrintEx levels 20 - 31 are reserved for the service.
  983. //
  984. //
  985. // This may help you determine what to set the DbgPrintEx mask.
  986. //
  987. // 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
  988. // 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
  989. // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  990. //
  991. //
  992. // CCPF_DBG can be defined if you want to turn on asserts and debug
  993. // prints in prefetcher code but you do not want to have a checked
  994. // kernel. Defining CCPF_DBG overrides defining DBG.
  995. //
  996. #if CCPF_DBG
  997. NTSYSAPI
  998. VOID
  999. NTAPI
  1000. RtlAssert(
  1001. PVOID FailedAssertion,
  1002. PVOID FileName,
  1003. ULONG LineNumber,
  1004. PCHAR Message
  1005. );
  1006. #define DBGPR(x) DbgPrintEx x
  1007. #define CCPF_ASSERT(x) if (!(x)) RtlAssert(#x, __FILE__, __LINE__, NULL )
  1008. #else // CCPF_DBG
  1009. //
  1010. // If CCPF_DBG is not defined, build with debug prints and asserts
  1011. // only on checked build.
  1012. //
  1013. #if DBG
  1014. #define DBGPR(x) DbgPrintEx x
  1015. #define CCPF_ASSERT(x) ASSERT(x)
  1016. #else // DBG
  1017. //
  1018. // On a free build we don't compile with debug prints or asserts.
  1019. //
  1020. #define DBGPR(x)
  1021. #define CCPF_ASSERT(x)
  1022. #endif // DBG
  1023. #endif // CCPF_DBG
  1024. #endif // _PREFTCHP_H