Changeset 36597 in vbox
- Timestamp:
- Apr 6, 2011 7:46:15 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mangling.h
r36581 r36597 747 747 # define RTMemTmpAllocZTag RT_MANGLER(RTMemTmpAllocZTag) 748 748 # define RTMemTmpFree RT_MANGLER(RTMemTmpFree) 749 # define RTMemTrackerDumpAllToFile RT_MANGLER(RTMemTrackerDumpAllToFile) 750 # define RTMemTrackerDumpAllToLog RT_MANGLER(RTMemTrackerDumpAllToLog) 751 # define RTMemTrackerDumpAllToLogRel RT_MANGLER(RTMemTrackerDumpAllToLogRel) 752 # define RTMemTrackerDumpAllToStdErr RT_MANGLER(RTMemTrackerDumpAllToStdErr) 753 # define RTMemTrackerDumpAllToStdOut RT_MANGLER(RTMemTrackerDumpAllToStdOut) 754 # define RTMemTrackerDumpStatsToFile RT_MANGLER(RTMemTrackerDumpStatsToFile) 755 # define RTMemTrackerDumpStatsToLog RT_MANGLER(RTMemTrackerDumpStatsToLog) 756 # define RTMemTrackerDumpStatsToLogRel RT_MANGLER(RTMemTrackerDumpStatsToLogRel) 757 # define RTMemTrackerDumpStatsToStdErr RT_MANGLER(RTMemTrackerDumpStatsToStdErr) 758 # define RTMemTrackerDumpStatsToStdOut RT_MANGLER(RTMemTrackerDumpStatsToStdOut) 759 # define RTMemTrackerHdrAlloc RT_MANGLER(RTMemTrackerHdrAlloc) 760 # define RTMemTrackerHdrFree RT_MANGLER(RTMemTrackerHdrFree) 761 # define RTMemTrackerHdrReallocDone RT_MANGLER(RTMemTrackerHdrReallocDone) 762 # define RTMemTrackerHdrReallocPrep RT_MANGLER(RTMemTrackerHdrReallocPrep) 749 763 # define RTMemWipeThoroughly RT_MANGLER(RTMemWipeThoroughly) 750 764 # define RTMpCpuId RT_MANGLER(RTMpCpuId) … … 1386 1400 # define RTThreadGetType RT_MANGLER(RTThreadGetType) 1387 1401 # define RTThreadIsInInterrupt RT_MANGLER(RTThreadIsInInterrupt) /* r0drv */ 1402 # define RTThreadIsInitialized RT_MANGLER(RTThreadIsInitialized) 1388 1403 # define RTThreadIsMain RT_MANGLER(RTThreadIsMain) 1404 # define RTThreadIsSelfAlive RT_MANGLER(RTThreadIsSelfAlive) 1405 # define RTThreadIsSelfKnown RT_MANGLER(RTThreadIsSelfKnown) 1389 1406 # define RTThreadNativeSelf RT_MANGLER(RTThreadNativeSelf) 1390 1407 # define RTThreadPoke RT_MANGLER(RTThreadPoke) /* not-win not-os2 */ -
trunk/include/iprt/memtracker.h
r32431 r36597 46 46 RTMEMTRACKERMETHOD_ALLOC, 47 47 RTMEMTRACKERMETHOD_ALLOCZ, 48 RTMEMTRACKERMETHOD_REALLOC, 48 RTMEMTRACKERMETHOD_REALLOC_PREP, /**< Internal, don't use. */ 49 RTMEMTRACKERMETHOD_REALLOC_DONE, /**< Internal, don't use. */ 50 RTMEMTRACKERMETHOD_REALLOC_FAILED, /**< Internal, don't use. */ 49 51 RTMEMTRACKERMETHOD_FREE, 50 52 … … 60 62 typedef struct RTMEMTRACKERTAG *PRTMEMTRACKERTAG; 61 63 64 /** Pointer to a user structure. */ 65 typedef struct RTMEMTRACKERUSER *PRTMEMTRACKERUSER; 66 62 67 /** 63 68 * Memory Tracking Header for use with RTMemTrackerHdrAlloc, … … 69 74 /** Magic value / eye catcher (RTMEMTRACKERHDR_MAGIC). */ 70 75 size_t uMagic; 71 /** The allocation size . */72 size_t cb Size;76 /** The allocation size, user data only. */ 77 size_t cbUser; 73 78 /** The list entry. */ 74 79 RTLISTNODE ListEntry; 80 /** Pointer to the user structure where this header is linked. */ 81 PRTMEMTRACKERUSER pUser; 82 /** Pointer to the per-tag structure. */ 83 PRTMEMTRACKERTAG pTag; 75 84 /** The tag string. */ 76 85 const char *pszTag; 77 /** Pointer to the per-tag structure. */ 78 PRTMEMTRACKERTAG pTag; 79 /** Alignmnet padding. */ 80 void *pvAlignment[2]; 86 /** Pointer to the user data we're tracking. */ 87 void *pvUser; 81 88 } RTMEMTRACKERHDR; 89 /** Pointer to a memory tracker header. */ 90 typedef RTMEMTRACKERHDR *PRTMEMTRACKERHDR; 91 /** Pointer to a const memory tracker header. */ 92 typedef RTMEMTRACKERHDR *PPRTMEMTRACKERHDR; 82 93 83 94 /** Magic value for RTMEMTRACKERHDR::uMagic (Kelly Link). */ 84 95 #if ARCH_BITS == 64 85 # define RTMEMTRACKERHDR_MAGIC UINT64_C(0x1907691919690719)96 # define RTMEMTRACKERHDR_MAGIC UINT64_C(0x1907691919690719) 86 97 #else 87 # define RTMEMTRACKERHDR_MAGIC UINT32_C(0x19690719)98 # define RTMEMTRACKERHDR_MAGIC UINT32_C(0x19690719) 88 99 #endif 100 /** Magic number used when reallocated. */ 101 #if ARCH_BITS == 64 102 # define RTMEMTRACKERHDR_MAGIC_REALLOC UINT64_C(0x0000691919690000) 103 #else 104 # define RTMEMTRACKERHDR_MAGIC_REALLOC UINT32_C(0x19690000) 105 #endif 106 /** Magic number used when freed. */ 107 #define RTMEMTRACKERHDR_MAGIC_FREE (~RTMEMTRACKERHDR_MAGIC) 108 89 109 90 110 /** … … 94 114 * @param pv The header + user data block. This must be at 95 115 * least @a cb + sizeof(RTMEMTRACKERHDR). 96 * @param cb 116 * @param cbUser The user data size (bytes). 97 117 * @param pszTag The tag string. 98 118 * @param enmMethod The method that the user called. 99 119 */ 100 RTDECL(void *) RTMemTrackerHdrAlloc(void *pv, size_t cb , const char *pszTag, RTMEMTRACKERMETHOD enmMethod);120 RTDECL(void *) RTMemTrackerHdrAlloc(void *pv, size_t cbUser, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); 101 121 102 122 /** … … 104 124 * 105 125 * @returns Pointer to the user data part. 106 * @param pvOld 107 * @param cbOld The size of the old user data, 0 if not known.108 * @param pszTag The tag string.109 * @param enmMethod The method that the user called.110 */ 111 RTDECL(void *) RTMemTrackerHdrReallocPrep(void *pvOld , size_t cbOld, const char *pszTag, RTMEMTRACKERMETHOD enmMethod);126 * @param pvOldUser Pointer to the old user data. 127 * @param cbOldUser The size of the old user data, 0 if not 128 * known. 129 * @param pszTag The tag string. 130 */ 131 RTDECL(void *) RTMemTrackerHdrReallocPrep(void *pvOldUser, size_t cbOldUser, const char *pszTag); 112 132 113 133 /** … … 119 139 * this is NULL, we assume the realloc() call 120 140 * failed. 121 * @param cbNew 122 * @param pvOld 141 * @param cbNewUser The user data size (bytes). 142 * @param pvOldUser Pointer to the old user data. This is only 123 143 * valid on failure of course and used to bail out 124 144 * in that case. Should not be NULL. 125 145 * @param pszTag The tag string. 146 */ 147 RTDECL(void *) RTMemTrackerHdrReallocDone(void *pvNew, size_t cbNewUser, void *pvOldUser, const char *pszTag); 148 149 150 /** 151 * Do the accounting on free. 152 * 153 * @returns @a pv. 154 * @param pvUser Pointer to the user data. 155 * @param cbUser The size of the user data, 0 if not known. 156 * @param pszTag The tag string. 126 157 * @param enmMethod The method that the user called. 127 158 */ 128 RTDECL(void *) RTMemTrackerHdrReallocDone(void *pvNew, size_t cbNew, void *pvOld, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); 129 130 131 /** 132 * Do the accounting on free. 133 * 134 * @returns @a pv. 135 * @param pv Pointer to the user data. 136 * @param cb The size of the user data, 0 if not known. 137 * @param pszTag The tag string. 138 * @param enmMethod The method that the user called. 139 */ 140 RTDECL(void *) RTMemTrackerHdrFree(void *pv, size_t cb, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); 159 RTDECL(void *) RTMemTrackerHdrFree(void *pvUser, size_t cbUser, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); 141 160 142 161 … … 149 168 * Dumps all the allocations and tag statistics to the release log. 150 169 */ 151 RTDECL(void) RTMemTrackerDumpAllTo RelLog(void);170 RTDECL(void) RTMemTrackerDumpAllToLogRel(void); 152 171 153 172 /** … … 169 188 /** 170 189 * Dumps all the tag statistics to the log. 171 */ 172 RTDECL(void) RTMemTrackerDumpStatsToLog(void); 190 * 191 * @param fVerbose Whether to print all the stats or just the ones 192 * relevant to hunting leaks. 193 */ 194 RTDECL(void) RTMemTrackerDumpStatsToLog(bool fVerbose); 173 195 174 196 /** 175 197 * Dumps all the tag statistics to the release log. 176 */ 177 RTDECL(void) RTMemTrackerDumpStatsToRelLog(void); 198 * 199 * @param fVerbose Whether to print all the stats or just the ones 200 * relevant to hunting leaks. 201 */ 202 RTDECL(void) RTMemTrackerDumpStatsToLogRel(bool fVerbose); 178 203 179 204 /** 180 205 * Dumps all the tag statistics to standard out. 181 */ 182 RTDECL(void) RTMemTrackerDumpStatsToStdOut(void); 206 * 207 * @param fVerbose Whether to print all the stats or just the ones 208 * relevant to hunting leaks. 209 */ 210 RTDECL(void) RTMemTrackerDumpStatsToStdOut(bool fVerbose); 183 211 184 212 /** 185 213 * Dumps all the tag statistics to standard err. 186 */ 187 RTDECL(void) RTMemTrackerDumpStatsToStdErr(void); 214 * 215 * @param fVerbose Whether to print all the stats or just the ones 216 * relevant to hunting leaks. 217 */ 218 RTDECL(void) RTMemTrackerDumpStatsToStdErr(bool fVerbose); 188 219 189 220 /** 190 221 * Dumps all the tag statistics to the specified filename. 191 */ 192 RTDECL(void) RTMemTrackerDumpStatsToFile(const char *pszFilename); 222 * 223 * @param fVerbose Whether to print all the stats or just the ones 224 * relevant to hunting leaks. 225 * @param pszFilename The name of the file to dump to. 226 */ 227 RTDECL(void) RTMemTrackerDumpStatsToFile(bool fVerbose, const char *pszFilename); 193 228 194 229 -
trunk/src/VBox/Runtime/Makefile.kmk
r36578 r36597 251 251 common/alloc/heapoffset.cpp \ 252 252 common/alloc/memcache.cpp \ 253 common/alloc/memtracker.cpp \ 253 254 common/checksum/adler32.cpp \ 254 255 common/checksum/crc32.cpp \ … … 2258 2259 do \ 2259 2260 if $(SED) -ne '/\# *define '"$${fn}"' /q 1' $(PATH_ROOT)/include/iprt/mangling.h; then \ 2260 echo "mangling.h: Missing '"$${fn}"'"; \2261 echo "mangling.h: Missing # define "$${fn}" RT_MANGLER("$${fn}")"; \ 2261 2262 rcExit=1;\ 2262 2263 fi \ … … 2289 2290 do \ 2290 2291 if $(SED) -ne '/\# *define '"$${fn}"' /q 1' $(PATH_ROOT)/include/iprt/mangling.h; then \ 2291 echo "mangling.h: Missing '"$${fn}"'"; \2292 echo "mangling.h: Missing # define "$${fn}" RT_MANGLER("$${fn}")""; \ 2292 2293 rcExit=1;\ 2293 2294 fi \ -
trunk/src/VBox/Runtime/common/alloc/memtracker.cpp
r32431 r36597 5 5 6 6 /* 7 * Copyright (C) 2010 Oracle Corporation7 * Copyright (C) 2010-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include <iprt/mem cache.h>31 #include <iprt/memtracker.h> 32 32 #include "internal/iprt.h" 33 33 34 #include <iprt/asm.h> 34 35 #include <iprt/assert.h> 36 #include <iprt/avl.h> 37 #include <iprt/critsect.h> 38 #ifdef IN_RING3 39 # include <iprt/file.h> 40 #endif 41 #include <iprt/err.h> 42 #include <iprt/list.h> 43 #include <iprt/log.h> 35 44 #include <iprt/mem.h> 36 #include <iprt/param.h> 37 45 #include <iprt/semaphore.h> 46 #include <iprt/string.h> 47 #include <iprt/thread.h> 48 49 #include "internal/file.h" 38 50 #include "internal/magics.h" 39 51 #include "internal/strhash.h" 52 53 54 /******************************************************************************* 55 * Structures and Typedefs * 56 *******************************************************************************/ 57 /** Pointer to a memory tracker instance */ 58 typedef struct RTMEMTRACKERINT *PRTMEMTRACKERINT; 59 60 /** 61 * Memory tracker statistics. 62 */ 63 typedef struct RTMEMTRACKERSTATS 64 { 65 /** Array of method calls. */ 66 uint64_t volatile acMethodCalls[RTMEMTRACKERMETHOD_END]; 67 /** The number of times this user freed or reallocated a memory block 68 * orignally allocated by someone else. */ 69 uint64_t volatile cUserChanges; 70 /** The total number of bytes allocated ever. */ 71 uint64_t volatile cbTotalAllocated; 72 /** The total number of blocks allocated ever. */ 73 uint64_t volatile cTotalAllocatedBlocks; 74 /** The number of bytes currently allocated. */ 75 size_t volatile cbAllocated; 76 /** The number of blocks currently allocated. */ 77 size_t volatile cAllocatedBlocks; 78 } RTMEMTRACKERSTATS; 79 /** Pointer to memory tracker statistics. */ 80 typedef RTMEMTRACKERSTATS *PRTMEMTRACKERSTATS; 81 82 83 /** 84 * Memory tracker user data. 85 */ 86 typedef struct RTMEMTRACKERUSER 87 { 88 /** Entry in the user list (RTMEMTRACKERINT::UserList). */ 89 RTLISTNODE ListEntry; 90 /** Pointer to the tracker. */ 91 PRTMEMTRACKERINT pTracker; 92 /** Critical section protecting the memory list. */ 93 RTCRITSECT CritSect; 94 /** The list of memory allocated by this user. */ 95 RTLISTNODE MemoryList; 96 /** Positive numbers indicates recursion. 97 * Negative numbers are used for the global user since that is shared by 98 * more than one thread. */ 99 int32_t volatile cInTracker; 100 /** The user identifier. */ 101 uint32_t idUser; 102 /** The statistics for this user. */ 103 RTMEMTRACKERSTATS Stats; 104 /** The user (thread) name. */ 105 char szName[32]; 106 } RTMEMTRACKERUSER; 107 /** Pointer to memory tracker per user data. */ 108 typedef RTMEMTRACKERUSER *PRTMEMTRACKERUSER; 109 110 111 /** 112 * Memory tracker per tag statistics. 113 */ 114 typedef struct RTMEMTRACKERTAG 115 { 116 /** AVL node core for lookup by hash. */ 117 AVLU32NODECORE Core; 118 /** Tag list entry for flat traversal while dumping. */ 119 RTLISTNODE ListEntry; 120 /** Pointer to the next tag with the same hash (collisions). */ 121 PRTMEMTRACKERTAG pNext; 122 /** The tag statistics. */ 123 RTMEMTRACKERSTATS Stats; 124 /** The tag name length. */ 125 size_t cchTag; 126 /** The tag string. */ 127 char szTag[1]; 128 } RTMEMTRACKERTAG; 129 130 131 /** 132 * The memory tracker instance. 133 */ 134 typedef struct RTMEMTRACKERINT 135 { 136 /** Cross roads semaphore separating dumping and normal operation. 137 * - NS - normal tracking. 138 * - EW - dumping tracking data. */ 139 RTSEMXROADS hXRoads; 140 141 /** Critical section protecting the user list and tag database. */ 142 RTCRITSECT CritSect; 143 /** List of RTMEMTRACKERUSER records. */ 144 RTLISTNODE UserList; 145 /** The next user identifier number. */ 146 uint32_t idUserNext; 147 /** The TLS index used for the per thread user records. */ 148 RTTLS iTls; 149 /** Cross roads semaphore used to protect the tag database. 150 * - NS - lookup. 151 * - EW + critsect - insertion. 152 * @todo Replaced this by a read-write semaphore. */ 153 RTSEMXROADS hXRoadsTagDb; 154 /** The root of the tag lookup database. */ 155 AVLU32TREE TagDbRoot; 156 /** List of RTMEMTRACKERTAG records. */ 157 RTLISTNODE TagList; 158 /** The global user record (fallback). */ 159 RTMEMTRACKERUSER FallbackUser; 160 /** The global statistics. */ 161 RTMEMTRACKERSTATS GlobalStats; 162 /** The number of busy (recursive) allocations. */ 163 uint64_t volatile cBusyAllocs; 164 /** The number of busy (recursive) frees. */ 165 uint64_t volatile cBusyFrees; 166 /** The number of tags. */ 167 uint32_t cTags; 168 /** The number of users. */ 169 uint32_t cUsers; 170 } RTMEMTRACKERINT; 171 AssertCompileMemberAlignment(RTMEMTRACKERINT, FallbackUser, 8); 172 173 174 /** 175 * Output callback structure. 176 */ 177 typedef struct RTMEMTRACKEROUTPUT 178 { 179 /** The printf like callback. */ 180 DECLCALLBACKMEMBER(void, pfnPrintf)(struct RTMEMTRACKEROUTPUT *pThis, const char *pszFormat, ...); 181 182 /** The data. */ 183 union 184 { 185 RTFILE hFile; 186 } uData; 187 } RTMEMTRACKEROUTPUT; 188 /** Pointer to a memory tracker output callback structure. */ 189 typedef RTMEMTRACKEROUTPUT *PRTMEMTRACKEROUTPUT; 190 191 192 /******************************************************************************* 193 * Global Variables * 194 *******************************************************************************/ 195 /** Pointer to the default memory tracker. */ 196 static PRTMEMTRACKERINT g_pDefaultTracker = NULL; 197 198 199 /** 200 * Creates a memory tracker. 201 * 202 * @returns IRPT status code. 203 * @param ppTracker Where to return the tracker instance. 204 */ 205 static int rtMemTrackerCreate(PRTMEMTRACKERINT *ppTracker) 206 { 207 PRTMEMTRACKERINT pTracker = (PRTMEMTRACKERINT)RTMemAllocZ(sizeof(*pTracker)); 208 if (!pTracker) 209 return VERR_NO_MEMORY; 210 211 /* 212 * Create locks and stuff. 213 */ 214 int rc = RTCritSectInitEx(&pTracker->CritSect, 215 RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_BOOTSTRAP_HACK, 216 NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL); 217 if (RT_SUCCESS(rc)) 218 { 219 rc = RTSemXRoadsCreate(&pTracker->hXRoads); 220 if (RT_SUCCESS(rc)) 221 { 222 rc = RTSemXRoadsCreate(&pTracker->hXRoadsTagDb); 223 if (RT_SUCCESS(rc)) 224 { 225 rc = RTTlsAllocEx(&pTracker->iTls, NULL); 226 if (RT_SUCCESS(rc)) 227 { 228 rc = RTCritSectInitEx(&pTracker->FallbackUser.CritSect, 229 RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_BOOTSTRAP_HACK, 230 NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL); 231 if (RT_SUCCESS(rc)) 232 { 233 /* 234 * Initialize the rest of the structure. 235 */ 236 RTListInit(&pTracker->UserList); 237 RTListInit(&pTracker->TagList); 238 RTListInit(&pTracker->FallbackUser.ListEntry); 239 RTListInit(&pTracker->FallbackUser.MemoryList); 240 pTracker->FallbackUser.pTracker = pTracker; 241 pTracker->FallbackUser.cInTracker = INT32_MIN / 2; 242 pTracker->FallbackUser.idUser = pTracker->idUserNext++; 243 strcpy(pTracker->FallbackUser.szName, "fallback"); 244 245 *ppTracker = pTracker; 246 return VINF_SUCCESS; 247 } 248 249 RTTlsFree(pTracker->iTls); 250 } 251 RTSemXRoadsDestroy(pTracker->hXRoadsTagDb); 252 } 253 RTSemXRoadsDestroy(pTracker->hXRoads); 254 } 255 RTCritSectDelete(&pTracker->CritSect); 256 } 257 return rc; 258 } 259 260 261 /** 262 * Gets the user record to use. 263 * 264 * @returns Pointer to a user record. 265 * @param pTracker The tracker instance. 266 */ 267 static PRTMEMTRACKERUSER rtMemTrackerGetUser(PRTMEMTRACKERINT pTracker) 268 { 269 /* ASSUMES that RTTlsGet and RTTlsSet will not reenter. */ 270 PRTMEMTRACKERUSER pUser = (PRTMEMTRACKERUSER)RTTlsGet(pTracker->iTls); 271 if (RT_UNLIKELY(!pUser)) 272 { 273 /* 274 * Is the thread currently initializing or terminating? 275 * If so, don't try add any user record for it as RTThread may barf or 276 * we might not get the thread name. 277 */ 278 if (!RTThreadIsSelfAlive()) 279 return &pTracker->FallbackUser; 280 281 /* 282 * Allocate and initialize a new user record for this thread. 283 * 284 * We install the fallback user record while doing the allocation and 285 * locking so that we can deal with recursions. 286 */ 287 int rc = RTTlsSet(pTracker->iTls, &pTracker->FallbackUser); 288 if (RT_SUCCESS(rc)) 289 { 290 pUser = (PRTMEMTRACKERUSER)RTMemAllocZ(sizeof(*pUser)); 291 if (pUser) 292 { 293 rc = RTCritSectInitEx(&pUser->CritSect, 294 RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_BOOTSTRAP_HACK, 295 NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL); 296 if (RT_SUCCESS(rc)) 297 { 298 RTListInit(&pUser->ListEntry); 299 RTListInit(&pUser->MemoryList); 300 pUser->pTracker = pTracker; 301 pUser->cInTracker = 1; 302 303 const char *pszName = RTThreadSelfName(); 304 if (pszName) 305 RTStrCopy(pUser->szName, sizeof(pUser->szName), pszName); 306 307 /* 308 * Register the new user record. 309 */ 310 rc = RTTlsSet(pTracker->iTls, pUser); 311 if (RT_SUCCESS(rc)) 312 { 313 RTCritSectEnter(&pTracker->CritSect); 314 315 pUser->idUser = pTracker->idUserNext++; 316 RTListAppend(&pTracker->UserList, &pUser->ListEntry); 317 pTracker->cUsers++; 318 319 RTCritSectLeave(&pTracker->CritSect); 320 return pUser; 321 } 322 323 RTCritSectDelete(&pUser->CritSect); 324 } 325 RTMemFree(pUser); 326 } 327 else 328 rc = VERR_NO_MEMORY; 329 } 330 331 /* Failed, user the fallback. */ 332 pUser = &pTracker->FallbackUser; 333 } 334 335 ASMAtomicIncS32(&pUser->cInTracker); 336 return pUser; 337 } 338 339 340 /** 341 * Counterpart to rtMemTrackerGetUser. 342 * 343 * @param pUser The user record to 'put' back. 344 */ 345 DECLINLINE(void) rtMemTrackerPutUser(PRTMEMTRACKERUSER pUser) 346 { 347 ASMAtomicDecS32(&pUser->cInTracker); 348 } 349 350 351 /** 352 * Get the tag record corresponding to @a pszTag. 353 * 354 * @returns The tag record. This may be NULL if we're out of memory or 355 * if something goes wrong. 356 * 357 * @param pTracker The tracker instance. 358 * @param pUser The user record of the caller. Must NOT be 359 * NULL. This is used to prevent infinite 360 * recursions when allocating a new tag record. 361 * @param pszTag The tag string. Can be NULL. 362 */ 363 DECLINLINE(PRTMEMTRACKERTAG) rtMemTrackerGetTag(PRTMEMTRACKERINT pTracker, PRTMEMTRACKERUSER pUser, const char *pszTag) 364 { 365 AssertPtr(pTracker); 366 AssertPtr(pUser); 367 if (pUser->cInTracker <= 0) 368 return NULL; 369 370 /* 371 * Hash tag string. 372 */ 373 size_t cchTag; 374 uint32_t uHash; 375 if (pszTag) 376 uHash = sdbmN(pszTag, 260, &cchTag); 377 else 378 { 379 pszTag = ""; 380 cchTag = 0; 381 uHash = 0; 382 } 383 384 /* 385 * Look up the tag. 386 */ 387 RTSemXRoadsNSEnter(pTracker->hXRoadsTagDb); 388 PRTMEMTRACKERTAG pTag = (PRTMEMTRACKERTAG)RTAvlU32Get(&pTracker->TagDbRoot, uHash); 389 while ( pTag 390 && ( pTag->cchTag != cchTag 391 || memcmp(pTag->szTag, pszTag, cchTag)) ) 392 pTag = pTag->pNext; 393 RTSemXRoadsNSLeave(pTracker->hXRoadsTagDb); 394 395 /* 396 * Create a new tag record if not found. 397 */ 398 if (RT_UNLIKELY(!pTag)) 399 { 400 pTag = (PRTMEMTRACKERTAG)RTMemAllocZVar(RT_OFFSETOF(RTMEMTRACKERTAG, szTag[cchTag + 1])); 401 if (pTag) 402 { 403 pTag->Core.Key = uHash; 404 pTag->cchTag = cchTag; 405 memcpy(pTag->szTag, pszTag, cchTag + 1); 406 407 RTSemXRoadsEWEnter(pTracker->hXRoadsTagDb); 408 RTCritSectEnter(&pTracker->CritSect); 409 410 void *pvFreeMe = NULL; 411 PRTMEMTRACKERTAG pHeadTag = (PRTMEMTRACKERTAG)RTAvlU32Get(&pTracker->TagDbRoot, uHash); 412 if (!pHeadTag) 413 { 414 RTAvlU32Insert(&pTracker->TagDbRoot, &pTag->Core); 415 RTListAppend(&pTracker->TagList, &pTag->ListEntry); 416 pTracker->cTags++; 417 } 418 else 419 { 420 PRTMEMTRACKERTAG pTag2 = pHeadTag; 421 while ( pTag2 422 && ( pTag2->cchTag != cchTag 423 || memcmp(pTag2->szTag, pszTag, cchTag)) ) 424 pTag2 = pTag2->pNext; 425 if (RT_LIKELY(!pTag2)) 426 { 427 pTag->pNext = pHeadTag->pNext; 428 pHeadTag->pNext = pTag; 429 RTListAppend(&pTracker->TagList, &pTag->ListEntry); 430 pTracker->cTags++; 431 } 432 else 433 { 434 pvFreeMe = pTag; 435 pTag = pTag2; 436 } 437 } 438 439 RTCritSectLeave(&pTracker->CritSect); 440 RTSemXRoadsEWLeave(pTracker->hXRoadsTagDb); 441 442 if (RT_LIKELY(pvFreeMe)) 443 RTMemFree(pvFreeMe); 444 } 445 } 446 447 return pTag; 448 } 449 450 451 /** 452 * Counterpart to rtMemTrackerGetTag. 453 * 454 * @param pTag The tag record to 'put' back. 455 */ 456 DECLINLINE(void) rtMemTrackerPutTag(PRTMEMTRACKERTAG pTag) 457 { 458 NOREF(pTag); 459 } 460 461 462 /** 463 * Record an allocation call. 464 * 465 * @param pStats The statistics record. 466 * @param cbUser The size of the allocation. 467 * @param enmMethod The allocation method. 468 */ 469 DECLINLINE(void) rtMemTrackerStateRecordAlloc(PRTMEMTRACKERSTATS pStats, size_t cbUser, RTMEMTRACKERMETHOD enmMethod) 470 { 471 ASMAtomicAddU64(&pStats->cbTotalAllocated, cbUser); 472 ASMAtomicIncU64(&pStats->cTotalAllocatedBlocks); 473 ASMAtomicAddZ(&pStats->cbAllocated, cbUser); 474 ASMAtomicIncZ(&pStats->cAllocatedBlocks); 475 ASMAtomicIncU64(&pStats->acMethodCalls[enmMethod]); 476 } 477 478 479 /** 480 * Record a free call. 481 * 482 * @param pStats The statistics record. 483 * @param cbUser The size of the allocation. 484 * @param enmMethod The free method. 485 */ 486 DECLINLINE(void) rtMemTrackerStateRecordFree(PRTMEMTRACKERSTATS pStats, size_t cbUser, RTMEMTRACKERMETHOD enmMethod) 487 { 488 ASMAtomicSubZ(&pStats->cbAllocated, cbUser); 489 ASMAtomicDecZ(&pStats->cAllocatedBlocks); 490 ASMAtomicIncU64(&pStats->acMethodCalls[enmMethod]); 491 } 492 493 494 /** 495 * Internal RTMemTrackerHdrAlloc and RTMemTrackerHdrAllocEx worker. 496 * 497 * @returns Pointer to the user data allocation. 498 * @param pTracker The tracker instance. Can be NULL. 499 * @param pv The pointer to the allocated memory. This 500 * includes room for the header. 501 * @param cbUser The size requested by the user. 502 * @param pszTag The tag string. 503 * @param enmMethod The allocation method. 504 */ 505 static void *rtMemTrackerHdrAllocEx(PRTMEMTRACKERINT pTracker, void *pv, size_t cbUser, 506 const char *pszTag, RTMEMTRACKERMETHOD enmMethod) 507 { 508 /* 509 * Check input. 510 */ 511 if (!pv) 512 return NULL; 513 AssertReturn(enmMethod > RTMEMTRACKERMETHOD_INVALID && enmMethod < RTMEMTRACKERMETHOD_END, NULL); 514 515 /* 516 * Initialize the header. 517 */ 518 PRTMEMTRACKERHDR pHdr = (PRTMEMTRACKERHDR)pv; 519 520 pHdr->uMagic = RTMEMTRACKERHDR_MAGIC; 521 pHdr->cbUser = cbUser; 522 RTListInit(&pHdr->ListEntry); 523 pHdr->pUser = NULL; 524 pHdr->pszTag = pszTag; 525 pHdr->pTag = NULL; 526 pHdr->pvUser = pHdr + 1; 527 528 /* 529 * Add it to the tracker if we've got one. 530 */ 531 if (pTracker) 532 { 533 PRTMEMTRACKERUSER pUser = rtMemTrackerGetUser(pTracker); 534 if (pUser->cInTracker == 1) 535 { 536 RTSemXRoadsNSEnter(pTracker->hXRoads); 537 538 /* Get the tag and update it's statistics. */ 539 PRTMEMTRACKERTAG pTag = rtMemTrackerGetTag(pTracker, pUser, pszTag); 540 if (pTag) 541 { 542 pHdr->pTag = pTag; 543 rtMemTrackerStateRecordAlloc(&pTag->Stats, cbUser, enmMethod); 544 rtMemTrackerPutTag(pTag); 545 } 546 547 /* Link the header and update the user statistics. */ 548 RTCritSectEnter(&pUser->CritSect); 549 RTListAppend(&pUser->MemoryList, &pHdr->ListEntry); 550 RTCritSectLeave(&pUser->CritSect); 551 552 pHdr->pUser = pUser; 553 rtMemTrackerStateRecordAlloc(&pUser->Stats, cbUser, enmMethod); 554 555 /* Update the global statistics. */ 556 rtMemTrackerStateRecordAlloc(&pTracker->GlobalStats, cbUser, enmMethod); 557 558 RTSemXRoadsNSLeave(pTracker->hXRoads); 559 } 560 else 561 ASMAtomicIncU64(&pTracker->cBusyAllocs); 562 rtMemTrackerPutUser(pUser); 563 } 564 565 return pHdr + 1; 566 } 567 568 569 /** 570 * Internal worker for rtMemTrackerHdrFreeEx and rtMemTrackerHdrReallocPrep. 571 * 572 * @returns Pointer to the original block. 573 * @param pTracker The tracker instance. Can be NULL. 574 * @param pvUser Pointer to the user memory. 575 * @param cbUser The size of the user memory or 0. 576 * @param pszTag The tag to associate the free with. 577 * @param enmMethod The free method. 578 * @param uDeadMagic The dead magic value to use. 579 */ 580 static void *rtMemTrackerHdrFreeCommon(PRTMEMTRACKERINT pTracker, void *pvUser, size_t cbUser, 581 const char *pszTag, RTMEMTRACKERMETHOD enmMethod, 582 size_t uDeadMagic) 583 { 584 PRTMEMTRACKERHDR pHdr = (PRTMEMTRACKERHDR)pvUser - 1; 585 AssertReturn(pHdr->uMagic == RTMEMTRACKERHDR_MAGIC, NULL); 586 Assert(pHdr->cbUser == cbUser || !cbUser); NOREF(cbUser); 587 Assert(pHdr->pvUser == pvUser); 588 589 AssertReturn(enmMethod > RTMEMTRACKERMETHOD_INVALID && enmMethod < RTMEMTRACKERMETHOD_END, NULL); 590 591 /* 592 * First mark it as free. 593 */ 594 pHdr->uMagic = uDeadMagic; 595 596 /* 597 * If there is a association with a user, we need to unlink it and update 598 * the statistics. 599 * 600 * A note on the locking here. We don't take the crossroads semaphore when 601 * reentering the memory tracker on the same thread because we may be 602 * holding it in a different direction and would therefore deadlock. 603 */ 604 PRTMEMTRACKERUSER pMemUser = pHdr->pUser; 605 if (pMemUser) 606 { 607 Assert(pMemUser->pTracker == pTracker); Assert(pTracker); 608 PRTMEMTRACKERUSER pCallingUser = rtMemTrackerGetUser(pTracker); 609 bool const fTakeXRoadsLock = pCallingUser->cInTracker <= 1; 610 if (fTakeXRoadsLock) 611 RTSemXRoadsNSEnter(pTracker->hXRoads); 612 613 RTCritSectEnter(&pMemUser->CritSect); 614 RTListNodeRemove(&pHdr->ListEntry); 615 RTCritSectLeave(&pMemUser->CritSect); 616 617 if (pCallingUser == pMemUser) 618 rtMemTrackerStateRecordFree(&pCallingUser->Stats, pHdr->cbUser, enmMethod); 619 else 620 { 621 ASMAtomicIncU64(&pCallingUser->Stats.cUserChanges); 622 ASMAtomicIncU64(&pCallingUser->Stats.acMethodCalls[enmMethod]); 623 624 ASMAtomicSubU64(&pMemUser->Stats.cbTotalAllocated, cbUser); 625 ASMAtomicSubZ(&pMemUser->Stats.cbAllocated, cbUser); 626 } 627 628 rtMemTrackerStateRecordFree(&pTracker->GlobalStats, pHdr->cbUser, enmMethod); 629 630 /** @todo we're currently ignoring pszTag, consider how to correctly 631 * attribute the free operation if the tags differ - it 632 * makes sense at all... */ 633 if (pHdr->pTag) 634 rtMemTrackerStateRecordFree(&pHdr->pTag->Stats, pHdr->cbUser, enmMethod); 635 636 637 if (fTakeXRoadsLock) 638 RTSemXRoadsNSLeave(pTracker->hXRoads); 639 rtMemTrackerPutUser(pCallingUser); 640 } 641 else 642 { 643 /* 644 * No tracked. This may happen even when pTracker != NULL when the same 645 * thread reenters the tracker when allocating tracker structures or memory 646 * in some subroutine like threading and locking. 647 */ 648 Assert(!pHdr->pTag); 649 if (pTracker) 650 ASMAtomicIncU64(&pTracker->cBusyFrees); 651 } 652 653 return pHdr; 654 } 655 656 657 /** 658 * Internal worker for RTMemTrackerHdrReallocPrep and 659 * RTMemTrackerHdrReallocPrepEx. 660 * 661 * @returns Pointer to the actual allocation. 662 * @param pTracker The tracker instance. Can be NULL. 663 * @param pvOldUser The user memory. 664 * @param cbOldUser The size of the user memory, 0 if unknown. 665 * @param pszTag The tag string. 666 */ 667 static void *rtMemTrackerHdrReallocPrepEx(PRTMEMTRACKERINT pTracker, void *pvOldUser, size_t cbOldUser, const char *pszTag) 668 { 669 if (!pvOldUser) 670 return NULL; 671 return rtMemTrackerHdrFreeCommon(pTracker, pvOldUser, cbOldUser, pszTag, 672 RTMEMTRACKERMETHOD_REALLOC_PREP, RTMEMTRACKERHDR_MAGIC_REALLOC); 673 } 674 675 676 /** 677 * Internal worker for RTMemTrackerHdrReallocDone and 678 * RTMemTrackerHdrReallocDoneEx. 679 * 680 * @returns Pointer to the actual allocation. 681 * @param pTracker The tracker instance. Can be NULL. 682 * @param pvNew The new memory chunk. Can be NULL. 683 * @param cbNewUser The size of the new memory chunk. 684 * @param pvOldUser Pointer to the old user memory. 685 * @param pszTag The tag string. 686 */ 687 static void *rtMemTrackerHdrReallocDoneEx(PRTMEMTRACKERINT pTracker, void *pvNew, size_t cbNewUser, 688 void *pvOldUser, const char *pszTag) 689 { 690 /* Succeeded? */ 691 if (pvNew) 692 return rtMemTrackerHdrAllocEx(pTracker, pvNew, cbNewUser, pszTag, RTMEMTRACKERMETHOD_REALLOC_DONE); 693 694 /* Failed or just realloc to zero? */ 695 if (cbNewUser) 696 { 697 PRTMEMTRACKERHDR pHdr = (PRTMEMTRACKERHDR)pvOldUser - 1; 698 AssertReturn(pHdr->uMagic == RTMEMTRACKERHDR_MAGIC_REALLOC, NULL); 699 700 return rtMemTrackerHdrAllocEx(pTracker, pHdr, pHdr->cbUser, pszTag, RTMEMTRACKERMETHOD_REALLOC_FAILED); 701 } 702 703 /* Tealloc to zero bytes, i.e. free. */ 704 return NULL; 705 } 706 707 708 /** 709 * Internal worker for RTMemTrackerHdrFree and RTMemTrackerHdrFreeEx. 710 * 711 * @returns Pointer to the actual allocation. 712 * @param pTracker The tracker instance. Can be NULL. 713 * @param pvUser The user memory. 714 * @param cbUser The size of the user memory, 0 if unknown. 715 * @param pszTag The tag string. 716 * @param enmMethod The free method. 717 */ 718 static void *rtMemTrackerHdrFreeEx(PRTMEMTRACKERINT pTracker, void *pvUser, size_t cbUser, 719 const char *pszTag, RTMEMTRACKERMETHOD enmMethod) 720 { 721 if (!pvUser) 722 return NULL; 723 return rtMemTrackerHdrFreeCommon(pTracker, pvUser, cbUser, pszTag, enmMethod, RTMEMTRACKERHDR_MAGIC_FREE); 724 } 725 726 727 /** 728 * Prints a statistics record. 729 * 730 * @param pStats The record. 731 * @param pOutput The output callback table. 732 * @param fVerbose Whether to print in terse or verbose form. 733 */ 734 DECLINLINE(void) rtMemTrackerDumpOneStatRecord(PRTMEMTRACKERSTATS pStats, PRTMEMTRACKEROUTPUT pOutput, bool fVerbose) 735 { 736 if (fVerbose) 737 { 738 pOutput->pfnPrintf(pOutput, 739 " Currently allocated: %7zu blocks, %8zu bytes\n" 740 " Total allocation sum: %7RU64 blocks, %8RU64 bytes\n" 741 , 742 pStats->cAllocatedBlocks, 743 pStats->cbAllocated, 744 pStats->cTotalAllocatedBlocks, 745 pStats->cbTotalAllocated); 746 pOutput->pfnPrintf(pOutput, 747 " Alloc: %7RU64 AllocZ: %7RU64 Free: %7RU64 User Chg: %7RU64\n" 748 " RPrep: %7RU64 RDone: %7RU64 RFail: %7RU64\n" 749 " New: %7RU64 New[]: %7RU64 Delete: %7RU64 Delete[]: %7RU64\n" 750 , 751 pStats->acMethodCalls[RTMEMTRACKERMETHOD_ALLOC], 752 pStats->acMethodCalls[RTMEMTRACKERMETHOD_ALLOCZ], 753 pStats->acMethodCalls[RTMEMTRACKERMETHOD_FREE], 754 pStats->cUserChanges, 755 pStats->acMethodCalls[RTMEMTRACKERMETHOD_REALLOC_PREP], 756 pStats->acMethodCalls[RTMEMTRACKERMETHOD_REALLOC_DONE], 757 pStats->acMethodCalls[RTMEMTRACKERMETHOD_REALLOC_FAILED], 758 pStats->acMethodCalls[RTMEMTRACKERMETHOD_NEW], 759 pStats->acMethodCalls[RTMEMTRACKERMETHOD_NEW_ARRAY], 760 pStats->acMethodCalls[RTMEMTRACKERMETHOD_DELETE], 761 pStats->acMethodCalls[RTMEMTRACKERMETHOD_DELETE_ARRAY]); 762 } 763 else 764 { 765 pOutput->pfnPrintf(pOutput, " %zu bytes in %zu blocks\n", 766 pStats->cbAllocated, pStats->cAllocatedBlocks); 767 } 768 } 769 770 771 /** 772 * Internal worker that dumps all the memory tracking data. 773 * 774 * @param pTracker The tracker instance. Can be NULL. 775 * @param pOutput The output callback table. 776 */ 777 static void rtMemTrackerDumpAllWorker(PRTMEMTRACKERINT pTracker, PRTMEMTRACKEROUTPUT pOutput) 778 { 779 if (!pTracker) 780 return; 781 782 /* 783 * We use the EW direction to make sure the lists, trees and statistics 784 * does not change while we're working. 785 */ 786 PRTMEMTRACKERUSER pUser = rtMemTrackerGetUser(pTracker); 787 RTSemXRoadsEWEnter(pTracker->hXRoads); 788 789 /* Global statistics.*/ 790 pOutput->pfnPrintf(pOutput, "*** Global statistics ***\n"); 791 rtMemTrackerDumpOneStatRecord(&pTracker->GlobalStats, pOutput, true); 792 pOutput->pfnPrintf(pOutput, " Busy Allocs: %4RU64 Busy Frees: %4RU64 Tags: %3u Users: %3u\n", 793 pTracker->cBusyAllocs, pTracker->cBusyFrees, pTracker->cTags, pTracker->cUsers); 794 795 /* Per tag statistics. */ 796 pOutput->pfnPrintf(pOutput, "\n*** Tag statistics ***\n"); 797 PRTMEMTRACKERTAG pTag, pNextTag; 798 RTListForEachSafe(&pTracker->TagList, pTag, pNextTag, RTMEMTRACKERTAG, ListEntry) 799 { 800 pOutput->pfnPrintf(pOutput, "Tag: %s\n", pTag->szTag); 801 rtMemTrackerDumpOneStatRecord(&pTag->Stats, pOutput, true); 802 pOutput->pfnPrintf(pOutput, "\n", pTag->szTag); 803 } 804 805 /* Per user statistics & blocks. */ 806 pOutput->pfnPrintf(pOutput, "\n*** User statistics ***\n"); 807 PRTMEMTRACKERUSER pCurUser, pNextUser; 808 RTListForEachSafe(&pTracker->UserList, pCurUser, pNextUser, RTMEMTRACKERUSER, ListEntry) 809 { 810 pOutput->pfnPrintf(pOutput, "User #%u: %s%s (cInTracker=%d)\n", 811 pCurUser->idUser, 812 pCurUser->szName, 813 pUser == pCurUser ? " (me)" : "", 814 pCurUser->cInTracker); 815 rtMemTrackerDumpOneStatRecord(&pCurUser->Stats, pOutput, true); 816 817 PRTMEMTRACKERHDR pCurHdr, pNextHdr; 818 RTListForEachSafe(&pCurUser->MemoryList, pCurHdr, pNextHdr, RTMEMTRACKERHDR, ListEntry) 819 { 820 if (pCurHdr->pTag) 821 pOutput->pfnPrintf(pOutput, 822 " %zu bytes at %p with tag %s\n" 823 " %.*Rhxd\n" 824 "\n", 825 pCurHdr->cbUser, pCurHdr->pvUser, pCurHdr->pTag->szTag, 826 RT_MIN(pCurHdr->cbUser, 16*3), pCurHdr->pvUser); 827 else 828 pOutput->pfnPrintf(pOutput, 829 " %zu bytes at %p without a tag\n" 830 " %.*Rhxd\n" 831 "\n", 832 pCurHdr->cbUser, pCurHdr->pvUser, 833 RT_MIN(pCurHdr->cbUser, 16*3), pCurHdr->pvUser); 834 } 835 pOutput->pfnPrintf(pOutput, "\n", pTag->szTag); 836 } 837 838 /* Repeat the global statistics. */ 839 pOutput->pfnPrintf(pOutput, "*** Global statistics (reprise) ***\n"); 840 rtMemTrackerDumpOneStatRecord(&pTracker->GlobalStats, pOutput, true); 841 pOutput->pfnPrintf(pOutput, " Busy Allocs: %4RU64 Busy Frees: %4RU64 Tags: %3u Users: %3u\n", 842 pTracker->cBusyAllocs, pTracker->cBusyFrees, pTracker->cTags, pTracker->cUsers); 843 844 RTSemXRoadsEWLeave(pTracker->hXRoads); 845 rtMemTrackerPutUser(pUser); 846 } 847 848 849 /** 850 * Internal worker that dumps the memory tracking statistics. 851 * 852 * @param pTracker The tracker instance. Can be NULL. 853 * @param pOutput The output callback table. 854 * @param fVerbose Whether to the verbose or quiet. 855 */ 856 static void rtMemTrackerDumpStatsWorker(PRTMEMTRACKERINT pTracker, PRTMEMTRACKEROUTPUT pOutput, bool fVerbose) 857 { 858 if (!pTracker) 859 return; 860 861 /* 862 * We use the EW direction to make sure the lists, trees and statistics 863 * does not change while we're working. 864 */ 865 PRTMEMTRACKERUSER pUser = rtMemTrackerGetUser(pTracker); 866 RTSemXRoadsEWEnter(pTracker->hXRoads); 867 868 /* Global statistics.*/ 869 pOutput->pfnPrintf(pOutput, "*** Global statistics ***\n"); 870 rtMemTrackerDumpOneStatRecord(&pTracker->GlobalStats, pOutput, fVerbose); 871 if (fVerbose) 872 pOutput->pfnPrintf(pOutput, " Busy Allocs: %4RU64 Busy Frees: %4RU64 Tags: %3u Users: %3u\n", 873 pTracker->cBusyAllocs, pTracker->cBusyFrees, pTracker->cTags, pTracker->cUsers); 874 875 /* Per tag statistics. */ 876 pOutput->pfnPrintf(pOutput, "\n*** Tag statistics ***\n"); 877 PRTMEMTRACKERTAG pTag, pNextTag; 878 RTListForEachSafe(&pTracker->TagList, pTag, pNextTag, RTMEMTRACKERTAG, ListEntry) 879 { 880 if ( fVerbose 881 || pTag->Stats.cbAllocated) 882 { 883 pOutput->pfnPrintf(pOutput, "Tag: %s\n", pTag->szTag); 884 rtMemTrackerDumpOneStatRecord(&pTag->Stats, pOutput, fVerbose); 885 if (fVerbose) 886 pOutput->pfnPrintf(pOutput, "\n", pTag->szTag); 887 } 888 } 889 890 /* Per user statistics. */ 891 pOutput->pfnPrintf(pOutput, "\n*** User statistics ***\n"); 892 PRTMEMTRACKERUSER pCurUser, pNextUser; 893 RTListForEachSafe(&pTracker->UserList, pCurUser, pNextUser, RTMEMTRACKERUSER, ListEntry) 894 { 895 if ( fVerbose 896 || pCurUser->Stats.cbAllocated 897 || pCurUser == pUser) 898 { 899 pOutput->pfnPrintf(pOutput, "User #%u: %s%s (cInTracker=%d)\n", 900 pCurUser->idUser, 901 pCurUser->szName, 902 pUser == pCurUser ? " (me)" : "", 903 pCurUser->cInTracker); 904 rtMemTrackerDumpOneStatRecord(&pCurUser->Stats, pOutput, fVerbose); 905 if (fVerbose) 906 pOutput->pfnPrintf(pOutput, "\n", pTag->szTag); 907 } 908 } 909 910 if (fVerbose) 911 { 912 /* Repeat the global statistics. */ 913 pOutput->pfnPrintf(pOutput, "*** Global statistics (reprise) ***\n"); 914 rtMemTrackerDumpOneStatRecord(&pTracker->GlobalStats, pOutput, fVerbose); 915 pOutput->pfnPrintf(pOutput, " Busy Allocs: %4RU64 Busy Frees: %4RU64 Tags: %3u Users: %3u\n", 916 pTracker->cBusyAllocs, pTracker->cBusyFrees, pTracker->cTags, pTracker->cUsers); 917 } 918 919 RTSemXRoadsEWLeave(pTracker->hXRoads); 920 rtMemTrackerPutUser(pUser); 921 } 922 923 924 /** 925 * @callback_method_impl{RTMEMTRACKEROUTPUT::pfnPrintf, Outputting to the release log} 926 */ 927 static DECLCALLBACK(void) rtMemTrackerDumpLogOutput(PRTMEMTRACKEROUTPUT pThis, const char *pszFormat, ...) 928 { 929 va_list va; 930 va_start(va, pszFormat); 931 RTLogPrintfV(pszFormat, va); 932 va_end(va); 933 } 934 935 936 /** 937 * Internal worker for RTMemTrackerDumpAllToLog and RTMemTrackerDumpAllToLogEx. 938 * 939 * @param pTracker The tracker instance. Can be NULL. 940 */ 941 static void rtMemTrackerDumpAllToLogEx(PRTMEMTRACKERINT pTracker) 942 { 943 RTMEMTRACKEROUTPUT Output; 944 Output.pfnPrintf = rtMemTrackerDumpLogOutput; 945 rtMemTrackerDumpAllWorker(pTracker, &Output); 946 } 947 948 949 /** 950 * Internal worker for RTMemTrackerDumpStatsToLog and 951 * RTMemTrackerDumpStatsToLogEx. 952 * 953 * @param pTracker The tracker instance. Can be NULL. 954 * @param fVerbose Whether to print all the stats or just the ones 955 * relevant to hunting leaks. 956 */ 957 static void rtMemTrackerDumpStatsToLogEx(PRTMEMTRACKERINT pTracker, bool fVerbose) 958 { 959 RTMEMTRACKEROUTPUT Output; 960 Output.pfnPrintf = rtMemTrackerDumpLogOutput; 961 rtMemTrackerDumpStatsWorker(pTracker, &Output, fVerbose); 962 } 963 964 965 /** 966 * @callback_method_impl{RTMEMTRACKEROUTPUT::pfnPrintf, Outputting to the release log} 967 */ 968 static DECLCALLBACK(void) rtMemTrackerDumpLogRelOutput(PRTMEMTRACKEROUTPUT pThis, const char *pszFormat, ...) 969 { 970 va_list va; 971 va_start(va, pszFormat); 972 RTLogRelPrintfV(pszFormat, va); 973 va_end(va); 974 } 975 976 977 /** 978 * Internal worker for RTMemTrackerDumpStatsToLog and 979 * RTMemTrackerDumpStatsToLogEx. 980 * 981 * @param pTracker The tracker instance. Can be NULL. 982 */ 983 static void rtMemTrackerDumpAllToLogRelEx(PRTMEMTRACKERINT pTracker) 984 { 985 RTMEMTRACKEROUTPUT Output; 986 Output.pfnPrintf = rtMemTrackerDumpLogRelOutput; 987 rtMemTrackerDumpAllWorker(pTracker, &Output); 988 } 989 990 991 /** 992 * Internal worker for RTMemTrackerDumpStatsToLogRel and 993 * RTMemTrackerDumpStatsToLogRelEx. 994 * 995 * @param pTracker The tracker instance. Can be NULL. 996 * @param fVerbose Whether to print all the stats or just the ones 997 * relevant to hunting leaks. 998 */ 999 static void rtMemTrackerDumpStatsToLogRelEx(PRTMEMTRACKERINT pTracker, bool fVerbose) 1000 { 1001 RTMEMTRACKEROUTPUT Output; 1002 Output.pfnPrintf = rtMemTrackerDumpLogRelOutput; 1003 rtMemTrackerDumpStatsWorker(pTracker, &Output, fVerbose); 1004 } 1005 1006 #ifdef IN_RING3 1007 1008 /** 1009 * @callback_method_impl{RTMEMTRACKEROUTPUT::pfnPrintf, Outputting to file} 1010 */ 1011 static DECLCALLBACK(void) rtMemTrackerDumpFileOutput(PRTMEMTRACKEROUTPUT pThis, const char *pszFormat, ...) 1012 { 1013 va_list va; 1014 va_start(va, pszFormat); 1015 char szOutput[_4K]; 1016 size_t cchOutput = RTStrPrintfV(szOutput, sizeof(szOutput), pszFormat, va); 1017 va_end(va); 1018 RTFileWrite(pThis->uData.hFile, szOutput, cchOutput, NULL); 1019 } 1020 1021 1022 /** 1023 * Internal work that dumps the memory tracking statistics to a file handle. 1024 * 1025 * @param pTracker The tracker instance. Can be NULL. 1026 * @param fVerbose Whether to print all the stats or just the ones 1027 * relevant to hunting leaks. 1028 * @param hFile The file handle. Can be NIL_RTFILE. 1029 */ 1030 static void rtMemTrackerDumpStatsToFileHandle(PRTMEMTRACKERINT pTracker, bool fVerbose, RTFILE hFile) 1031 { 1032 if (hFile == NIL_RTFILE) 1033 return; 1034 RTMEMTRACKEROUTPUT Output; 1035 Output.pfnPrintf = rtMemTrackerDumpFileOutput; 1036 Output.uData.hFile = hFile; 1037 rtMemTrackerDumpStatsWorker(pTracker, &Output, fVerbose); 1038 } 1039 1040 1041 /** 1042 * Internal work that dumps all the memory tracking information to a file 1043 * handle. 1044 * 1045 * @param pTracker The tracker instance. Can be NULL. 1046 * @param hFile The file handle. Can be NIL_RTFILE. 1047 */ 1048 static void rtMemTrackerDumpAllToFileHandle(PRTMEMTRACKERINT pTracker, RTFILE hFile) 1049 { 1050 if (hFile == NIL_RTFILE) 1051 return; 1052 RTMEMTRACKEROUTPUT Output; 1053 Output.pfnPrintf = rtMemTrackerDumpFileOutput; 1054 Output.uData.hFile = hFile; 1055 rtMemTrackerDumpAllWorker(pTracker, &Output); 1056 } 1057 1058 1059 /** 1060 * Internal worker for RTMemTrackerDumpStatsToStdOut and 1061 * RTMemTrackerDumpStatsToStdOutEx. 1062 * 1063 * @param pTracker The tracker instance. Can be NULL. 1064 * @param fVerbose Whether to print all the stats or just the ones 1065 * relevant to hunting leaks. 1066 */ 1067 static void rtMemTrackerDumpStatsToStdOutEx(PRTMEMTRACKERINT pTracker, bool fVerbose) 1068 { 1069 rtMemTrackerDumpStatsToFileHandle(pTracker, fVerbose, rtFileGetStandard(RTHANDLESTD_OUTPUT)); 1070 } 1071 1072 1073 /** 1074 * Internal worker for RTMemTrackerDumpAllToStdOut and 1075 * RTMemTrackerDumpAllToStdOutEx. 1076 * 1077 * @param pTracker The tracker instance. Can be NULL. 1078 */ 1079 static void rtMemTrackerDumpAllToStdOutEx(PRTMEMTRACKERINT pTracker) 1080 { 1081 rtMemTrackerDumpAllToFileHandle(pTracker, rtFileGetStandard(RTHANDLESTD_OUTPUT)); 1082 } 1083 1084 1085 /** 1086 * Internal worker for RTMemTrackerDumpStatsToStdErr and 1087 * RTMemTrackerDumpStatsToStdErrEx. 1088 * 1089 * @param pTracker The tracker instance. Can be NULL. 1090 * @param fVerbose Whether to print all the stats or just the ones 1091 * relevant to hunting leaks. 1092 */ 1093 static void rtMemTrackerDumpStatsToStdErrEx(PRTMEMTRACKERINT pTracker, bool fVerbose) 1094 { 1095 rtMemTrackerDumpStatsToFileHandle(pTracker, fVerbose, rtFileGetStandard(RTHANDLESTD_ERROR)); 1096 } 1097 1098 1099 /** 1100 * Internal worker for RTMemTrackerDumpAllToStdErr and 1101 * RTMemTrackerDumpAllToStdErrEx. 1102 * 1103 * @param pTracker The tracker instance. Can be NULL. 1104 */ 1105 static void rtMemTrackerDumpAllToStdErrEx(PRTMEMTRACKERINT pTracker) 1106 { 1107 rtMemTrackerDumpAllToFileHandle(pTracker, rtFileGetStandard(RTHANDLESTD_ERROR)); 1108 } 1109 1110 1111 /** 1112 * Internal worker for RTMemTrackerDumpStatsToFile and 1113 * RTMemTrackerDumpStatsToFileEx. 1114 * 1115 * @param pTracker The tracker instance. Can be NULL. 1116 * @param fVerbose Whether to print all the stats or just the ones 1117 * relevant to hunting leaks. 1118 * @param pszFilename The name of the output file. 1119 */ 1120 static void rtMemTrackerDumpStatsToFileEx(PRTMEMTRACKERINT pTracker, bool fVerbose, const char *pszFilename) 1121 { 1122 if (!pTracker) 1123 return; 1124 1125 /** @todo this is borked. */ 1126 RTFILE hFile; 1127 int rc = RTFileOpen(&hFile, pszFilename, 1128 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE 1129 | (0600 << RTFILE_O_CREATE_MODE_SHIFT)); 1130 if (RT_FAILURE(rc)) 1131 return; 1132 rtMemTrackerDumpStatsToFileHandle(pTracker, fVerbose, hFile); 1133 RTFileClose(hFile); 1134 } 1135 1136 1137 /** 1138 * Internal worker for RTMemTrackerDumpAllToFile and 1139 * RTMemTrackerDumpAllToFileEx. 1140 * 1141 * @param pTracker The tracker instance. Can be NULL. 1142 * @param pszFilename The name of the output file. 1143 */ 1144 static void rtMemTrackerDumpAllToFileEx(PRTMEMTRACKERINT pTracker, const char *pszFilename) 1145 { 1146 if (!pTracker) 1147 return; 1148 1149 RTFILE hFile; 1150 int rc = RTFileOpen(&hFile, pszFilename, 1151 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE 1152 | (0600 << RTFILE_O_CREATE_MODE_SHIFT)); 1153 if (RT_FAILURE(rc)) 1154 return; 1155 rtMemTrackerDumpAllToFileHandle(pTracker, hFile); 1156 RTFileClose(hFile); 1157 } 1158 1159 #endif /* IN_RING3 */ 1160 1161 1162 1163 /* 1164 * 1165 * 1166 * Default tracker. 1167 * Default tracker. 1168 * Default tracker. 1169 * Default tracker. 1170 * Default tracker. 1171 * 1172 * 1173 */ 1174 1175 1176 /** 1177 * Handles the lazy initialization when g_pDefaultTracker is NULL. 1178 * 1179 * @returns The newly created default tracker or NULL. 1180 */ 1181 static PRTMEMTRACKERINT rtMemTrackerLazyInitDefaultTracker(void) 1182 { 1183 /* 1184 * Don't attempt initialize before RTThread has been initialized. 1185 */ 1186 if (!RTThreadIsInitialized()) 1187 return NULL; 1188 1189 /* 1190 * Only one initialization at a time. For now we'll ASSUME that there 1191 * won't be thread ending up here at the same time, only the same 1192 * reentering from the allocator when creating the tracker. 1193 */ 1194 static volatile bool s_fInitialized = false; 1195 if (ASMAtomicXchgBool(&s_fInitialized, true)) 1196 return g_pDefaultTracker; 1197 1198 PRTMEMTRACKERINT pTracker; 1199 int rc = rtMemTrackerCreate(&pTracker); 1200 if (RT_FAILURE(rc)) 1201 return NULL; 1202 1203 g_pDefaultTracker = pTracker; 1204 return pTracker; 1205 } 1206 1207 1208 1209 RTDECL(void *) RTMemTrackerHdrAlloc(void *pv, size_t cb, const char *pszTag, RTMEMTRACKERMETHOD enmMethod) 1210 { 1211 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1212 if (RT_UNLIKELY(!pTracker)) 1213 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1214 return rtMemTrackerHdrAllocEx(pTracker, pv, cb, pszTag, enmMethod); 1215 } 1216 1217 1218 RTDECL(void *) RTMemTrackerHdrReallocPrep(void *pvOldUser, size_t cbOldUser, const char *pszTag) 1219 { 1220 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1221 if (RT_UNLIKELY(!pTracker)) 1222 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1223 return rtMemTrackerHdrReallocPrepEx(pTracker, pvOldUser, cbOldUser, pszTag); 1224 } 1225 1226 1227 RTDECL(void *) RTMemTrackerHdrReallocDone(void *pvNew, size_t cbNewUser, void *pvOld, const char *pszTag) 1228 { 1229 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1230 if (RT_UNLIKELY(!pTracker)) 1231 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1232 return rtMemTrackerHdrReallocDoneEx(pTracker, pvNew, cbNewUser, pvOld, pszTag); 1233 } 1234 1235 1236 RTDECL(void *) RTMemTrackerHdrFree(void *pvUser, size_t cbUser, const char *pszTag, RTMEMTRACKERMETHOD enmMethod) 1237 { 1238 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1239 if (RT_UNLIKELY(!pTracker)) 1240 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1241 return rtMemTrackerHdrFreeEx(pTracker, pvUser, cbUser, pszTag, enmMethod); 1242 } 1243 1244 1245 RTDECL(void) RTMemTrackerDumpAllToLog(void) 1246 { 1247 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1248 if (RT_UNLIKELY(!pTracker)) 1249 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1250 return rtMemTrackerDumpAllToLogEx(pTracker); 1251 } 1252 1253 1254 RTDECL(void) RTMemTrackerDumpAllToLogRel(void) 1255 { 1256 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1257 if (RT_UNLIKELY(!pTracker)) 1258 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1259 return rtMemTrackerDumpAllToLogRelEx(pTracker); 1260 } 1261 1262 1263 RTDECL(void) RTMemTrackerDumpAllToStdOut(void) 1264 { 1265 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1266 if (RT_UNLIKELY(!pTracker)) 1267 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1268 return rtMemTrackerDumpAllToStdOutEx(pTracker); 1269 } 1270 1271 1272 RTDECL(void) RTMemTrackerDumpAllToStdErr(void) 1273 { 1274 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1275 if (RT_UNLIKELY(!pTracker)) 1276 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1277 return rtMemTrackerDumpAllToStdErrEx(pTracker); 1278 } 1279 1280 1281 RTDECL(void) RTMemTrackerDumpAllToFile(const char *pszFilename) 1282 { 1283 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1284 if (RT_UNLIKELY(!pTracker)) 1285 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1286 return rtMemTrackerDumpAllToFileEx(pTracker, pszFilename); 1287 } 1288 1289 1290 RTDECL(void) RTMemTrackerDumpStatsToLog(bool fVerbose) 1291 { 1292 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1293 if (RT_UNLIKELY(!pTracker)) 1294 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1295 return rtMemTrackerDumpStatsToLogEx(pTracker, fVerbose); 1296 } 1297 1298 1299 RTDECL(void) RTMemTrackerDumpStatsToLogRel(bool fVerbose) 1300 { 1301 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1302 if (RT_UNLIKELY(!pTracker)) 1303 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1304 return rtMemTrackerDumpStatsToLogRelEx(pTracker, fVerbose); 1305 } 1306 1307 1308 RTDECL(void) RTMemTrackerDumpStatsToStdOut(bool fVerbose) 1309 { 1310 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1311 if (RT_UNLIKELY(!pTracker)) 1312 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1313 return rtMemTrackerDumpStatsToStdOutEx(pTracker, fVerbose); 1314 } 1315 1316 1317 RTDECL(void) RTMemTrackerDumpStatsToStdErr(bool fVerbose) 1318 { 1319 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1320 if (RT_UNLIKELY(!pTracker)) 1321 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1322 return rtMemTrackerDumpStatsToStdErrEx(pTracker, fVerbose); 1323 } 1324 1325 1326 RTDECL(void) RTMemTrackerDumpStatsToFile(bool fVerbose, const char *pszFilename) 1327 { 1328 PRTMEMTRACKERINT pTracker = g_pDefaultTracker; 1329 if (RT_UNLIKELY(!pTracker)) 1330 pTracker = rtMemTrackerLazyInitDefaultTracker(); 1331 return rtMemTrackerDumpStatsToFileEx(pTracker, fVerbose, pszFilename); 1332 } 1333 -
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r34507 r36597 43 43 #include "internal/lockvalidator.h" 44 44 #include "internal/magics.h" 45 #include "internal/strhash.h" 45 46 #include "internal/thread.h" 46 47 … … 851 852 852 853 853 /* sdbm:854 This algorithm was created for sdbm (a public-domain reimplementation of855 ndbm) database library. it was found to do well in scrambling bits,856 causing better distribution of the keys and fewer splits. it also happens857 to be a good general hashing function with good distribution. the actual858 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below859 is the faster version used in gawk. [there is even a faster, duff-device860 version] the magic constant 65599 was picked out of thin air while861 experimenting with different constants, and turns out to be a prime.862 this is one of the algorithms used in berkeley db (see sleepycat) and863 elsewhere. */864 DECL_FORCE_INLINE(uint32_t) sdbm(const char *str, uint32_t hash)865 {866 uint8_t *pu8 = (uint8_t *)str;867 int c;868 869 while ((c = *pu8++))870 hash = c + (hash << 6) + (hash << 16) - hash;871 872 return hash;873 }874 875 876 854 /** 877 855 * Hashes the specified source position. … … 889 867 uHash = 0; 890 868 if (pSrcPos->pszFile) 891 uHash = sdbm (pSrcPos->pszFile, uHash);869 uHash = sdbmInc(pSrcPos->pszFile, uHash); 892 870 if (pSrcPos->pszFunction) 893 uHash = sdbm (pSrcPos->pszFunction, uHash);871 uHash = sdbmInc(pSrcPos->pszFunction, uHash); 894 872 uHash += pSrcPos->uLine; 895 873 } -
trunk/src/VBox/Runtime/common/string/strspace.cpp
r36555 r36597 33 33 34 34 #include <iprt/assert.h> 35 #include "internal/strhash.h" 35 36 36 37 … … 72 73 #include "../table/avl_Destroy.cpp.h" 73 74 74 75 76 /* sdbm:77 This algorithm was created for sdbm (a public-domain reimplementation of78 ndbm) database library. it was found to do well in scrambling bits,79 causing better distribution of the keys and fewer splits. it also happens80 to be a good general hashing function with good distribution. the actual81 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below82 is the faster version used in gawk. [there is even a faster, duff-device83 version] the magic constant 65599 was picked out of thin air while84 experimenting with different constants, and turns out to be a prime.85 this is one of the algorithms used in berkeley db (see sleepycat) and86 elsewhere. */87 DECLINLINE(uint32_t) sdbm(const char *str, size_t *pcch)88 {89 uint8_t *pu8 = (uint8_t *)str;90 uint32_t hash = 0;91 int c;92 93 while ((c = *pu8++))94 hash = c + (hash << 6) + (hash << 16) - hash;95 96 *pcch = (uintptr_t)pu8 - (uintptr_t)str - 1;97 return hash;98 }99 100 DECLINLINE(uint32_t) sdbmN(const char *str, size_t cchMax, size_t *pcch)101 {102 uint8_t *pu8 = (uint8_t *)str;103 uint32_t hash = 0;104 int c;105 106 while ((c = *pu8++) && cchMax-- > 0)107 hash = c + (hash << 6) + (hash << 16) - hash;108 109 *pcch = (uintptr_t)pu8 - (uintptr_t)str - 1;110 return hash;111 }112 75 113 76 -
trunk/src/VBox/Runtime/include/internal/file.h
r28800 r36597 44 44 int rtFileRecalcAndValidateFlags(uint32_t *pfOpen); 45 45 46 47 /** 48 * Internal interface for getting the RTFILE handle of stdin, stdout or stderr. 49 * 50 * This interface will not be exposed and is purely for internal IPRT use. 51 * 52 * @returns Handle or NIL_RTFILE. 53 * 54 * @param enmStdHandle The standard handle. 55 */ 56 RTFILE rtFileGetStandard(RTHANDLESTD enmStdHandle); 57 46 58 RT_C_DECLS_END 47 59 -
trunk/src/VBox/Runtime/r3/alloc.cpp
r33269 r36597 34 34 #endif 35 35 36 /*#define RTMEMALLOC_USE_TRACKER*/ 37 /* Don't enable the tracker when building the minimal IPRT. */ 38 #ifdef RT_MINI 39 # undef RTMEMALLOC_USE_TRACKER 40 #endif 41 36 42 37 43 /******************************************************************************* … … 73 79 #undef RTMemDupExTag 74 80 81 #undef RTALLOC_USE_EFENCE 82 75 83 76 84 RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW … … 178 186 #else /* !RTALLOC_USE_EFENCE */ 179 187 180 # ifdef RTALLOC_USE_TRACKER 181 void *pv; 182 if (!pvOld) 183 { 184 if (cbNew) 185 pv = RTMemTrackerHdrAlloc(realloc(pvOld, cbNew + sizeof(RTMEMTRACKERHDR)), cbNew, 186 pszTag, RTMEMTRACKERMETHOD_REALLOC); 187 else 188 pv = NULL; 189 } 190 else 191 { 192 RTMemTrackerHdrReallocPrep(pvOld, 0, pszTag, RTMEMTRACKERMETHOD_REALLOC); 193 pv = RTMemTrackerHdrRealloc(realloc(pvOld, cbNew + sizeof(RTMEMTRACKERHDR)), cbNew, pvOld, 194 pszTag, RTMEMTRACKERMETHOD_REALLOC); 195 } 188 # ifdef RTMEMALLOC_USE_TRACKER 189 void *pvRealOld = RTMemTrackerHdrReallocPrep(pvOld, 0, pszTag); 190 size_t cbRealNew = cbNew || !pvRealOld ? cbNew + sizeof(RTMEMTRACKERHDR) : 0; 191 void *pvNew = realloc(pvRealOld, cbRealNew); 192 void *pv = RTMemTrackerHdrReallocDone(pvNew, cbNew, pvOld, pszTag); 196 193 # else 197 194 void *pv = realloc(pvOld, cbNew); … … 213 210 rtR3MemFree("Free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), NULL, 0, NULL); 214 211 #else 215 # ifdef RT ALLOC_USE_TRACKER212 # ifdef RTMEMALLOC_USE_TRACKER 216 213 pv = RTMemTrackerHdrFree(pv, 0, NULL, RTMEMTRACKERMETHOD_FREE); 217 214 # endif -
trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp
r34579 r36597 376 376 377 377 378 RTFILE rtFileGetStandard(RTHANDLESTD enmStdHandle) 379 { 380 int fd; 381 switch (enmStdHandle) 382 { 383 case RTHANDLESTD_INPUT: fd = 0; break; 384 case RTHANDLESTD_OUTPUT: fd = 1; break; 385 case RTHANDLESTD_ERROR: fd = 2; break; 386 break; 387 default: 388 AssertFailedReturn(NIL_RTFILE); 389 } 390 391 struct stat st; 392 int rc = fstat(fd, &st); 393 if (rc == -1) 394 return NIL_RTFILE; 395 return (RTFILE)fd; 396 } 397 398 378 399 RTR3DECL(int) RTFileDelete(const char *pszFilename) 379 400 { -
trunk/src/VBox/Runtime/r3/win/fileio-win.cpp
r36367 r36597 349 349 350 350 351 RTFILE rtFileGetStandard(RTHANDLESTD enmStdHandle) 352 { 353 DWORD dwStdHandle; 354 switch (enmStdHandle) 355 { 356 case RTHANDLESTD_INPUT: dwStdHandle = STD_INPUT_HANDLE; break; 357 case RTHANDLESTD_OUTPUT: dwStdHandle = STD_OUTPUT_HANDLE; break; 358 case RTHANDLESTD_ERROR: dwStdHandle = STD_ERROR_HANDLE; break; 359 break; 360 default: 361 AssertFailedReturn(NIL_RTFILE); 362 } 363 364 HANDLE hHandle = GetStdHandle(dwStdHandle); 365 if (hNative == INVALID_HANDLE_VALUE) 366 return NIL_RTFILE; 367 368 RTFILE hFile = (RTFILE)(uintptr_t)hHandle; 369 AssertReturn((HANDLE)(uintptr_t)hFile == hHandle, NIL_RTFILE); 370 return hFile; 371 } 372 373 351 374 RTR3DECL(int) RTFileSeek(RTFILE File, int64_t offSeek, unsigned uMethod, uint64_t *poffActual) 352 375 { … … 405 428 } 406 429 407 /* 408 * If it's a console, we might bump into out of memory conditions in the 409 * ReadConsole call. 430 /* 431 * If it's a console, we might bump into out of memory conditions in the 432 * ReadConsole call. 410 433 */ 411 434 DWORD dwErr = GetLastError(); … … 450 473 return VINF_SUCCESS; 451 474 } 452 475 453 476 return RTErrConvertFromWin32(dwErr); 454 477 } … … 491 514 } 492 515 493 /* 494 * If it's a console, we might bump into out of memory conditions in the 495 * WriteConsole call. 516 /* 517 * If it's a console, we might bump into out of memory conditions in the 518 * WriteConsole call. 496 519 */ 497 520 DWORD dwErr = GetLastError();
Note:
See TracChangeset
for help on using the changeset viewer.