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.

312 lines
8.0 KiB

  1. /**************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * IceCAP user counters for GDI+ memory allocations
  8. *
  9. * Abstract:
  10. *
  11. * This is an IceCAP "user counter" DLL. It exports logging functions which
  12. * GDI+ will call during memory allocation (if PROFILE_MEMORY_USAGE is
  13. * true). It also exports query functions for hooking up to IceCAP.
  14. *
  15. * Instructions for use:
  16. *
  17. * + Build memcounter.dll
  18. * + Copy memcounter.dll and the icecap.ini file (which is in the same
  19. * directory as memcounter.cpp) to the test app directory.
  20. * + set PROFILE_MEMORY_USAGE=1
  21. * + Build GDIPLUS.DLL
  22. * + Instrument it (using "gppick.bat")
  23. * + Run the test
  24. * + Afterwards, view the .ICP file that has been generated.
  25. *
  26. * In the IceCAP viewer, you will need to add columns for
  27. * "User counter 1, elapsed inclusive", etc.
  28. *
  29. * Created:
  30. *
  31. * 06/10/2000 agodfrey
  32. * Created it from the sample code in IceCAP4\Samples\MemTrack.
  33. *
  34. **************************************************************************/
  35. #include <windows.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #define DONTUSEICECAPLIB
  39. #include "icecap.h"
  40. // GLOBALS
  41. //
  42. // This is where we will store our counter values. These could
  43. // just as easily be put in shared memory so you can have another
  44. // process updating them. They can not be put in the counter
  45. // functions as auto variables, since naked functions don't
  46. // allow for this.
  47. DWORD g_dwTlsSlot = 0xffffffff; // TLS Slot, allocated in DllMain
  48. DWORD g_dwTlsIndexSize; // 'Pre-computed' slot offset, so we can
  49. // avoid calling TlsGetValue in probes
  50. //
  51. // Data tracked for each thread.
  52. struct SAllocInfo
  53. {
  54. COUNTER cntAllocs; // Number of allocations made
  55. COUNTER cntBytes; // Bytes (total) allocated
  56. };
  57. const UINT g_uiMaxThreads = 64; // Max sim. threads tracked
  58. SAllocInfo g_aAllocInfo[g_uiMaxThreads]; // Data tracked
  59. BOOL g_afInUse[g_uiMaxThreads]; // Is a particular data slot used
  60. // FUNCTIONS
  61. //
  62. ///////////////////////////////////////////////////////////////
  63. // DllMain
  64. //
  65. // Standard DLL entry point, sets up storage for per-thread
  66. // counter information.
  67. //
  68. // History: 9-16-98 MHotchin Created
  69. //
  70. ///////////////////////////////////////////////////////////////
  71. BOOL
  72. APIENTRY
  73. DllMain(
  74. HANDLE ,
  75. DWORD dwReason,
  76. LPVOID )
  77. {
  78. switch (dwReason)
  79. {
  80. case DLL_PROCESS_ATTACH:
  81. g_dwTlsSlot = TlsAlloc();
  82. memset(g_afInUse, 0, sizeof(g_afInUse));
  83. if (g_dwTlsSlot == 0xffffffff)
  84. {
  85. return FALSE;
  86. }
  87. //
  88. // Tricky, tricky, tricky...
  89. // We can pre-compute where the TLS slot will be, once
  90. // we have the index. The offsets are OS dependent!
  91. //
  92. // This makes the probes much faster, becuase we don't need to
  93. // call TlsGetValue().
  94. if (GetVersion() & 0x80000000)
  95. {
  96. // *** WIN 9x ONLY ***
  97. g_dwTlsIndexSize = g_dwTlsSlot * sizeof(void *) + 0x88;
  98. }
  99. else
  100. {
  101. //
  102. // *** NT ONLY ***
  103. g_dwTlsIndexSize = g_dwTlsSlot * sizeof(void *) + 0xe10;
  104. }
  105. //
  106. // FALL THROUGH
  107. case DLL_THREAD_ATTACH:
  108. {
  109. SAllocInfo *pInfo = NULL;
  110. //
  111. // Locate a data slot for this thread and remeber it's pointer
  112. // in the TLS slot.
  113. for (UINT i = 0; i < g_uiMaxThreads; i++)
  114. {
  115. if (!g_afInUse[i])
  116. {
  117. g_afInUse[i] = TRUE;
  118. pInfo = &(g_aAllocInfo[i]);
  119. memset(pInfo, 0, sizeof(SAllocInfo));
  120. break;
  121. }
  122. }
  123. TlsSetValue(g_dwTlsSlot, pInfo);
  124. }
  125. break;
  126. case DLL_PROCESS_DETACH:
  127. if (g_dwTlsSlot != 0xffffffff)
  128. {
  129. TlsFree(g_dwTlsSlot);
  130. g_dwTlsSlot = 0xffffffff;
  131. }
  132. break;
  133. case DLL_THREAD_DETACH:
  134. {
  135. SAllocInfo *pInfo = (SAllocInfo *)TlsGetValue(g_dwTlsSlot);
  136. if (pInfo != NULL)
  137. {
  138. UINT iIndex = pInfo - g_aAllocInfo;
  139. g_afInUse[iIndex] = FALSE;
  140. }
  141. }
  142. break;
  143. }
  144. return TRUE;
  145. }
  146. ///////////////////////////////////////////////////////////////
  147. // GetCounterInfo
  148. //
  149. // This is where we define what is counter is, and how it
  150. // behaves.
  151. //
  152. // History: 9-16-98 MHotchin Created
  153. // 2-26-99 AlonB updated for new USERCOUNTER API
  154. //
  155. ///////////////////////////////////////////////////////////////
  156. extern "C" BOOL _stdcall GetCounterInfo(DWORD iCounter, USERCOUNTERINFO *pInfo)
  157. {
  158. // we only have two counters to set up
  159. if (iCounter > 1)
  160. return FALSE;
  161. pInfo->dwSize = sizeof(USERCOUNTERINFO);
  162. pInfo->bSynchronized = TRUE;
  163. if (0 == iCounter)
  164. {
  165. // SETUP COUNTER 0
  166. strcpy(pInfo->szCounterFuncName, "GetCounterOneValue");
  167. strcpy(pInfo->szName, "Mem Allocs");
  168. pInfo->ct = MonotonicallyIncreasing;
  169. }
  170. else // 1 == iCounter
  171. {
  172. // SETUP COUNTER 1
  173. strcpy(pInfo->szCounterFuncName, "GetCounterTwoValue");
  174. strcpy(pInfo->szName, "Byte Allocs");
  175. pInfo->ct = RandomIncreasing;
  176. }
  177. // We didn't do anything here that could fail, at least nothing
  178. // that wouldn't be catistrophic. So just return TRUE.
  179. //
  180. return TRUE;
  181. }
  182. extern "C"
  183. VOID _stdcall
  184. MC_LogAllocation(UINT size)
  185. {
  186. //
  187. // Get data pointer from TLS slot and update counts for this thread.
  188. if (g_dwTlsSlot != 0xffffffff)
  189. {
  190. SAllocInfo *pAllocInfo = (SAllocInfo *)TlsGetValue(g_dwTlsSlot);
  191. if (pAllocInfo != NULL)
  192. {
  193. pAllocInfo->cntAllocs++;
  194. pAllocInfo->cntBytes += size;
  195. }
  196. }
  197. }
  198. extern "C"
  199. BOOL
  200. _stdcall
  201. InitCounters(void)
  202. {
  203. return TRUE;
  204. }
  205. #define PcTeb 0x18
  206. //-----------------------------------------------------------------------------
  207. // GetCounterOneValue
  208. //
  209. // Return current value for first counter - number of CRT allocs
  210. //
  211. // History: 9-16-98 MHotchin Created
  212. //
  213. //-----------------------------------------------------------------------------
  214. //
  215. extern "C"
  216. COUNTER
  217. _declspec(naked) _stdcall
  218. GetCounterOneValue(void)
  219. {
  220. _asm
  221. {
  222. mov eax, g_dwTlsIndexSize // Load TLS slot offset
  223. add eax, fs:[PcTeb] // Load pointer to TLS slot
  224. mov eax, [eax] // Load Data pointer from TLS slot
  225. je NoSample // If NULL, skip
  226. mov edx, dword ptr [eax+0x04] // High word of # allocs
  227. mov eax, dword ptr [eax] // Low word of # allocs
  228. ret
  229. NoSample:
  230. mov eax, 0
  231. mov edx, 0
  232. ret
  233. }
  234. }
  235. //-----------------------------------------------------------------------------
  236. // GetCounterTwoValue
  237. //
  238. // Return current value of second counter - number of bytes allocated.
  239. //
  240. // History: 9-16-98 MHotchin Created
  241. //
  242. //-----------------------------------------------------------------------------
  243. extern "C"
  244. COUNTER
  245. _declspec(naked) _stdcall
  246. GetCounterTwoValue(void)
  247. {
  248. _asm
  249. {
  250. mov eax, g_dwTlsIndexSize // Load TLS slot offset
  251. add eax, fs:[PcTeb] // Load pointer to TLS slot
  252. mov eax, [eax] // Load Data pointer from TLS slot
  253. je NoSample // If NULL, skip
  254. mov edx, dword ptr [eax+0x0c] // High wors of # bytes
  255. mov eax, dword ptr [eax+0x08] // Low word of # bytes
  256. ret
  257. NoSample:
  258. mov eax, 0
  259. mov edx, 0
  260. ret
  261. }
  262. }