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.

205 lines
6.6 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. appmema.cpp
  5. Abstract:
  6. This file contains the memory allocation function "wrappers"
  7. to allow monitoring of the memory usage by a performance monitoring
  8. application (e.g. PERFMON).
  9. --*/
  10. #ifdef DO_TIMING_BUILD
  11. #include <windows.h>
  12. #include <assert.h>
  13. #include "appmema.h"
  14. HANDLE ThisDLLHandle = NULL;
  15. HANDLE hAppMemSharedMemory = NULL; // Handle of counter Shared Memory
  16. PAPPMEM_DATA_HEADER pDataHeader = NULL; // pointer to header of shared mem
  17. PAPPMEM_INSTANCE pAppData = NULL; // pointer to the app data for this app
  18. static
  19. BOOL
  20. DllProcessAttach (
  21. IN HANDLE DllHandle
  22. )
  23. /*++
  24. Description:
  25. Initializes the interface to the performance counters DLL by
  26. opening the Shared Memory file used to communicate statistics
  27. from the application to the counter DLL. If the Shared memory
  28. file does not exist, it is created, formatted and initialized.
  29. If the file has already been created and formatted, then the
  30. next available APPMEM_INSTANCE entry is moved from the free list
  31. to the InUse list and the corresponding pointer is saved for
  32. subsequent use by this application
  33. --*/
  34. {
  35. LONG status;
  36. TCHAR szMappedObject[] = SHARED_MEMORY_OBJECT_NAME;
  37. DWORD dwBytes;
  38. // save this DLL handle
  39. ThisDLLHandle = DllHandle;
  40. // disable thread attach & detach calls to save the overhead
  41. // since we don't care about them.
  42. DisableThreadLibraryCalls (DllHandle);
  43. // open & initialize shared memory file
  44. SetLastError (ERROR_SUCCESS); // just to clear it out
  45. // open/create shared memory used by the application to pass performance values
  46. status = GetSharedMemoryDataHeader (
  47. &hAppMemSharedMemory, NULL, &pDataHeader,
  48. FALSE); // read/write access is required
  49. // here the memory block should be initialized and ready for use
  50. if (status == ERROR_SUCCESS) {
  51. if (pDataHeader->dwFirstFreeOffset != 0) {
  52. // then there are blocks left so get the next free
  53. pAppData = FIRST_FREE(pDataHeader);
  54. // update free list to make next item the first in list
  55. pDataHeader->dwFirstFreeOffset = pAppData->dwOffsetOfNext;
  56. // insert the new item into the head of the in use list
  57. pAppData->dwOffsetOfNext = pDataHeader->dwFirstInUseOffset;
  58. pDataHeader->dwFirstInUseOffset = (DWORD)((LPBYTE)pAppData -
  59. (LPBYTE)pDataHeader);
  60. // now initialize this instance's data
  61. pAppData->dwProcessId = GetCurrentProcessId(); // id of process using this instance
  62. dwBytes = sizeof (APP_DATA_SAMPLE) * TD_TOTAL;
  63. dwBytes += sizeof (DWORD) * DD_TOTAL;
  64. memset (&pAppData->TimeData[0], 0, dwBytes);
  65. pDataHeader->dwInstanceCount++; // increment count
  66. } else {
  67. // no more free slots left
  68. assert (pDataHeader->dwFirstFreeOffset != 0);
  69. }
  70. } else {
  71. // unable to open shared memory file
  72. // even though this is an error we should return true so as to
  73. // not abort the application. No performance data will be
  74. // collected though.
  75. }
  76. return TRUE;
  77. }
  78. static
  79. BOOL
  80. DllProcessDetach (
  81. IN HANDLE DllHandle
  82. )
  83. {
  84. PAPPMEM_INSTANCE pPrevItem;
  85. // remove instance for this app
  86. if ((pAppData != NULL) && (pDataHeader != NULL)) {
  87. // zero the fields out first
  88. memset (pAppData, 0, sizeof (APPMEM_INSTANCE));
  89. // move from in use (busy) list back to the free list
  90. if ((pDataHeader->dwFirstFreeOffset != 0) && (pDataHeader->dwFirstInUseOffset != 0)) {
  91. // find previous item in busy list
  92. if (FIRST_INUSE(pDataHeader) != pAppData) {
  93. // not the first so walk down the list
  94. pPrevItem = FIRST_INUSE(pDataHeader);
  95. while (APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext) != pAppData) {
  96. pPrevItem = APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext);
  97. if (pPrevItem->dwOffsetOfNext == 0) break; // end of list
  98. }
  99. if (APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext) == pAppData) {
  100. APPMEM_INST(pDataHeader, pPrevItem->dwOffsetOfNext)->dwOffsetOfNext =
  101. pAppData->dwOffsetOfNext;
  102. } else {
  103. // it was never in the busy list (?!?)
  104. }
  105. } else {
  106. // this is the first in the list so update it
  107. pDataHeader->dwFirstInUseOffset = pAppData->dwOffsetOfNext;
  108. }
  109. // here, pAppData has been removed from the InUse list and now
  110. // it must be inserted back at the beginning of the free list
  111. pAppData->dwOffsetOfNext = pDataHeader->dwFirstFreeOffset;
  112. pDataHeader->dwFirstFreeOffset = (DWORD)((LPBYTE)pAppData - (LPBYTE)pDataHeader);
  113. }
  114. }
  115. // decrement instance counter
  116. pDataHeader->dwInstanceCount--; // decrement count
  117. // close shared memory file handle
  118. if (hAppMemSharedMemory != NULL) CloseHandle (hAppMemSharedMemory);
  119. // clear pointers
  120. hAppMemSharedMemory = NULL;
  121. pDataHeader = NULL;
  122. pAppData = NULL;
  123. return TRUE;
  124. }
  125. BOOL
  126. __stdcall
  127. AppPerfOpen(HINSTANCE hInstance)
  128. {
  129. return DllProcessAttach (hInstance);
  130. }
  131. BOOL
  132. __stdcall
  133. AppPerfClose(HINSTANCE hInstance)
  134. {
  135. return DllProcessDetach (hInstance);
  136. }
  137. void
  138. UpdateAppPerfTimeData (
  139. DWORD dwItemId,
  140. DWORD dwStage
  141. )
  142. {
  143. LONGLONG llTime;
  144. assert (dwItemId < TD_TOTAL);
  145. QueryPerformanceCounter ((LARGE_INTEGER *)&llTime);
  146. // GetSystemTimeAsFileTime ((LPFILETIME)&llTime);
  147. if (dwStage == TD_BEGIN) {
  148. assert (pAppData->TimeData[dwItemId].dw1 == 0); // this shouldn't be called while timing
  149. pAppData->TimeData[dwItemId].ll1 = llTime; // save start time
  150. pAppData->TimeData[dwItemId].dw1++; // indicate were counting
  151. } else {
  152. assert (pAppData->TimeData[dwItemId].dw1 == 1); // this should only be called while timing
  153. pAppData->TimeData[dwItemId].ll0 += llTime; // add in current time
  154. // then remove the start time
  155. pAppData->TimeData[dwItemId].ll0 -= pAppData->TimeData[dwItemId].ll1;
  156. // increment completed operation count
  157. pAppData->TimeData[dwItemId].dw0++;
  158. // decrement busy count
  159. pAppData->TimeData[dwItemId].dw1--;
  160. }
  161. return;
  162. }
  163. void
  164. UpdateAppPerfDwordData (
  165. DWORD dwItemId,
  166. DWORD dwValue
  167. )
  168. {
  169. assert (dwItemId < DD_TOTAL);
  170. pAppData->DwordData[dwItemId] = dwValue;
  171. return;
  172. }
  173. #endif