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.

1421 lines
32 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. counters.cxx
  5. Abstract:
  6. Contains the performance monitoring counter management code
  7. Author:
  8. Eric Stenson (ericsten) 25-Sep-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "countersp.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text( INIT, UlInitializeCounters )
  15. #pragma alloc_text( PAGE, UlTerminateCounters )
  16. #pragma alloc_text( PAGE, UlCreateSiteCounterEntry )
  17. #if REFERENCE_DEBUG
  18. #pragma alloc_text( PAGE, UlReferenceSiteCounterEntry )
  19. #pragma alloc_text( PAGE, UlDereferenceSiteCounterEntry )
  20. #endif
  21. #pragma alloc_text( PAGE, UlGetGlobalCounters )
  22. #pragma alloc_text( PAGE, UlGetSiteCounters )
  23. #endif // ALLOC_PRAGMA
  24. #if 0
  25. NOT PAGEABLE -- UlIncCounter
  26. NOT PAGEABLE -- UlDecCounter
  27. NOT PAGEABLE -- UlAddCounter
  28. NOT PAGEABLE -- UlResetCounter
  29. NOT PAGEABLE -- UlIncSiteCounter
  30. NOT PAGEABLE -- UlDecSiteCounter
  31. NOT PAGEABLE -- UlAddSiteCounter
  32. NOT PAGEABLE -- UlResetSiteCounter
  33. NOT PAGEABLE -- UlMaxSiteCounter
  34. NOT PAGEABLE -- UlMaxSiteCounter64
  35. #endif
  36. BOOLEAN g_InitCountersCalled = FALSE;
  37. HTTP_GLOBAL_COUNTERS g_UlGlobalCounters;
  38. FAST_MUTEX g_SiteCounterListMutex;
  39. LIST_ENTRY g_SiteCounterListHead = {NULL,NULL};
  40. LONG g_SiteCounterListCount = 0;
  41. /***************************************************************************++
  42. Routine Description:
  43. Performs global initialization of the global (cache) and instance (per
  44. site) counters.
  45. Return Value:
  46. NTSTATUS - Completion status.
  47. --***************************************************************************/
  48. NTSTATUS
  49. UlInitializeCounters(
  50. VOID
  51. )
  52. {
  53. NTSTATUS Status = STATUS_SUCCESS;
  54. //
  55. // Sanity check.
  56. //
  57. PAGED_CODE();
  58. ASSERT( !g_InitCountersCalled );
  59. UlTrace(PERF_COUNTERS, ("http!UlInitializeCounters\n"));
  60. if (!g_InitCountersCalled)
  61. {
  62. //
  63. // zero out global counter block
  64. //
  65. RtlZeroMemory(&g_UlGlobalCounters, sizeof(HTTP_GLOBAL_COUNTERS));
  66. //
  67. // init Site Counter list
  68. //
  69. ExInitializeFastMutex(&g_SiteCounterListMutex);
  70. InitializeListHead(&g_SiteCounterListHead);
  71. g_SiteCounterListCount = 0;
  72. // done!
  73. g_InitCountersCalled = TRUE;
  74. }
  75. RETURN( Status );
  76. } // UlInitializeCounters
  77. /***************************************************************************++
  78. Routine Description:
  79. Performs global cleanup of the global (cache) and instance (per
  80. site) counters.
  81. --***************************************************************************/
  82. VOID
  83. UlTerminateCounters(
  84. VOID
  85. )
  86. {
  87. //
  88. // [debug only] Walk list of counters and check the ref count for each counter block.
  89. //
  90. #if DBG
  91. PLIST_ENTRY pEntry;
  92. PUL_SITE_COUNTER_ENTRY pCounterEntry;
  93. if (!g_InitCountersCalled)
  94. {
  95. goto End;
  96. }
  97. if (IsListEmpty(&g_SiteCounterListHead))
  98. {
  99. ASSERT(0 == g_SiteCounterListCount);
  100. // Good! No counters left behind!
  101. goto End;
  102. }
  103. //
  104. // Walk list of Site Counter Entries
  105. //
  106. pEntry = g_SiteCounterListHead.Flink;
  107. while (pEntry != &g_SiteCounterListHead)
  108. {
  109. pCounterEntry = CONTAINING_RECORD(
  110. pEntry,
  111. UL_SITE_COUNTER_ENTRY,
  112. ListEntry
  113. );
  114. ASSERT(IS_VALID_SITE_COUNTER_ENTRY(pCounterEntry));
  115. UlTrace(PERF_COUNTERS,
  116. ("http!UlTerminateCounters: Error: pCounterEntry %p SiteId %d RefCount %d\n",
  117. pCounterEntry,
  118. pCounterEntry->Counters.SiteId,
  119. pCounterEntry->RefCount
  120. ));
  121. pEntry = pEntry->Flink;
  122. }
  123. End:
  124. return;
  125. #endif // DBG
  126. }
  127. ///////////////////////////////////////////////////////////////////////////////
  128. // Site Counter Entry
  129. //
  130. /***************************************************************************++
  131. Routine Description:
  132. Creates a new site counter entry for the given SiteId.
  133. Arguments:
  134. SiteId - the site id for the site counters.
  135. Return Value:
  136. NTSTATUS - Completion status.
  137. --***************************************************************************/
  138. NTSTATUS
  139. UlCreateSiteCounterEntry(
  140. IN OUT PUL_CONFIG_GROUP_OBJECT pConfigGroup,
  141. ULONG SiteId
  142. )
  143. {
  144. NTSTATUS Status;
  145. PUL_SITE_COUNTER_ENTRY pNewEntry;
  146. //
  147. // Sanity check.
  148. //
  149. PAGED_CODE();
  150. ASSERT( pConfigGroup != NULL );
  151. //
  152. // Setup locals so we know how to cleanup on exit.
  153. //
  154. Status = STATUS_SUCCESS;
  155. //
  156. // [debug only] Check to see if the SiteId is already
  157. // in the list of existing Site Counter Entries.
  158. //
  159. ASSERT(!UlpIsInSiteCounterList(SiteId));
  160. // Alloc new struct w/space from Non Paged Pool
  161. pNewEntry = UL_ALLOCATE_STRUCT(
  162. NonPagedPool,
  163. UL_SITE_COUNTER_ENTRY,
  164. UL_SITE_COUNTER_ENTRY_POOL_TAG);
  165. if (pNewEntry)
  166. {
  167. UlTrace( PERF_COUNTERS,
  168. ("http!UlCreateSiteCounterEntry: pNewEntry %p, pConfigGroup %p, SiteId %d\n",
  169. pNewEntry,
  170. pConfigGroup,
  171. SiteId )
  172. );
  173. pNewEntry->Signature = UL_SITE_COUNTER_ENTRY_POOL_TAG;
  174. pNewEntry->RefCount = 1;
  175. // Zero out counters
  176. RtlZeroMemory(&(pNewEntry->Counters), sizeof(HTTP_SITE_COUNTERS));
  177. // Set Site ID
  178. pNewEntry->Counters.SiteId = SiteId;
  179. // Init Counter Mutex
  180. ExInitializeFastMutex(&(pNewEntry->EntryMutex));
  181. // Add to Site Counter List
  182. ExAcquireFastMutex(&g_SiteCounterListMutex);
  183. InsertTailList(
  184. &g_SiteCounterListHead,
  185. &(pNewEntry->ListEntry)
  186. );
  187. g_SiteCounterListCount++;
  188. ExReleaseFastMutex(&g_SiteCounterListMutex);
  189. // Check for wrap-around of Site List count.
  190. ASSERT( 0 != g_SiteCounterListCount );
  191. }
  192. else
  193. {
  194. UlTrace( PERF_COUNTERS,
  195. ("http!UlCreateSiteCounterEntry: Error: NO_MEMORY pConfigGroup %p, SiteId %d\n",
  196. pNewEntry,
  197. pConfigGroup,
  198. SiteId )
  199. );
  200. Status = STATUS_NO_MEMORY;
  201. }
  202. pConfigGroup->pSiteCounters = pNewEntry;
  203. RETURN( Status );
  204. }
  205. #if REFERENCE_DEBUG
  206. /***************************************************************************++
  207. Routine Description:
  208. increments the refcount.
  209. Arguments:
  210. pEntry - the object to increment.
  211. Return Value:
  212. NTSTATUS - Completion status.
  213. --***************************************************************************/
  214. VOID
  215. UlReferenceSiteCounterEntry(
  216. IN PUL_SITE_COUNTER_ENTRY pEntry
  217. REFERENCE_DEBUG_FORMAL_PARAMS
  218. )
  219. {
  220. LONG refCount;
  221. //
  222. // Sanity check.
  223. //
  224. PAGED_CODE();
  225. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  226. refCount = InterlockedIncrement( &pEntry->RefCount );
  227. //
  228. // Tracing.
  229. //
  230. WRITE_REF_TRACE_LOG(
  231. g_pSiteCounterTraceLog,
  232. REF_ACTION_REFERENCE_SITE_COUNTER_ENTRY,
  233. refCount,
  234. pEntry,
  235. pFileName,
  236. LineNumber
  237. );
  238. UlTrace(
  239. REFCOUNT,
  240. ("http!UlReferenceSiteCounterEntry pEntry=%p refcount=%d SiteId=%d\n",
  241. pEntry,
  242. refCount,
  243. pEntry->Counters.SiteId)
  244. );
  245. } // UlReferenceAppPool
  246. /***************************************************************************++
  247. Routine Description:
  248. decrements the refcount. if it hits 0, destruct's the site counter entry
  249. block.
  250. Arguments:
  251. pEntry - the object to decrement.
  252. Return Value:
  253. NTSTATUS - Completion status.
  254. --***************************************************************************/
  255. VOID
  256. UlDereferenceSiteCounterEntry(
  257. IN PUL_SITE_COUNTER_ENTRY pEntry
  258. REFERENCE_DEBUG_FORMAL_PARAMS
  259. )
  260. {
  261. LONG refCount;
  262. NTSTATUS Status;
  263. //
  264. // Sanity check.
  265. //
  266. PAGED_CODE();
  267. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  268. refCount = InterlockedDecrement( &pEntry->RefCount );
  269. //
  270. // Tracing.
  271. //
  272. WRITE_REF_TRACE_LOG(
  273. g_pSiteCounterTraceLog,
  274. REF_ACTION_DEREFERENCE_SITE_COUNTER_ENTRY,
  275. refCount,
  276. pEntry,
  277. pFileName,
  278. LineNumber
  279. );
  280. UlTrace(
  281. REFCOUNT,
  282. ("http!UlDereferenceSiteCounter pEntry=%p refcount=%d SiteId=%d\n",
  283. pEntry,
  284. refCount,
  285. pEntry->Counters.SiteId)
  286. );
  287. //
  288. // Remove from the list if we hit zero
  289. //
  290. if (refCount == 0)
  291. {
  292. ASSERT( 0 != g_SiteCounterListCount );
  293. UlTrace(
  294. PERF_COUNTERS,
  295. ("http!UlDereferenceSiteCounter: Removing pEntry=%p SiteId=%d\n",
  296. pEntry,
  297. pEntry->Counters.SiteId)
  298. );
  299. // Remove from list
  300. ExAcquireFastMutex(&g_SiteCounterListMutex);
  301. RemoveEntryList(&pEntry->ListEntry);
  302. pEntry->ListEntry.Flink = pEntry->ListEntry.Blink = NULL;
  303. g_SiteCounterListCount--;
  304. ExReleaseFastMutex(&g_SiteCounterListMutex);
  305. // Release memory
  306. UL_FREE_POOL_WITH_SIG(pEntry, UL_SITE_COUNTER_ENTRY_POOL_TAG);
  307. }
  308. }
  309. #endif
  310. ///////////////////////////////////////////////////////////////////////////////
  311. // Collection
  312. //
  313. /***************************************************************************++
  314. Routine Description:
  315. Gets the Global (cache) counters.
  316. Arguments:
  317. pCounter - pointer to block of memory where the counter data should be
  318. written.
  319. BlockSize - Maximum size available at pCounter.
  320. pBytesWritten - On success, count of bytes written into the block of
  321. memory at pCounter. On failure, the required count of bytes for the
  322. memory at pCounter.
  323. Return Value:
  324. NTSTATUS - Completion status.
  325. --***************************************************************************/
  326. NTSTATUS
  327. UlGetGlobalCounters(
  328. PVOID IN OUT pCounter,
  329. ULONG IN BlockSize,
  330. PULONG OUT pBytesWritten
  331. )
  332. {
  333. ULONG i;
  334. PAGED_CODE();
  335. ASSERT( pBytesWritten );
  336. UlTraceVerbose(PERF_COUNTERS,
  337. ("http!UlGetGlobalCounters\n"));
  338. if (BlockSize < sizeof(HTTP_GLOBAL_COUNTERS))
  339. {
  340. //
  341. // Tell the caller how many bytes are required.
  342. //
  343. *pBytesWritten = sizeof(HTTP_GLOBAL_COUNTERS);
  344. RETURN( STATUS_BUFFER_TOO_SMALL );
  345. }
  346. RtlCopyMemory(
  347. pCounter,
  348. &g_UlGlobalCounters,
  349. sizeof(g_UlGlobalCounters)
  350. );
  351. //
  352. // Zero out any counters that must be zeroed.
  353. //
  354. for ( i = 0; i < HttpGlobalCounterMaximum; i++ )
  355. {
  356. if (TRUE == aIISULGlobalDescription[i].WPZeros)
  357. {
  358. // Zero it out
  359. UlResetCounter((HTTP_GLOBAL_COUNTER_ID) i);
  360. }
  361. }
  362. *pBytesWritten = sizeof(HTTP_GLOBAL_COUNTERS);
  363. RETURN( STATUS_SUCCESS );
  364. } // UlpGetGlobalCounters
  365. /***************************************************************************++
  366. Routine Description:
  367. Gets the Site (instance) counters for all sites
  368. Arguments:
  369. pCounter - pointer to block of memory where the counter data should be
  370. written.
  371. BlockSize - Maximum size available at pCounter.
  372. pBytesWritten - On success, count of bytes written into the block of
  373. memory at pCounter. On failure, the required count of bytes for the
  374. memory at pCounter.
  375. pBlocksWritten - (optional) On success, count of site counter blocks
  376. written to pCounter.
  377. Return Value:
  378. NTSTATUS - Completion status.
  379. --***************************************************************************/
  380. NTSTATUS
  381. UlGetSiteCounters(
  382. PVOID IN OUT pCounter,
  383. ULONG IN BlockSize,
  384. PULONG OUT pBytesWritten,
  385. PULONG OUT pBlocksWritten OPTIONAL
  386. )
  387. {
  388. NTSTATUS Status;
  389. ULONG i;
  390. ULONG BytesNeeded;
  391. ULONG BytesToGo;
  392. ULONG BlocksSeen;
  393. PUCHAR pBlock;
  394. PLIST_ENTRY pEntry;
  395. PUL_SITE_COUNTER_ENTRY pCounterEntry;
  396. PAGED_CODE();
  397. ASSERT( pBytesWritten );
  398. UlTraceVerbose(PERF_COUNTERS,
  399. ("http!UlGetSiteCounters\n"));
  400. //
  401. // Setup locals so we know how to cleanup on exit.
  402. //
  403. Status = STATUS_SUCCESS;
  404. BytesToGo = BlockSize;
  405. BlocksSeen = 0;
  406. pBlock = (PUCHAR) pCounter;
  407. BytesNeeded = g_SiteCounterListCount * sizeof(HTTP_SITE_COUNTERS);
  408. if (BytesNeeded > BlockSize)
  409. {
  410. // Need more space
  411. *pBytesWritten = BytesNeeded;
  412. Status = STATUS_BUFFER_TOO_SMALL;
  413. goto End;
  414. }
  415. if (IsListEmpty(&g_SiteCounterListHead))
  416. {
  417. // No counters to return.
  418. goto End;
  419. }
  420. //
  421. // NOTE: g_SiteCounterListHead is the only member of
  422. // the list which isn't contained within a UL_SITE_COUNTER_ENTRY.
  423. //
  424. pEntry = g_SiteCounterListHead.Flink;
  425. //
  426. // Walk list of Site Counter Entries
  427. //
  428. while (pEntry != &g_SiteCounterListHead)
  429. {
  430. pCounterEntry = CONTAINING_RECORD(
  431. pEntry,
  432. UL_SITE_COUNTER_ENTRY,
  433. ListEntry
  434. );
  435. if (BytesToGo < sizeof(HTTP_SITE_COUNTERS))
  436. {
  437. // NOTE: the only way this can happen is if someone
  438. // added a site to the end of the site list before
  439. // we finished walking the counter list.
  440. *pBytesWritten = BlockSize + sizeof(HTTP_SITE_COUNTERS);
  441. Status = STATUS_BUFFER_TOO_SMALL;
  442. goto End;
  443. }
  444. RtlCopyMemory(pBlock,
  445. &(pCounterEntry->Counters),
  446. sizeof(HTTP_SITE_COUNTERS)
  447. );
  448. //
  449. // Zero out any counters that must be zeroed.
  450. //
  451. for ( i = 0; i < HttpSiteCounterMaximum; i++ )
  452. {
  453. if (TRUE == aIISULSiteDescription[i].WPZeros)
  454. {
  455. // Zero it out
  456. UlResetSiteCounter(pCounterEntry, (HTTP_SITE_COUNTER_ID) i);
  457. }
  458. }
  459. //
  460. // Continue to next block
  461. //
  462. pBlock += sizeof(HTTP_SITE_COUNTERS);
  463. BytesToGo -= sizeof(HTTP_SITE_COUNTERS);
  464. BlocksSeen++;
  465. pEntry = pEntry->Flink;
  466. }
  467. End:
  468. //
  469. // Set callers values
  470. //
  471. if (STATUS_SUCCESS == Status)
  472. {
  473. // REVIEW: If we failed, *pBytesWritten already contains
  474. // the bytes required value.
  475. *pBytesWritten = DIFF(pBlock - ((PUCHAR)pCounter));
  476. }
  477. if (pBlocksWritten)
  478. {
  479. *pBlocksWritten = BlocksSeen;
  480. }
  481. RETURN( Status );
  482. } // UlpGetSiteCounters
  483. #if REFERENCE_DEBUG
  484. ///////////////////////////////////////////////////////////////////////////////
  485. // Global Counter functions
  486. //
  487. /***************************************************************************++
  488. Routine Description:
  489. Increment a Global (cache) performance counter.
  490. Arguments:
  491. Ctr - ID of Counter to increment
  492. --***************************************************************************/
  493. VOID
  494. UlIncCounter(
  495. HTTP_GLOBAL_COUNTER_ID Ctr
  496. )
  497. {
  498. PCHAR pCtr;
  499. ASSERT( g_InitCountersCalled );
  500. ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
  501. UlTraceVerbose( PERF_COUNTERS,
  502. ("http!UlIncCounter (Ctr == %d)\n", Ctr) );
  503. //
  504. // figure out offset of Ctr in g_UlGlobalCounters
  505. //
  506. pCtr = (PCHAR) &g_UlGlobalCounters;
  507. pCtr += aIISULGlobalDescription[Ctr].Offset;
  508. // figure out data size of Ctr and do
  509. // apropriate thread-safe increment
  510. if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size)
  511. {
  512. // ULONG
  513. InterlockedIncrement((PLONG) pCtr);
  514. }
  515. else
  516. {
  517. // ULONGLONG
  518. UlInterlockedIncrement64((PLONGLONG) pCtr);
  519. }
  520. } // UlIncCounter
  521. /***************************************************************************++
  522. Routine Description:
  523. Decrement a Global (cache) performance counter.
  524. Arguments:
  525. Ctr - ID of Counter to decrement
  526. --***************************************************************************/
  527. VOID
  528. UlDecCounter(
  529. HTTP_GLOBAL_COUNTER_ID Ctr
  530. )
  531. {
  532. PCHAR pCtr;
  533. ASSERT( g_InitCountersCalled );
  534. ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
  535. UlTraceVerbose( PERF_COUNTERS,
  536. ("http!UlDecCounter (Ctr == %d)\n", Ctr));
  537. //
  538. // figure out offset of Ctr in g_UlGlobalCounters
  539. //
  540. pCtr = (PCHAR) &g_UlGlobalCounters;
  541. pCtr += aIISULGlobalDescription[Ctr].Offset;
  542. // figure out data size of Ctr and do
  543. // apropriate thread-safe increment
  544. if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size)
  545. {
  546. // ULONG
  547. InterlockedDecrement((PLONG) pCtr);
  548. }
  549. else
  550. {
  551. // ULONGLONG
  552. UlInterlockedDecrement64((PLONGLONG) pCtr);
  553. }
  554. }
  555. /***************************************************************************++
  556. Routine Description:
  557. Add a ULONG value to a Global (cache) performance counter.
  558. Arguments:
  559. Ctr - ID of counter to which the Value should be added
  560. Value - The amount to add to the counter
  561. --***************************************************************************/
  562. VOID
  563. UlAddCounter(
  564. HTTP_GLOBAL_COUNTER_ID Ctr,
  565. ULONG Value
  566. )
  567. {
  568. PCHAR pCtr;
  569. ASSERT( g_InitCountersCalled );
  570. ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
  571. UlTraceVerbose( PERF_COUNTERS,
  572. ("http!UlAddCounter (Ctr == %d, Value == %d)\n", Ctr, Value));
  573. //
  574. // figure out offset of Ctr in g_UlGlobalCounters
  575. //
  576. pCtr = (PCHAR) &g_UlGlobalCounters;
  577. pCtr += aIISULGlobalDescription[Ctr].Offset;
  578. //
  579. // figure out data size of Ctr and do
  580. // apropriate thread-safe increment
  581. //
  582. if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size)
  583. {
  584. // ULONG
  585. InterlockedExchangeAdd((PLONG) pCtr, Value);
  586. }
  587. else
  588. {
  589. // ULONGLONG
  590. UlInterlockedAdd64((PLONGLONG) pCtr, Value);
  591. }
  592. } // UlAddCounter
  593. /***************************************************************************++
  594. Routine Description:
  595. Zero-out a Global (cache) performance counter.
  596. Arguments:
  597. Ctr - ID of Counter to be reset.
  598. --***************************************************************************/
  599. VOID
  600. UlResetCounter(
  601. HTTP_GLOBAL_COUNTER_ID Ctr
  602. )
  603. {
  604. // Special Case
  605. PCHAR pCtr;
  606. ASSERT( g_InitCountersCalled );
  607. ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
  608. UlTraceVerbose(PERF_COUNTERS,
  609. ("http!UlResetCounter (Ctr == %d)\n", Ctr));
  610. //
  611. // figure out offset of Ctr in g_UlGlobalCounters
  612. //
  613. pCtr = (PCHAR) &g_UlGlobalCounters;
  614. pCtr += aIISULGlobalDescription[Ctr].Offset;
  615. //
  616. // do apropriate "set" for data size of Ctr
  617. //
  618. if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size)
  619. {
  620. // ULONG
  621. InterlockedExchange((PLONG) pCtr, 0);
  622. }
  623. else
  624. {
  625. // ULONGLONG
  626. LONGLONG localCtr;
  627. LONGLONG originalCtr;
  628. LONGLONG localZero = 0;
  629. do {
  630. localCtr = *((volatile LONGLONG *) pCtr);
  631. originalCtr = InterlockedCompareExchange64( (PLONGLONG) pCtr,
  632. localZero,
  633. localCtr );
  634. } while (originalCtr != localCtr);
  635. }
  636. } // UlResetCounter
  637. ///////////////////////////////////////////////////////////////////////////////
  638. // Site Counter functions
  639. //
  640. /***************************************************************************++
  641. Routine Description:
  642. Increment a NonCritical Site performance counter.
  643. Arguments:
  644. pEntry - pointer to Site Counter entry
  645. CounterId - ID of Counter to increment
  646. Returns:
  647. Nothing
  648. --***************************************************************************/
  649. VOID
  650. UlIncSiteNonCriticalCounterUlong(
  651. PUL_SITE_COUNTER_ENTRY pEntry,
  652. HTTP_SITE_COUNTER_ID CounterId
  653. )
  654. {
  655. PCHAR pCounter;
  656. PLONG plValue;
  657. pCounter = (PCHAR) &(pEntry->Counters);
  658. pCounter += aIISULSiteDescription[CounterId].Offset;
  659. plValue = (PLONG) pCounter;
  660. ++(*plValue);
  661. }
  662. /***************************************************************************++
  663. Routine Description:
  664. Increment a NonCritical Site performance counter.
  665. Arguments:
  666. pEntry - pointer to Site Counter entry
  667. CounterId - ID of Counter to increment
  668. Returns:
  669. Nothing
  670. --***************************************************************************/
  671. VOID
  672. UlIncSiteNonCriticalCounterUlonglong(
  673. PUL_SITE_COUNTER_ENTRY pEntry,
  674. HTTP_SITE_COUNTER_ID CounterId
  675. )
  676. {
  677. PCHAR pCounter;
  678. PLONGLONG pllValue;
  679. pCounter = (PCHAR) &(pEntry->Counters);
  680. pCounter += aIISULSiteDescription[CounterId].Offset;
  681. pllValue = (PLONGLONG) pCounter;
  682. ++(*pllValue);
  683. }
  684. /***************************************************************************++
  685. Routine Description:
  686. Increment a Site performance counter.
  687. Arguments:
  688. pEntry - pointer to Site Counter entry
  689. Ctr - ID of Counter to increment
  690. Returns:
  691. Value of counter after incrementing
  692. --***************************************************************************/
  693. LONGLONG
  694. UlIncSiteCounter(
  695. PUL_SITE_COUNTER_ENTRY pEntry,
  696. HTTP_SITE_COUNTER_ID Ctr
  697. )
  698. {
  699. PCHAR pCtr;
  700. LONGLONG llValue;
  701. ASSERT( g_InitCountersCalled );
  702. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  703. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  704. UlTraceVerbose( PERF_COUNTERS,
  705. ("http!UlIncSiteCounter Ctr=%d SiteId=%d\n",
  706. Ctr,
  707. pEntry->Counters.SiteId
  708. ));
  709. //
  710. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  711. //
  712. pCtr = (PCHAR) &(pEntry->Counters);
  713. pCtr += aIISULSiteDescription[Ctr].Offset;
  714. // figure out data size of Ctr and do
  715. // apropriate thread-safe increment
  716. if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size)
  717. {
  718. // ULONG
  719. llValue = (LONGLONG) InterlockedIncrement((PLONG) pCtr);
  720. }
  721. else
  722. {
  723. // ULONGLONG
  724. llValue = UlInterlockedIncrement64((PLONGLONG) pCtr);
  725. }
  726. return llValue;
  727. }
  728. /***************************************************************************++
  729. Routine Description:
  730. Decrement a Site performance counter.
  731. Arguments:
  732. pEntry - pointer to Site Counter entry
  733. Ctr - ID of Counter to decrement
  734. --***************************************************************************/
  735. VOID
  736. UlDecSiteCounter(
  737. PUL_SITE_COUNTER_ENTRY pEntry,
  738. HTTP_SITE_COUNTER_ID Ctr
  739. )
  740. {
  741. PCHAR pCtr;
  742. ASSERT( g_InitCountersCalled );
  743. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  744. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  745. UlTraceVerbose( PERF_COUNTERS,
  746. ("http!UlDecSiteCounter Ctr=%d SiteId=%d\n",
  747. Ctr,
  748. pEntry->Counters.SiteId
  749. ));
  750. //
  751. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  752. //
  753. pCtr = (PCHAR) &(pEntry->Counters);
  754. pCtr += aIISULSiteDescription[Ctr].Offset;
  755. // figure out data size of Ctr and do
  756. // apropriate thread-safe increment
  757. if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size)
  758. {
  759. // ULONG
  760. InterlockedDecrement((PLONG) pCtr);
  761. }
  762. else
  763. {
  764. // ULONGLONG
  765. UlInterlockedDecrement64((PLONGLONG) pCtr);
  766. }
  767. }
  768. /***************************************************************************++
  769. Routine Description:
  770. Add a ULONG value to a 32-bit site performance counter.
  771. Arguments:
  772. pEntry - pointer to Site Counter entry
  773. Ctr - ID of counter to which the Value should be added
  774. Value - The amount to add to the counter
  775. --***************************************************************************/
  776. VOID
  777. UlAddSiteCounter(
  778. PUL_SITE_COUNTER_ENTRY pEntry,
  779. HTTP_SITE_COUNTER_ID Ctr,
  780. ULONG Value
  781. )
  782. {
  783. PCHAR pCtr;
  784. ASSERT( g_InitCountersCalled );
  785. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  786. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  787. UlTraceVerbose( PERF_COUNTERS,
  788. ("http!UlAddSiteCounter Ctr=%d SiteId=%d Value=%d\n",
  789. Ctr,
  790. pEntry->Counters.SiteId,
  791. Value
  792. ));
  793. //
  794. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  795. //
  796. pCtr = (PCHAR) &(pEntry->Counters);
  797. pCtr += aIISULSiteDescription[Ctr].Offset;
  798. // figure out data size of Ctr and do
  799. // apropriate thread-safe increment
  800. ASSERT(sizeof(ULONG) == aIISULSiteDescription[Ctr].Size);
  801. InterlockedExchangeAdd((PLONG) pCtr, Value);
  802. }
  803. /***************************************************************************++
  804. Routine Description:
  805. Add a ULONGLONG value to a 64-bit site performance counter.
  806. Arguments:
  807. pEntry - pointer to Site Counter entry
  808. Ctr - ID of counter to which the Value should be added
  809. Value - The amount to add to the counter
  810. --***************************************************************************/
  811. VOID
  812. UlAddSiteCounter64(
  813. PUL_SITE_COUNTER_ENTRY pEntry,
  814. HTTP_SITE_COUNTER_ID Ctr,
  815. ULONGLONG llValue
  816. )
  817. {
  818. PCHAR pCtr;
  819. ASSERT( g_InitCountersCalled );
  820. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  821. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  822. UlTraceVerbose( PERF_COUNTERS,
  823. ("http!UlAddSiteCounter64 Ctr=%d SiteId=%d Value=%I64d\n",
  824. Ctr,
  825. pEntry->Counters.SiteId,
  826. llValue
  827. ));
  828. //
  829. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  830. //
  831. pCtr = (PCHAR) &(pEntry->Counters);
  832. pCtr += aIISULSiteDescription[Ctr].Offset;
  833. ASSERT(sizeof(ULONGLONG) == aIISULSiteDescription[Ctr].Size);
  834. UlInterlockedAdd64((PLONGLONG) pCtr, llValue);
  835. }
  836. /***************************************************************************++
  837. Routine Description:
  838. Reset a Site performance counter.
  839. Arguments:
  840. pEntry - pointer to Site Counter entry
  841. Ctr - ID of counter to be reset
  842. --***************************************************************************/
  843. VOID
  844. UlResetSiteCounter(
  845. PUL_SITE_COUNTER_ENTRY pEntry,
  846. HTTP_SITE_COUNTER_ID Ctr
  847. )
  848. {
  849. PCHAR pCtr;
  850. ASSERT( g_InitCountersCalled );
  851. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  852. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  853. UlTraceVerbose( PERF_COUNTERS,
  854. ("http!UlResetSiteCounter Ctr=%d SiteId=%d\n",
  855. Ctr,
  856. pEntry->Counters.SiteId
  857. ));
  858. //
  859. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  860. //
  861. pCtr = (PCHAR) &(pEntry->Counters);
  862. pCtr += aIISULSiteDescription[Ctr].Offset;
  863. //
  864. // do apropriate "set" for data size of Ctr
  865. //
  866. if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size)
  867. {
  868. // ULONG
  869. InterlockedExchange((PLONG) pCtr, 0);
  870. }
  871. else
  872. {
  873. // ULONGLONG
  874. LONGLONG localCtr;
  875. LONGLONG originalCtr;
  876. LONGLONG localZero = 0;
  877. do {
  878. localCtr = *((volatile LONGLONG *) pCtr);
  879. originalCtr = InterlockedCompareExchange64( (PLONGLONG) pCtr,
  880. localZero,
  881. localCtr );
  882. } while (originalCtr != localCtr);
  883. }
  884. }
  885. /***************************************************************************++
  886. Routine Description:
  887. Determine if a new maximum value of a Site performance counter has been
  888. hit and set the counter to the new maximum if necessary. (ULONG version)
  889. Arguments:
  890. pEntry - pointer to Site Counter entry
  891. Ctr - ID of counter
  892. Value - possible new maximum (NOTE: Assumes that the counter Ctr is a
  893. 32-bit value)
  894. --***************************************************************************/
  895. VOID
  896. UlMaxSiteCounter(
  897. PUL_SITE_COUNTER_ENTRY pEntry,
  898. HTTP_SITE_COUNTER_ID Ctr,
  899. ULONG Value
  900. )
  901. {
  902. PCHAR pCtr;
  903. ASSERT( g_InitCountersCalled );
  904. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  905. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  906. UlTraceVerbose( PERF_COUNTERS,
  907. ("http!UlMaxSiteCounter Ctr=%d SiteId=%d Value=%d\n",
  908. Ctr,
  909. pEntry->Counters.SiteId,
  910. Value
  911. ));
  912. //
  913. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  914. //
  915. pCtr = (PCHAR) &(pEntry->Counters);
  916. pCtr += aIISULSiteDescription[Ctr].Offset;
  917. // Grab counter block mutex
  918. ExAcquireFastMutex(&pEntry->EntryMutex);
  919. if (Value > (ULONG) *pCtr)
  920. {
  921. InterlockedExchange((PLONG) pCtr, Value);
  922. }
  923. // Release counter block mutex
  924. ExReleaseFastMutex(&pEntry->EntryMutex);
  925. }
  926. /***************************************************************************++
  927. Routine Description:
  928. Determine if a new maximum value of a Site performance counter has been
  929. hit and set the counter to the new maximum if necessary. (LONGLONG version)
  930. Arguments:
  931. pEntry - pointer to Site Counter entry
  932. Ctr - ID of counter
  933. Value - possible new maximum (NOTE: Assumes that the counter Ctr is a
  934. 64-bit value)
  935. --***************************************************************************/
  936. VOID
  937. UlMaxSiteCounter64(
  938. PUL_SITE_COUNTER_ENTRY pEntry,
  939. HTTP_SITE_COUNTER_ID Ctr,
  940. LONGLONG llValue
  941. )
  942. {
  943. PCHAR pCtr;
  944. ASSERT( g_InitCountersCalled );
  945. ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
  946. ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
  947. UlTraceVerbose( PERF_COUNTERS,
  948. ("http!UlMaxSiteCounter64 Ctr=%d SiteId=%d Value=%I64d\n",
  949. Ctr,
  950. pEntry->Counters.SiteId,
  951. llValue
  952. ));
  953. //
  954. // figure out offset of Ctr in HTTP_SITE_COUNTERS
  955. //
  956. pCtr = (PCHAR) &(pEntry->Counters);
  957. pCtr += aIISULSiteDescription[Ctr].Offset;
  958. // Grab counter block mutex
  959. ExAcquireFastMutex(&pEntry->EntryMutex);
  960. if (llValue > (LONGLONG) *pCtr)
  961. {
  962. *((PLONGLONG) pCtr) = llValue;
  963. #if 0
  964. // REVIEW: There *must* be a better way to do this...
  965. // REVIEW: I want to do: (LONGLONG) *pCtr = llValue;
  966. // REVIEW: But casting something seems to make it a constant.
  967. // REVIEW: Also, there isn't an "InterlockedExchange64" for x86.
  968. // REVIEW: Any suggestions? --EricSten
  969. RtlCopyMemory(
  970. pCtr,
  971. &llValue,
  972. sizeof(LONGLONG)
  973. );
  974. #endif // 0
  975. }
  976. // Release counter block mutex
  977. ExReleaseFastMutex(&pEntry->EntryMutex);
  978. }
  979. #endif
  980. /***************************************************************************++
  981. Routine Description:
  982. Predicate to test if a site counter entry already exists for the given
  983. SiteId
  984. Arguments:
  985. SiteId - ID of site
  986. Return Value:
  987. TRUE if found
  988. FALSE if not found
  989. --***************************************************************************/
  990. BOOLEAN
  991. UlpIsInSiteCounterList(ULONG SiteId)
  992. {
  993. PLIST_ENTRY pEntry;
  994. PUL_SITE_COUNTER_ENTRY pCounterEntry;
  995. BOOLEAN IsFound = FALSE;
  996. if (IsListEmpty(&g_SiteCounterListHead))
  997. {
  998. ASSERT(0 == g_SiteCounterListCount);
  999. // Good! No counters left behind!
  1000. goto End;
  1001. }
  1002. //
  1003. // Walk list of Site Counter Entries
  1004. //
  1005. pEntry = g_SiteCounterListHead.Flink;
  1006. while (pEntry != &g_SiteCounterListHead)
  1007. {
  1008. pCounterEntry = CONTAINING_RECORD(
  1009. pEntry,
  1010. UL_SITE_COUNTER_ENTRY,
  1011. ListEntry
  1012. );
  1013. ASSERT(IS_VALID_SITE_COUNTER_ENTRY(pCounterEntry));
  1014. if (SiteId == pCounterEntry->Counters.SiteId)
  1015. {
  1016. IsFound = TRUE;
  1017. goto End;
  1018. }
  1019. pEntry = pEntry->Flink;
  1020. }
  1021. End:
  1022. return IsFound;
  1023. }