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

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1999.
  5. //
  6. // File: perfobj.cxx
  7. //
  8. // Contents: Performance Data Object
  9. //
  10. // Classes : CPerfMon
  11. //
  12. // History: 23-March-94 t-joshh Created
  13. // 14-Jan-98 dlee Cleanup
  14. // 10-May-99 dlee More cleanup
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include <smem.hxx>
  20. #include <mutex.hxx>
  21. #include <perfci.hxx>
  22. #include <perfobj.hxx>
  23. #include <ciregkey.hxx>
  24. DECLARE_INFOLEVEL(Perf)
  25. //
  26. // Total size occupied by the filter and CI counters
  27. //
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Function : ComputeCIPerfmonVars
  31. //
  32. // Purpose : Computes sizes of various data structures that deal with
  33. // CI perfmon counters.
  34. //
  35. // Arguments : [cMaxCats] -- Returns the maximum number of catalogs
  36. // that can be open at once.
  37. // [cbCatBitfield] -- Returns the count of bytes needed for
  38. // the bitfield used to keep track of
  39. // the slots in the shared memory allocated
  40. // for each catalog's perfmon info. There
  41. // is one slot per catalog.
  42. // [cbPerfHeader] -- Returns the count of bytes at the start
  43. // of the shared memory used for header info.
  44. // After the header comes the catalog slots.
  45. // [cbSharedMem] -- Returns the count of bytes of the shared
  46. // memory buffer.
  47. //
  48. // History : 5-April-99 dlee Created
  49. //
  50. //----------------------------------------------------------------------------
  51. void ComputeCIPerfmonVars(
  52. ULONG & cMaxCats,
  53. ULONG & cbCatBitfield,
  54. ULONG & cbPerfHeader,
  55. ULONG & cbSharedMem )
  56. {
  57. cMaxCats = GetMaxCatalogs();
  58. //
  59. // The bitfield must be large enough to hold 1 bit per catalog, rounded
  60. // up to the closest byte.
  61. //
  62. cbCatBitfield = AlignBlock( cMaxCats, cBitsPerByte ) / cBitsPerByte;
  63. cbCatBitfield = AlignBlock( cbCatBitfield, sizeof DWORD );
  64. //
  65. // The header includes the # of instances, the bitfield, and 2 sequence
  66. // number integers.
  67. //
  68. cbPerfHeader = ( 3 * sizeof( int ) ) + cbCatBitfield;
  69. //
  70. // The shared memory must be large enough for the header and 1 slot for
  71. // each catalog. Each slot consists of an int header, the actual
  72. // counters, and the name of the catalog.
  73. //
  74. cbSharedMem = cbPerfHeader + ( cMaxCats * cbPerfCatalogSlot );
  75. ciDebugOut(( DEB_ITRACE, "header: %d, each %d\n", cbPerfHeader, cbPerfCatalogSlot ));
  76. ciDebugOut(( DEB_ITRACE, "cbSharedMem: %#x\n", cbSharedMem ));
  77. // Round the shared memory up to a page size
  78. SYSTEM_INFO si;
  79. GetSystemInfo( &si );
  80. cbSharedMem = AlignBlock( cbSharedMem, si.dwPageSize );
  81. ciDebugOut(( DEB_ITRACE, "cbSharedMem: after %#x\n", cbSharedMem ));
  82. } //ComputeCIPerfmonVars
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Function : CPerfMon::CPerfMon
  86. //
  87. // Purpose : Constructor
  88. //
  89. // Arguments : [wszInstanceName] -- name of the performance object
  90. //
  91. // History : 23-March-94 t-joshh Created
  92. //
  93. //----------------------------------------------------------------------------
  94. CPerfMon::CPerfMon (
  95. const WCHAR * wszInstanceName ) :
  96. _cCounters( FILTER_TOTAL_NUM_COUNTERS + CI_TOTAL_NUM_COUNTERS ),
  97. _pdwSharedMemory( 0 ),
  98. _pcCount( 0 ),
  99. _pbBitfield( 0 ),
  100. _pSeqNo(0),
  101. _iWhichSlot( 0 ),
  102. _piNumberAttach( 0 )
  103. {
  104. ULONG cMaxCats, cbCatBitfield, cbPerfHeader, cbSharedMem;
  105. ComputeCIPerfmonVars( cMaxCats, cbCatBitfield, cbPerfHeader, cbSharedMem );
  106. // Open the performance object
  107. _SharedMemObj.CreateForWriteFromRegKey( CI_PERF_MEM_NAME,
  108. cbSharedMem,
  109. wcsContentIndexPerfKey );
  110. if ( !_SharedMemObj.Ok() )
  111. THROW( CException( E_OUTOFMEMORY ) );
  112. _xPerfMutex.Set( new CNamedMutex() );
  113. _xPerfMutex->Init( CI_PERF_MUTEX_NAME );
  114. CNamedMutexLock lock( _xPerfMutex.GetReference() );
  115. // Fill in the number of instances
  116. _pcCount = (int *) _SharedMemObj.Get();
  117. _pbBitfield = ((BYTE *)_SharedMemObj.Get() + sizeof(int));
  118. _pSeqNo = (UINT *) ( _pbBitfield + cbCatBitfield );
  119. //
  120. // First, check whether there already exist a block in the memory assigned to
  121. // the specified object. If existed, just assign the existing block.
  122. // If not, assign a non-occupied block.
  123. //
  124. int iFirstEmpty = -1;
  125. int iTmpCount = *_pcCount;
  126. //
  127. // Copy the instance (catalog) name or just the prefix that fits
  128. //
  129. unsigned cwc = wcslen( wszInstanceName );
  130. cwc = __min( cwc, CI_PERF_MAX_CATALOG_LEN - 1 );
  131. WCHAR awcName[ CI_PERF_MAX_CATALOG_LEN ];
  132. RtlCopyMemory( awcName, wszInstanceName, cwc * sizeof WCHAR );
  133. awcName[ cwc ] = 0;
  134. CBitfield bits( _pbBitfield );
  135. for ( int i = 0;
  136. i < (int) cMaxCats && (iTmpCount > 0 || iFirstEmpty == -1);
  137. i++ )
  138. {
  139. if ( !bits.IsBitSet( i ) )
  140. {
  141. if (iFirstEmpty == -1)
  142. iFirstEmpty = i;
  143. }
  144. else
  145. {
  146. ULONG ulByte = cbPerfHeader + (i * cbPerfCatalogSlot) + sizeof(int);
  147. if ( 0 == wcscmp( (WCHAR *) ((BYTE *)_SharedMemObj.Get() + ulByte), awcName ) )
  148. {
  149. _iWhichSlot = i;
  150. break;
  151. }
  152. iTmpCount--;
  153. }
  154. }
  155. if ( iTmpCount <= 0 )
  156. {
  157. _iWhichSlot = iFirstEmpty;
  158. bits.SetBit( _iWhichSlot );
  159. *_pcCount += 1;
  160. }
  161. //
  162. // The catarray protects us agains opening too many catalogs, but the
  163. // user can change MaxCatalogs in the registry at any time...
  164. //
  165. if ( -1 == _iWhichSlot )
  166. {
  167. Win4Assert( !"too many catalogs open!" );
  168. THROW( CException( E_INVALIDARG ) );
  169. }
  170. //
  171. // Update the sequence number
  172. //
  173. *_pSeqNo += 1;
  174. PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Sequence Number %d \n", *_pSeqNo ));
  175. PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Chosen Block %d No. of Instance %d\n", _iWhichSlot, *_pcCount));
  176. ULONG ulByteToSkip = cbPerfHeader + ( _iWhichSlot * cbPerfCatalogSlot );
  177. //
  178. // Increment the number of PerfMon object attached to this slot by 1
  179. //
  180. _piNumberAttach = (int *) ((BYTE *)_SharedMemObj.Get() + ulByteToSkip);
  181. PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Number of Object Attached : %d\n", *_piNumberAttach));
  182. *_piNumberAttach += 1;
  183. ulByteToSkip += sizeof(int);
  184. //
  185. // Fill the name of the instance into the shared memory
  186. //
  187. wcscpy( (WCHAR *)((BYTE *)_SharedMemObj.Get() + ulByteToSkip), awcName );
  188. //
  189. // Assign a block of memory space for each instance
  190. //
  191. _pdwSharedMemory = ((DWORD *) ( (BYTE *)_SharedMemObj.Get()
  192. + ulByteToSkip
  193. + ( CI_PERF_MAX_CATALOG_LEN * sizeof WCHAR ) ) );
  194. PerfDebugOut(( DEB_ITRACE, "@@@ Writer : Done with Initialize CPerfMon \n"));
  195. } //CPerfMon
  196. //+---------------------------------------------------------------------------
  197. //
  198. // Function : CPerfMon::~CPerfMon
  199. //
  200. // Purpose : Destructor
  201. //
  202. // Arguments : none
  203. //
  204. // History : 23-March-94 t-joshh Created
  205. //
  206. //----------------------------------------------------------------------------
  207. CPerfMon::~CPerfMon()
  208. {
  209. CNamedMutexLock lock( _xPerfMutex.GetReference() );
  210. if ( 1 == *_piNumberAttach )
  211. {
  212. //
  213. // Since the current CPerfMon is the last one using the slot, the
  214. // slot will be cleaned up and the number of instances reduce by 1
  215. //
  216. *_pcCount -= 1;
  217. PerfDebugOut(( DEB_ITRACE, "~CPerfMon : No. of Instance become %d\n", *_pcCount));
  218. CBitfield bits( _pbBitfield );
  219. bits.ClearBit( _iWhichSlot );
  220. RtlZeroMemory( (void *)_piNumberAttach, cbPerfCatalogSlot );
  221. *_pSeqNo += 1; // Update the sequence number
  222. PerfDebugOut(( DEB_ITRACE, "~CPerfMon : Update SeqNo %d\n", *_pSeqNo ));
  223. }
  224. else
  225. {
  226. //
  227. // There are still some other CPerfMon object attached to this slot
  228. //
  229. *_piNumberAttach -= 1;
  230. PerfDebugOut(( DEB_ITRACE, " ~CPerfMon : Still have %d object attached\n", *_piNumberAttach));
  231. }
  232. } //~CPerfMon