206 lines
6.6 KiB
C++
206 lines
6.6 KiB
C++
/*++
|
||
|
||
Copyright (C) 1995-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
appmema.cpp
|
||
|
||
Abstract:
|
||
|
||
This file contains the memory allocation function "wrappers"
|
||
to allow monitoring of the memory usage by a performance monitoring
|
||
application (e.g. PERFMON).
|
||
|
||
--*/
|
||
|
||
#ifdef DO_TIMING_BUILD
|
||
|
||
#include <windows.h>
|
||
#include <assert.h>
|
||
#include "appmema.h"
|
||
|
||
HANDLE ThisDLLHandle = NULL;
|
||
|
||
HANDLE hAppMemSharedMemory = NULL; // Handle of counter Shared Memory
|
||
|
||
PAPPMEM_DATA_HEADER pDataHeader = NULL; // pointer to header of shared mem
|
||
PAPPMEM_INSTANCE pAppData = NULL; // pointer to the app data for this app
|
||
|
||
static
|
||
BOOL
|
||
DllProcessAttach (
|
||
IN HANDLE DllHandle
|
||
)
|
||
/*++
|
||
|
||
Description:
|
||
|
||
Initializes the interface to the performance counters DLL by
|
||
opening the Shared Memory file used to communicate statistics
|
||
from the application to the counter DLL. If the Shared memory
|
||
file does not exist, it is created, formatted and initialized.
|
||
If the file has already been created and formatted, then the
|
||
next available APPMEM_INSTANCE entry is moved from the free list
|
||
to the InUse list and the corresponding pointer is saved for
|
||
subsequent use by this application
|
||
|
||
--*/
|
||
{
|
||
LONG status;
|
||
TCHAR szMappedObject[] = SHARED_MEMORY_OBJECT_NAME;
|
||
DWORD dwBytes;
|
||
|
||
// save this DLL handle
|
||
ThisDLLHandle = DllHandle;
|
||
|
||
// disable thread attach & detach calls to save the overhead
|
||
// since we don't care about them.
|
||
DisableThreadLibraryCalls (DllHandle);
|
||
|
||
// open & initialize shared memory file
|
||
SetLastError (ERROR_SUCCESS); // just to clear it out
|
||
|
||
// open/create shared memory used by the application to pass performance values
|
||
status = GetSharedMemoryDataHeader (
|
||
&hAppMemSharedMemory, NULL, &pDataHeader,
|
||
FALSE); // read/write access is required
|
||
// here the memory block should be initialized and ready for use
|
||
if (status == ERROR_SUCCESS) {
|
||
if (pDataHeader->dwFirstFreeOffset != 0) {
|
||
// then there are blocks left so get the next free
|
||
pAppData = FIRST_FREE(pDataHeader);
|
||
// update free list to make next item the first in list
|
||
pDataHeader->dwFirstFreeOffset = pAppData->dwOffsetOfNext;
|
||
|
||
// insert the new item into the head of the in use list
|
||
pAppData->dwOffsetOfNext = pDataHeader->dwFirstInUseOffset;
|
||
pDataHeader->dwFirstInUseOffset = (DWORD)((LPBYTE)pAppData -
|
||
(LPBYTE)pDataHeader);
|
||
|
||
// now initialize this instance's data
|
||
pAppData->dwProcessId = GetCurrentProcessId(); // id of process using this instance
|
||
|
||
dwBytes = sizeof (APP_DATA_SAMPLE) * TD_TOTAL;
|
||
dwBytes += sizeof (DWORD) * DD_TOTAL;
|
||
memset (&pAppData->TimeData[0], 0, dwBytes);
|
||
|
||
pDataHeader->dwInstanceCount++; // increment count
|
||
} else {
|
||
// no more free slots left
|
||
assert (pDataHeader->dwFirstFreeOffset != 0);
|
||
}
|
||
} else {
|
||
// unable to open shared memory file
|
||
// even though this is an error we should return true so as to
|
||
// not abort the application. No performance data will be
|
||
// collected though.
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
DllProcessDetach (
|
||
IN HANDLE DllHandle
|
||
)
|
||
{
|
||
PAPPMEM_INSTANCE pPrevItem;
|
||
|
||
// remove instance for this app
|
||
if ((pAppData != NULL) && (pDataHeader != NULL)) {
|
||
// zero the fields out first
|
||
memset (pAppData, 0, sizeof (APPMEM_INSTANCE));
|
||
// move from in use (busy) list back to the free list
|
||
if ((pDataHeader->dwFirstFreeOffset != 0) && (pDataHeader->dwFirstInUseOffset != 0)) {
|
||
// find previous item in busy list
|
||
if (FIRST_INUSE(pDataHeader) != pAppData) {
|
||
// not the first so walk down the list
|
||
pPrevItem = FIRST_INUSE(pDataHeader);
|
||
while (APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext) != pAppData) {
|
||
pPrevItem = APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext);
|
||
if (pPrevItem->dwOffsetOfNext == 0) break; // end of list
|
||
}
|
||
if (APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext) == pAppData) {
|
||
APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext)->dwOffsetOfNext =
|
||
pAppData->dwOffsetOfNext;
|
||
} else {
|
||
// it was never in the busy list (?!?)
|
||
}
|
||
} else {
|
||
// this is the first in the list so update it
|
||
pDataHeader->dwFirstInUseOffset = pAppData->dwOffsetOfNext;
|
||
}
|
||
// here, pAppData has been removed from the InUse list and now
|
||
// it must be inserted back at the beginning of the free list
|
||
pAppData->dwOffsetOfNext = pDataHeader->dwFirstFreeOffset;
|
||
pDataHeader->dwFirstFreeOffset = (DWORD)((LPBYTE)pAppData - (LPBYTE)pDataHeader);
|
||
}
|
||
}
|
||
|
||
// decrement instance counter
|
||
pDataHeader->dwInstanceCount--; // decrement count
|
||
|
||
// close shared memory file handle
|
||
|
||
if (hAppMemSharedMemory != NULL) CloseHandle (hAppMemSharedMemory);
|
||
|
||
// clear pointers
|
||
hAppMemSharedMemory = NULL;
|
||
pDataHeader = NULL;
|
||
pAppData = NULL;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL
|
||
__stdcall
|
||
AppPerfOpen(HINSTANCE hInstance)
|
||
{
|
||
return DllProcessAttach (hInstance);
|
||
}
|
||
BOOL
|
||
__stdcall
|
||
AppPerfClose(HINSTANCE hInstance)
|
||
{
|
||
return DllProcessDetach (hInstance);
|
||
}
|
||
|
||
void
|
||
UpdateAppPerfTimeData (
|
||
DWORD dwItemId,
|
||
DWORD dwStage
|
||
)
|
||
{
|
||
LONGLONG llTime;
|
||
assert (dwItemId < TD_TOTAL);
|
||
QueryPerformanceCounter ((LARGE_INTEGER *)&llTime);
|
||
// GetSystemTimeAsFileTime ((LPFILETIME)&llTime);
|
||
if (dwStage == TD_BEGIN) {
|
||
assert (pAppData->TimeData[dwItemId].dw1 == 0); // this shouldn't be called while timing
|
||
pAppData->TimeData[dwItemId].ll1 = llTime; // save start time
|
||
pAppData->TimeData[dwItemId].dw1++; // indicate were counting
|
||
} else {
|
||
assert (pAppData->TimeData[dwItemId].dw1 == 1); // this should only be called while timing
|
||
pAppData->TimeData[dwItemId].ll0 += llTime; // add in current time
|
||
// then remove the start time
|
||
pAppData->TimeData[dwItemId].ll0 -= pAppData->TimeData[dwItemId].ll1;
|
||
// increment completed operation count
|
||
pAppData->TimeData[dwItemId].dw0++;
|
||
// decrement busy count
|
||
pAppData->TimeData[dwItemId].dw1--;
|
||
}
|
||
return;
|
||
}
|
||
|
||
void
|
||
UpdateAppPerfDwordData (
|
||
DWORD dwItemId,
|
||
DWORD dwValue
|
||
)
|
||
{
|
||
assert (dwItemId < DD_TOTAL);
|
||
pAppData->DwordData[dwItemId] = dwValue;
|
||
return;
|
||
}
|
||
#endif |