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.
 
 
 
 
 
 

291 lines
8.5 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1999.
//
// File: perfobj.cxx
//
// Contents: Performance Data Object
//
// Classes : CPerfMon
//
// History: 23-March-94 t-joshh Created
// 14-Jan-98 dlee Cleanup
// 10-May-99 dlee More cleanup
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <smem.hxx>
#include <mutex.hxx>
#include <perfci.hxx>
#include <perfobj.hxx>
#include <ciregkey.hxx>
DECLARE_INFOLEVEL(Perf)
//
// Total size occupied by the filter and CI counters
//
//+---------------------------------------------------------------------------
//
// Function : ComputeCIPerfmonVars
//
// Purpose : Computes sizes of various data structures that deal with
// CI perfmon counters.
//
// Arguments : [cMaxCats] -- Returns the maximum number of catalogs
// that can be open at once.
// [cbCatBitfield] -- Returns the count of bytes needed for
// the bitfield used to keep track of
// the slots in the shared memory allocated
// for each catalog's perfmon info. There
// is one slot per catalog.
// [cbPerfHeader] -- Returns the count of bytes at the start
// of the shared memory used for header info.
// After the header comes the catalog slots.
// [cbSharedMem] -- Returns the count of bytes of the shared
// memory buffer.
//
// History : 5-April-99 dlee Created
//
//----------------------------------------------------------------------------
void ComputeCIPerfmonVars(
ULONG & cMaxCats,
ULONG & cbCatBitfield,
ULONG & cbPerfHeader,
ULONG & cbSharedMem )
{
cMaxCats = GetMaxCatalogs();
//
// The bitfield must be large enough to hold 1 bit per catalog, rounded
// up to the closest byte.
//
cbCatBitfield = AlignBlock( cMaxCats, cBitsPerByte ) / cBitsPerByte;
cbCatBitfield = AlignBlock( cbCatBitfield, sizeof DWORD );
//
// The header includes the # of instances, the bitfield, and 2 sequence
// number integers.
//
cbPerfHeader = ( 3 * sizeof( int ) ) + cbCatBitfield;
//
// The shared memory must be large enough for the header and 1 slot for
// each catalog. Each slot consists of an int header, the actual
// counters, and the name of the catalog.
//
cbSharedMem = cbPerfHeader + ( cMaxCats * cbPerfCatalogSlot );
ciDebugOut(( DEB_ITRACE, "header: %d, each %d\n", cbPerfHeader, cbPerfCatalogSlot ));
ciDebugOut(( DEB_ITRACE, "cbSharedMem: %#x\n", cbSharedMem ));
// Round the shared memory up to a page size
SYSTEM_INFO si;
GetSystemInfo( &si );
cbSharedMem = AlignBlock( cbSharedMem, si.dwPageSize );
ciDebugOut(( DEB_ITRACE, "cbSharedMem: after %#x\n", cbSharedMem ));
} //ComputeCIPerfmonVars
//+---------------------------------------------------------------------------
//
// Function : CPerfMon::CPerfMon
//
// Purpose : Constructor
//
// Arguments : [wszInstanceName] -- name of the performance object
//
// History : 23-March-94 t-joshh Created
//
//----------------------------------------------------------------------------
CPerfMon::CPerfMon (
const WCHAR * wszInstanceName ) :
_cCounters( FILTER_TOTAL_NUM_COUNTERS + CI_TOTAL_NUM_COUNTERS ),
_pdwSharedMemory( 0 ),
_pcCount( 0 ),
_pbBitfield( 0 ),
_pSeqNo(0),
_iWhichSlot( 0 ),
_piNumberAttach( 0 )
{
ULONG cMaxCats, cbCatBitfield, cbPerfHeader, cbSharedMem;
ComputeCIPerfmonVars( cMaxCats, cbCatBitfield, cbPerfHeader, cbSharedMem );
// Open the performance object
_SharedMemObj.CreateForWriteFromRegKey( CI_PERF_MEM_NAME,
cbSharedMem,
wcsContentIndexPerfKey );
if ( !_SharedMemObj.Ok() )
THROW( CException( E_OUTOFMEMORY ) );
_xPerfMutex.Set( new CNamedMutex() );
_xPerfMutex->Init( CI_PERF_MUTEX_NAME );
CNamedMutexLock lock( _xPerfMutex.GetReference() );
// Fill in the number of instances
_pcCount = (int *) _SharedMemObj.Get();
_pbBitfield = ((BYTE *)_SharedMemObj.Get() + sizeof(int));
_pSeqNo = (UINT *) ( _pbBitfield + cbCatBitfield );
//
// First, check whether there already exist a block in the memory assigned to
// the specified object. If existed, just assign the existing block.
// If not, assign a non-occupied block.
//
int iFirstEmpty = -1;
int iTmpCount = *_pcCount;
//
// Copy the instance (catalog) name or just the prefix that fits
//
unsigned cwc = wcslen( wszInstanceName );
cwc = __min( cwc, CI_PERF_MAX_CATALOG_LEN - 1 );
WCHAR awcName[ CI_PERF_MAX_CATALOG_LEN ];
RtlCopyMemory( awcName, wszInstanceName, cwc * sizeof WCHAR );
awcName[ cwc ] = 0;
CBitfield bits( _pbBitfield );
for ( int i = 0;
i < (int) cMaxCats && (iTmpCount > 0 || iFirstEmpty == -1);
i++ )
{
if ( !bits.IsBitSet( i ) )
{
if (iFirstEmpty == -1)
iFirstEmpty = i;
}
else
{
ULONG ulByte = cbPerfHeader + (i * cbPerfCatalogSlot) + sizeof(int);
if ( 0 == wcscmp( (WCHAR *) ((BYTE *)_SharedMemObj.Get() + ulByte), awcName ) )
{
_iWhichSlot = i;
break;
}
iTmpCount--;
}
}
if ( iTmpCount <= 0 )
{
_iWhichSlot = iFirstEmpty;
bits.SetBit( _iWhichSlot );
*_pcCount += 1;
}
//
// The catarray protects us agains opening too many catalogs, but the
// user can change MaxCatalogs in the registry at any time...
//
if ( -1 == _iWhichSlot )
{
Win4Assert( !"too many catalogs open!" );
THROW( CException( E_INVALIDARG ) );
}
//
// Update the sequence number
//
*_pSeqNo += 1;
PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Sequence Number %d \n", *_pSeqNo ));
PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Chosen Block %d No. of Instance %d\n", _iWhichSlot, *_pcCount));
ULONG ulByteToSkip = cbPerfHeader + ( _iWhichSlot * cbPerfCatalogSlot );
//
// Increment the number of PerfMon object attached to this slot by 1
//
_piNumberAttach = (int *) ((BYTE *)_SharedMemObj.Get() + ulByteToSkip);
PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Number of Object Attached : %d\n", *_piNumberAttach));
*_piNumberAttach += 1;
ulByteToSkip += sizeof(int);
//
// Fill the name of the instance into the shared memory
//
wcscpy( (WCHAR *)((BYTE *)_SharedMemObj.Get() + ulByteToSkip), awcName );
//
// Assign a block of memory space for each instance
//
_pdwSharedMemory = ((DWORD *) ( (BYTE *)_SharedMemObj.Get()
+ ulByteToSkip
+ ( CI_PERF_MAX_CATALOG_LEN * sizeof WCHAR ) ) );
PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Done with Initialize CPerfMon \n"));
} //CPerfMon
//+---------------------------------------------------------------------------
//
// Function : CPerfMon::~CPerfMon
//
// Purpose : Destructor
//
// Arguments : none
//
// History : 23-March-94 t-joshh Created
//
//----------------------------------------------------------------------------
CPerfMon::~CPerfMon()
{
CNamedMutexLock lock( _xPerfMutex.GetReference() );
if ( 1 == *_piNumberAttach )
{
//
// Since the current CPerfMon is the last one using the slot, the
// slot will be cleaned up and the number of instances reduce by 1
//
*_pcCount -= 1;
PerfDebugOut(( DEB_ITRACE, "~CPerfMon : No. of Instance become %d\n", *_pcCount));
CBitfield bits( _pbBitfield );
bits.ClearBit( _iWhichSlot );
RtlZeroMemory( (void *)_piNumberAttach, cbPerfCatalogSlot );
*_pSeqNo += 1; // Update the sequence number
PerfDebugOut(( DEB_ITRACE, "~CPerfMon : Update SeqNo %d\n", *_pSeqNo ));
}
else
{
//
// There are still some other CPerfMon object attached to this slot
//
*_piNumberAttach -= 1;
PerfDebugOut(( DEB_ITRACE, " ~CPerfMon : Still have %d object attached\n", *_piNumberAttach));
}
} //~CPerfMon