|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
perfmem.c
Abstract:
This file implements an Performance Object that presents System Memory Performance Object
Created:
Bob Watson 22-Oct-1996
Revision History
--*/ //
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntmmapi.h>
#include <windows.h>
#include <winperf.h>
#include <ntprfctr.h>
#include <perfutil.h>
#include "perfos.h"
#include "perfosmc.h"
#include "datamem.h"
DWORD APIENTRY CollectMemoryObjectData ( IN OUT LPVOID *lppData, IN OUT LPDWORD lpcbTotalBytes, IN OUT LPDWORD lpNumObjectTypes ) /*++
Routine Description:
This routine will return the data for the XXX object
Arguments:
IN OUT LPVOID *lppData IN: pointer to the address of the buffer to receive the completed PerfDataBlock and subordinate structures. This routine will append its data to the buffer starting at the point referenced by *lppData. OUT: points to the first byte after the data structure added by this routine. This routine updated the value at lppdata after appending its data.
IN OUT LPDWORD lpcbTotalBytes IN: the address of the DWORD that tells the size in bytes of the buffer referenced by the lppData argument OUT: the number of bytes added by this routine is writted to the DWORD pointed to by this argument
IN OUT LPDWORD NumObjectTypes IN: the address of the DWORD to receive the number of objects added by this routine OUT: the number of objects added by this routine is writted to the DWORD pointed to by this argument
Returns:
0 if successful, else Win 32 error code of failure
--*/ { NTSTATUS Status; DWORD TotalLen; // Length of the total return block
PMEMORY_DATA_DEFINITION pMemoryDataDefinition; SYSTEM_FILECACHE_INFORMATION FileCache; PMEMORY_COUNTER_DATA pMCD; DWORD LocalPageSize;
pMemoryDataDefinition = (MEMORY_DATA_DEFINITION *) *lppData;
//
// Check for enough space for memory data block
//
TotalLen = sizeof(MEMORY_DATA_DEFINITION) + sizeof(MEMORY_COUNTER_DATA);
TotalLen = QWORD_MULTIPLE (TotalLen);
if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = (DWORD) 0; *lpNumObjectTypes = (DWORD) 0; return ERROR_MORE_DATA; }
#ifdef DBG
STARTTIMING; #endif
Status = NtQuerySystemInformation( SystemFileCacheInformation, &FileCache, sizeof(FileCache), NULL );
if (!NT_SUCCESS(Status)) { if (hEventLog != NULL) { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_FILE_CACHE_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&Status); } memset (&FileCache, 0, sizeof(FileCache)); }
#ifdef DBG
ENDTIMING (("PERFMEM: %d takes %I64u ms\n", __LINE__, diff)); #endif
//
// Define memory data block
//
memcpy (pMemoryDataDefinition, &MemoryDataDefinition, sizeof(MEMORY_DATA_DEFINITION));
//
// Format and collect memory data
//
LocalPageSize = BasicInfo.PageSize;
pMCD = (PMEMORY_COUNTER_DATA)&pMemoryDataDefinition[1];
pMCD->CounterBlock.ByteLength = QWORD_MULTIPLE(sizeof (MEMORY_COUNTER_DATA));
pMCD->AvailablePages = SysPerfInfo.AvailablePages; pMCD->AvailablePages *= LocalPageSize; // display as bytes
pMCD->AvailableKBytes = pMCD->AvailablePages / 1024; pMCD->AvailableMBytes = pMCD->AvailableKBytes / 1024; pMCD->CommittedPages = SysPerfInfo.CommittedPages; pMCD->CommittedPages *= LocalPageSize; pMCD->CommitList = SysPerfInfo.CommitLimit; pMCD->CommitList *= LocalPageSize; pMCD->PageFaults = SysPerfInfo.PageFaultCount; pMCD->WriteCopies = SysPerfInfo.CopyOnWriteCount; pMCD->TransitionFaults = SysPerfInfo.TransitionCount; pMCD->CacheFaults = FileCache.PageFaultCount; pMCD->DemandZeroFaults = SysPerfInfo.DemandZeroCount; pMCD->Pages = SysPerfInfo.PageReadCount + SysPerfInfo.DirtyPagesWriteCount; pMCD->PagesInput = SysPerfInfo.PageReadCount; pMCD->PageReads = SysPerfInfo.PageReadIoCount; pMCD->DirtyPages = SysPerfInfo.DirtyPagesWriteCount; pMCD->DirtyWrites = SysPerfInfo.DirtyWriteIoCount; pMCD->PagedPool = SysPerfInfo.PagedPoolPages; pMCD->PagedPool *= LocalPageSize; pMCD->NonPagedPool = SysPerfInfo.NonPagedPoolPages; pMCD->NonPagedPool *= LocalPageSize; pMCD->PagedPoolAllocs = SysPerfInfo.PagedPoolAllocs - SysPerfInfo.PagedPoolFrees; pMCD->NonPagedPoolAllocs = SysPerfInfo.NonPagedPoolAllocs - SysPerfInfo.NonPagedPoolFrees; pMCD->FreeSystemPtes = SysPerfInfo.FreeSystemPtes; pMCD->CacheBytes = FileCache.CurrentSize; pMCD->PeakCacheBytes = FileCache.PeakSize; pMCD->ResidentPagedPoolBytes = SysPerfInfo.ResidentPagedPoolPage; pMCD->ResidentPagedPoolBytes *= LocalPageSize; pMCD->TotalSysCodeBytes = SysPerfInfo.TotalSystemCodePages; pMCD->TotalSysCodeBytes *= LocalPageSize; pMCD->ResidentSysCodeBytes = SysPerfInfo.ResidentSystemCodePage; pMCD->ResidentSysCodeBytes *= LocalPageSize; pMCD->TotalSysDriverBytes = SysPerfInfo.TotalSystemDriverPages; pMCD->TotalSysDriverBytes *= LocalPageSize; pMCD->ResidentSysDriverBytes = SysPerfInfo.ResidentSystemDriverPage; pMCD->ResidentSysDriverBytes *= LocalPageSize; pMCD->ResidentSysCacheBytes = SysPerfInfo.ResidentSystemCachePage; pMCD->ResidentSysCacheBytes *= LocalPageSize; pMCD->TransitionRePurpose = FileCache.TransitionRePurposeCount;
// This is reported as a percentage of CommittedPages/CommitLimit.
// these value return a value in "page" units. Since this is a
// fraction, the page size (i.e. converting pages to bytes) will
// cancel out and as such can be ignored, saving some CPU cycles
//
pMCD->CommitBytesInUse = (ULONG)SysPerfInfo.CommittedPages; pMCD->CommitBytesLimit = (ULONG)SysPerfInfo.CommitLimit;
#if 0 // no longer supported
// load the VLM counters - this should really be removed period.
pMCD->SystemVlmCommitCharge = 0; pMCD->SystemVlmPeakCommitCharge = 0; pMCD->SystemVlmSharedCommitCharge = 0; #endif
*lpcbTotalBytes = pMemoryDataDefinition->MemoryObjectType.TotalByteLength = (DWORD) QWORD_MULTIPLE(((LPBYTE) (& pMCD[1])) - (LPBYTE) pMemoryDataDefinition); * lppData = (LPVOID) (((LPBYTE) pMemoryDataDefinition) + * lpcbTotalBytes);
*lpNumObjectTypes = 1; #ifdef DBG
ENDTIMING (("PERFMEM: %d takes %I64u ms total\n", __LINE__, diff)); #endif
return ERROR_SUCCESS; }
|