Leaked source code of windows server 2003
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.

1286 lines
31 KiB

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