VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/alloc-ef.cpp@ 32048

Last change on this file since 32048 was 31157, checked in by vboxsync, 14 years ago

iprt,++: Tag allocation in all builds with a string, defaulting to FILE.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.8 KB
Line 
1/* $Id: alloc-ef.cpp 31157 2010-07-28 03:15:35Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation, electric fence.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "alloc-ef.h"
32#include <iprt/mem.h>
33#include <iprt/log.h>
34#include <iprt/asm.h>
35#include <iprt/thread.h>
36#include <VBox/sup.h>
37#include <iprt/err.h>
38#include <errno.h>
39#include <stdio.h>
40#include <stdlib.h>
41
42#include <iprt/alloc.h>
43#include <iprt/assert.h>
44#include <iprt/param.h>
45#include <iprt/string.h>
46
47
48/*******************************************************************************
49* Global Variables *
50*******************************************************************************/
51#ifdef RTALLOC_EFENCE_TRACE
52/** Spinlock protecting the allthe blocks globals. */
53static volatile uint32_t g_BlocksLock;
54/** Tree tracking the allocations. */
55static AVLPVTREE g_BlocksTree;
56#ifdef RTALLOC_EFENCE_FREE_DELAYED
57/** Tail of the delayed blocks. */
58static volatile PRTMEMBLOCK g_pBlocksDelayHead;
59/** Tail of the delayed blocks. */
60static volatile PRTMEMBLOCK g_pBlocksDelayTail;
61/** Number of bytes in the delay list (includes fences). */
62static volatile size_t g_cbBlocksDelay;
63#endif
64#endif
65/** Array of pointers free watches for. */
66void *gapvRTMemFreeWatch[4] = {NULL, NULL, NULL, NULL};
67/** Enable logging of all freed memory. */
68bool gfRTMemFreeLog = false;
69
70
71/*******************************************************************************
72* Internal Functions *
73*******************************************************************************/
74/**
75 * Complains about something.
76 */
77static void rtmemComplain(const char *pszOp, const char *pszFormat, ...)
78{
79 va_list args;
80 fprintf(stderr, "RTMem error: %s: ", pszOp);
81 va_start(args, pszFormat);
82 vfprintf(stderr, pszFormat, args);
83 va_end(args);
84 RTAssertDoPanic();
85}
86
87/**
88 * Log an event.
89 */
90DECLINLINE(void) rtmemLog(const char *pszOp, const char *pszFormat, ...)
91{
92#if 0
93 va_list args;
94 fprintf(stderr, "RTMem info: %s: ", pszOp);
95 va_start(args, pszFormat);
96 vfprintf(stderr, pszFormat, args);
97 va_end(args);
98#endif
99}
100
101
102#ifdef RTALLOC_EFENCE_TRACE
103
104/**
105 * Aquires the lock.
106 */
107DECLINLINE(void) rtmemBlockLock(void)
108{
109 unsigned c = 0;
110 while (!ASMAtomicCmpXchgU32(&g_BlocksLock, 1, 0))
111 RTThreadSleep(((++c) >> 2) & 31);
112}
113
114
115/**
116 * Releases the lock.
117 */
118DECLINLINE(void) rtmemBlockUnlock(void)
119{
120 Assert(g_BlocksLock == 1);
121 ASMAtomicXchgU32(&g_BlocksLock, 0);
122}
123
124
125/**
126 * Creates a block.
127 */
128DECLINLINE(PRTMEMBLOCK) rtmemBlockCreate(RTMEMTYPE enmType, size_t cbUnaligned, size_t cbAligned,
129 const char *pszTag, void *pvCaller, RT_SRC_POS_DECL)
130{
131 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)malloc(sizeof(*pBlock));
132 if (pBlock)
133 {
134 pBlock->enmType = enmType;
135 pBlock->cbUnaligned = cbUnaligned;
136 pBlock->cbAligned = cbAligned;
137 pBlock->pszTag = pszTag;
138 pBlock->pvCaller = pvCaller;
139 pBlock->iLine = iLine;
140 pBlock->pszFile = pszFile;
141 pBlock->pszFunction = pszFunction;
142 }
143 return pBlock;
144}
145
146
147/**
148 * Frees a block.
149 */
150DECLINLINE(void) rtmemBlockFree(PRTMEMBLOCK pBlock)
151{
152 free(pBlock);
153}
154
155
156/**
157 * Insert a block from the tree.
158 */
159DECLINLINE(void) rtmemBlockInsert(PRTMEMBLOCK pBlock, void *pv)
160{
161 pBlock->Core.Key = pv;
162 rtmemBlockLock();
163 bool fRc = RTAvlPVInsert(&g_BlocksTree, &pBlock->Core);
164 rtmemBlockUnlock();
165 AssertRelease(fRc);
166}
167
168
169/**
170 * Remove a block from the tree and returns it to the caller.
171 */
172DECLINLINE(PRTMEMBLOCK) rtmemBlockRemove(void *pv)
173{
174 rtmemBlockLock();
175 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)RTAvlPVRemove(&g_BlocksTree, pv);
176 rtmemBlockUnlock();
177 return pBlock;
178}
179
180/**
181 * Gets a block.
182 */
183DECLINLINE(PRTMEMBLOCK) rtmemBlockGet(void *pv)
184{
185 rtmemBlockLock();
186 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)RTAvlPVGet(&g_BlocksTree, pv);
187 rtmemBlockUnlock();
188 return pBlock;
189}
190
191/**
192 * Dumps one allocation.
193 */
194static DECLCALLBACK(int) RTMemDumpOne(PAVLPVNODECORE pNode, void *pvUser)
195{
196 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)pNode;
197 fprintf(stderr, "%p %08lx(+%02lx) %p\n",
198 pBlock->Core.Key,
199 (unsigned long)pBlock->cbUnaligned,
200 (unsigned long)(pBlock->cbAligned - pBlock->cbUnaligned),
201 pBlock->pvCaller);
202 return 0;
203}
204
205/**
206 * Dumps the allocated blocks.
207 * This is something which you should call from gdb.
208 */
209extern "C" void RTMemDump(void);
210void RTMemDump(void)
211{
212 fprintf(stderr, "address size(alg) caller\n");
213 RTAvlPVDoWithAll(&g_BlocksTree, true, RTMemDumpOne, NULL);
214}
215
216
217#ifdef RTALLOC_EFENCE_FREE_DELAYED
218/**
219 * Insert a delayed block.
220 */
221DECLINLINE(void) rtmemBlockDelayInsert(PRTMEMBLOCK pBlock)
222{
223 size_t cbBlock = RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
224 pBlock->Core.pRight = NULL;
225 pBlock->Core.pLeft = NULL;
226 rtmemBlockLock();
227 if (g_pBlocksDelayHead)
228 {
229 g_pBlocksDelayHead->Core.pLeft = (PAVLPVNODECORE)pBlock;
230 pBlock->Core.pRight = (PAVLPVNODECORE)g_pBlocksDelayHead;
231 g_pBlocksDelayHead = pBlock;
232 }
233 else
234 {
235 g_pBlocksDelayTail = pBlock;
236 g_pBlocksDelayHead = pBlock;
237 }
238 g_cbBlocksDelay += cbBlock;
239 rtmemBlockUnlock();
240}
241
242/**
243 * Removes a delayed block.
244 */
245DECLINLINE(PRTMEMBLOCK) rtmemBlockDelayRemove(void)
246{
247 PRTMEMBLOCK pBlock = NULL;
248 rtmemBlockLock();
249 if (g_cbBlocksDelay > RTALLOC_EFENCE_FREE_DELAYED)
250 {
251 pBlock = g_pBlocksDelayTail;
252 if (pBlock)
253 {
254 g_pBlocksDelayTail = (PRTMEMBLOCK)pBlock->Core.pLeft;
255 if (pBlock->Core.pLeft)
256 pBlock->Core.pLeft->pRight = NULL;
257 else
258 g_pBlocksDelayHead = NULL;
259 g_cbBlocksDelay -= RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
260 }
261 }
262 rtmemBlockUnlock();
263 return pBlock;
264}
265
266
267#endif /* DELAY */
268
269#endif /* RTALLOC_EFENCE_TRACE */
270
271
272/**
273 * Internal allocator.
274 */
275RTDECL(void *) rtR3MemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cbUnaligned, size_t cbAligned,
276 const char *pszTag, void *pvCaller, RT_SRC_POS_DECL)
277{
278 /*
279 * Sanity.
280 */
281 if ( RT_ALIGN_Z(RTALLOC_EFENCE_SIZE, PAGE_SIZE) != RTALLOC_EFENCE_SIZE
282 && RTALLOC_EFENCE_SIZE <= 0)
283 {
284 rtmemComplain(pszOp, "Invalid E-fence size! %#x\n", RTALLOC_EFENCE_SIZE);
285 return NULL;
286 }
287 if (!cbUnaligned)
288 {
289#if 0
290 rtmemComplain(pszOp, "Request of ZERO bytes allocation!\n");
291 return NULL;
292#else
293 cbAligned = cbUnaligned = 1;
294#endif
295 }
296
297#ifndef RTALLOC_EFENCE_IN_FRONT
298 /* Alignment decreases fence accuracy, but this is at least partially
299 * counteracted by filling and checking the alignment padding. When the
300 * fence is in front then then no extra alignment is needed. */
301 cbAligned = RT_ALIGN_Z(cbAligned, RTALLOC_EFENCE_ALIGNMENT);
302#endif
303
304#ifdef RTALLOC_EFENCE_TRACE
305 /*
306 * Allocate the trace block.
307 */
308 PRTMEMBLOCK pBlock = rtmemBlockCreate(enmType, cbUnaligned, cbAligned, pszTag, pvCaller, RT_SRC_POS_ARGS);
309 if (!pBlock)
310 {
311 rtmemComplain(pszOp, "Failed to allocate trace block!\n");
312 return NULL;
313 }
314#endif
315
316 /*
317 * Allocate a block with page alignment space + the size of the E-fence.
318 */
319 size_t cbBlock = RT_ALIGN_Z(cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
320 void *pvBlock = RTMemPageAlloc(cbBlock);
321 if (pvBlock)
322 {
323 /*
324 * Calc the start of the fence and the user block
325 * and then change the page protection of the fence.
326 */
327#ifdef RTALLOC_EFENCE_IN_FRONT
328 void *pvEFence = pvBlock;
329 void *pv = (char *)pvEFence + RTALLOC_EFENCE_SIZE;
330# ifdef RTALLOC_EFENCE_NOMAN_FILLER
331 memset((char *)pv + cbUnaligned, RTALLOC_EFENCE_NOMAN_FILLER, cbBlock - RTALLOC_EFENCE_SIZE - cbUnaligned);
332# endif
333#else
334 void *pvEFence = (char *)pvBlock + (cbBlock - RTALLOC_EFENCE_SIZE);
335 void *pv = (char *)pvEFence - cbAligned;
336# ifdef RTALLOC_EFENCE_NOMAN_FILLER
337 memset(pvBlock, RTALLOC_EFENCE_NOMAN_FILLER, cbBlock - RTALLOC_EFENCE_SIZE - cbAligned);
338 memset((char *)pv + cbUnaligned, RTALLOC_EFENCE_NOMAN_FILLER, cbAligned - cbUnaligned);
339# endif
340#endif
341
342#ifdef RTALLOC_EFENCE_FENCE_FILLER
343 memset(pvEFence, RTALLOC_EFENCE_FENCE_FILLER, RTALLOC_EFENCE_SIZE);
344#endif
345 int rc = RTMemProtect(pvEFence, RTALLOC_EFENCE_SIZE, RTMEM_PROT_NONE);
346 if (!rc)
347 {
348#ifdef RTALLOC_EFENCE_TRACE
349 rtmemBlockInsert(pBlock, pv);
350#endif
351 if (enmType == RTMEMTYPE_RTMEMALLOCZ)
352 memset(pv, 0, cbUnaligned);
353#ifdef RTALLOC_EFENCE_FILLER
354 else
355 memset(pv, RTALLOC_EFENCE_FILLER, cbUnaligned);
356#endif
357
358 rtmemLog(pszOp, "returns %p (pvBlock=%p cbBlock=%#x pvEFence=%p cbUnaligned=%#x)\n", pv, pvBlock, cbBlock, pvEFence, cbUnaligned);
359 return pv;
360 }
361 rtmemComplain(pszOp, "RTMemProtect failed, pvEFence=%p size %d, rc=%d\n", pvEFence, RTALLOC_EFENCE_SIZE, rc);
362 RTMemPageFree(pvBlock, cbBlock);
363 }
364 else
365 rtmemComplain(pszOp, "Failed to allocated %lu (%lu) bytes.\n", (unsigned long)cbBlock, (unsigned long)cbUnaligned);
366
367#ifdef RTALLOC_EFENCE_TRACE
368 rtmemBlockFree(pBlock);
369#endif
370 return NULL;
371}
372
373
374/**
375 * Internal free.
376 */
377RTDECL(void) rtR3MemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, RT_SRC_POS_DECL)
378{
379 /*
380 * Simple case.
381 */
382 if (!pv)
383 return;
384
385 /*
386 * Check watch points.
387 */
388 for (unsigned i = 0; i < RT_ELEMENTS(gapvRTMemFreeWatch); i++)
389 if (gapvRTMemFreeWatch[i] == pv)
390 RTAssertDoPanic();
391
392#ifdef RTALLOC_EFENCE_TRACE
393 /*
394 * Find the block.
395 */
396 PRTMEMBLOCK pBlock = rtmemBlockRemove(pv);
397 if (pBlock)
398 {
399 if (gfRTMemFreeLog)
400 RTLogPrintf("RTMem %s: pv=%p pvCaller=%p cbUnaligned=%#x\n", pszOp, pv, pvCaller, pBlock->cbUnaligned);
401
402# ifdef RTALLOC_EFENCE_NOMAN_FILLER
403 /*
404 * Check whether the no man's land is untouched.
405 */
406# ifdef RTALLOC_EFENCE_IN_FRONT
407 void *pvWrong = ASMMemIsAll8((char *)pv + pBlock->cbUnaligned,
408 RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbUnaligned,
409 RTALLOC_EFENCE_NOMAN_FILLER);
410# else
411 /* Alignment must match allocation alignment in rtMemAlloc(). */
412 void *pvWrong = ASMMemIsAll8((char *)pv + pBlock->cbUnaligned,
413 pBlock->cbAligned - pBlock->cbUnaligned,
414 RTALLOC_EFENCE_NOMAN_FILLER);
415 if (pvWrong)
416 RTAssertDoPanic();
417 pvWrong = ASMMemIsAll8((void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK),
418 RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbAligned,
419 RTALLOC_EFENCE_NOMAN_FILLER);
420# endif
421 if (pvWrong)
422 RTAssertDoPanic();
423# endif
424
425# ifdef RTALLOC_EFENCE_FREE_FILL
426 /*
427 * Fill the user part of the block.
428 */
429 memset(pv, RTALLOC_EFENCE_FREE_FILL, pBlock->cbUnaligned);
430# endif
431
432# if defined(RTALLOC_EFENCE_FREE_DELAYED) && RTALLOC_EFENCE_FREE_DELAYED > 0
433 /*
434 * We're doing delayed freeing.
435 * That means we'll expand the E-fence to cover the entire block.
436 */
437 int rc = RTMemProtect(pv, pBlock->cbAligned, RTMEM_PROT_NONE);
438 if (RT_SUCCESS(rc))
439 {
440 /*
441 * Insert it into the free list and process pending frees.
442 */
443 rtmemBlockDelayInsert(pBlock);
444 while ((pBlock = rtmemBlockDelayRemove()) != NULL)
445 {
446 pv = pBlock->Core.Key;
447# ifdef RTALLOC_EFENCE_IN_FRONT
448 void *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
449# else
450 void *pvBlock = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
451# endif
452 size_t cbBlock = RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
453 rc = RTMemProtect(pvBlock, cbBlock, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
454 if (RT_SUCCESS(rc))
455 RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
456 else
457 rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvBlock, cbBlock, rc);
458 rtmemBlockFree(pBlock);
459 }
460 }
461 else
462 rtmemComplain(pszOp, "Failed to expand the efence of pv=%p cb=%d, rc=%d.\n", pv, pBlock, rc);
463
464# else /* !RTALLOC_EFENCE_FREE_DELAYED */
465
466 /*
467 * Turn of the E-fence and free it.
468 */
469# ifdef RTALLOC_EFENCE_IN_FRONT
470 void *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
471 void *pvEFence = pvBlock;
472# else
473 void *pvBlock = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
474 void *pvEFence = (char *)pv + pBlock->cb;
475# endif
476 int rc = RTMemProtect(pvEFence, RTALLOC_EFENCE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
477 if (RT_SUCCESS(rc))
478 RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
479 else
480 rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvEFence, RTALLOC_EFENCE_SIZE, rc);
481 rtmemBlockFree(pBlock);
482
483# endif /* !RTALLOC_EFENCE_FREE_DELAYED */
484 }
485 else
486 rtmemComplain(pszOp, "pv=%p not found! Incorrect free!\n", pv);
487
488#else /* !RTALLOC_EFENCE_TRACE */
489
490 /*
491 * We have no size tracking, so we're not doing any freeing because
492 * we cannot if the E-fence is after the block.
493 * Let's just expand the E-fence to the first page of the user bit
494 * since we know that it's around.
495 */
496 int rc = RTMemProtect((void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK), PAGE_SIZE, RTMEM_PROT_NONE);
497 if (RT_FAILURE(rc))
498 rtmemComplain(pszOp, "RTMemProtect(%p, PAGE_SIZE, RTMEM_PROT_NONE) -> %d\n", (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK), rc);
499#endif /* !RTALLOC_EFENCE_TRACE */
500}
501
502
503/**
504 * Internal realloc.
505 */
506RTDECL(void *) rtR3MemRealloc(const char *pszOp, RTMEMTYPE enmType, void *pvOld, size_t cbNew,
507 const char *pszTag, void *pvCaller, RT_SRC_POS_DECL)
508{
509 /*
510 * Allocate new and copy.
511 */
512 if (!pvOld)
513 return rtR3MemAlloc(pszOp, enmType, cbNew, cbNew, pszTag, pvCaller, RT_SRC_POS_ARGS);
514 if (!cbNew)
515 {
516 rtR3MemFree(pszOp, RTMEMTYPE_RTMEMREALLOC, pvOld, pvCaller, RT_SRC_POS_ARGS);
517 return NULL;
518 }
519
520#ifdef RTALLOC_EFENCE_TRACE
521
522 /*
523 * Get the block, allocate the new, copy the data, free the old one.
524 */
525 PRTMEMBLOCK pBlock = rtmemBlockGet(pvOld);
526 if (pBlock)
527 {
528 void *pvRet = rtR3MemAlloc(pszOp, enmType, cbNew, cbNew, pszTag, pvCaller, RT_SRC_POS_ARGS);
529 if (pvRet)
530 {
531 memcpy(pvRet, pvOld, RT_MIN(cbNew, pBlock->cbUnaligned));
532 rtR3MemFree(pszOp, RTMEMTYPE_RTMEMREALLOC, pvOld, pvCaller, RT_SRC_POS_ARGS);
533 }
534 return pvRet;
535 }
536 else
537 rtmemComplain(pszOp, "pvOld=%p was not found!\n", pvOld);
538 return NULL;
539
540#else /* !RTALLOC_EFENCE_TRACE */
541
542 rtmemComplain(pszOp, "Not supported if RTALLOC_EFENCE_TRACE isn't defined!\n");
543 return NULL;
544
545#endif /* !RTALLOC_EFENCE_TRACE */
546}
547
548
549
550
551RTDECL(void *) RTMemEfTmpAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
552{
553 return rtR3MemAlloc("TmpAlloc", RTMEMTYPE_RTMEMALLOC, cb, cb, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
554}
555
556
557RTDECL(void *) RTMemEfTmpAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
558{
559 return rtR3MemAlloc("TmpAlloc", RTMEMTYPE_RTMEMALLOCZ, cb, cb, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
560}
561
562
563RTDECL(void) RTMemEfTmpFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW
564{
565 if (pv)
566 rtR3MemFree("Free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), RT_SRC_POS_ARGS);
567}
568
569
570RTDECL(void *) RTMemEfAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
571{
572 return rtR3MemAlloc("Alloc", RTMEMTYPE_RTMEMALLOC, cb, cb, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
573}
574
575
576RTDECL(void *) RTMemEfAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
577{
578 return rtR3MemAlloc("AllocZ", RTMEMTYPE_RTMEMALLOCZ, cb, cb, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
579}
580
581
582RTDECL(void *) RTMemEfAllocVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
583{
584 size_t cbAligned;
585 if (cbUnaligned >= 16)
586 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
587 else
588 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
589 return rtR3MemAlloc("Alloc", RTMEMTYPE_RTMEMALLOC, cbUnaligned, cbAligned, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
590}
591
592
593RTDECL(void *) RTMemEfAllocZVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
594{
595 size_t cbAligned;
596 if (cbUnaligned >= 16)
597 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
598 else
599 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
600 return rtR3MemAlloc("AllocZ", RTMEMTYPE_RTMEMALLOCZ, cbUnaligned, cbAligned, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
601}
602
603
604RTDECL(void *) RTMemEfRealloc(void *pvOld, size_t cbNew, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
605{
606 return rtR3MemRealloc("Realloc", RTMEMTYPE_RTMEMREALLOC, pvOld, cbNew, pszTag, ASMReturnAddress(), RT_SRC_POS_ARGS);
607}
608
609
610RTDECL(void) RTMemEfFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW
611{
612 if (pv)
613 rtR3MemFree("Free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), RT_SRC_POS_ARGS);
614}
615
616
617RTDECL(void *) RTMemEfDup(const void *pvSrc, size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
618{
619 void *pvDst = RTMemEfAlloc(cb, pszTag, RT_SRC_POS_ARGS);
620 if (pvDst)
621 memcpy(pvDst, pvSrc, cb);
622 return pvDst;
623}
624
625
626RTDECL(void *) RTMemEfDupEx(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW
627{
628 void *pvDst = RTMemEfAlloc(cbSrc + cbExtra, pszTag, RT_SRC_POS_ARGS);
629 if (pvDst)
630 {
631 memcpy(pvDst, pvSrc, cbSrc);
632 memset((uint8_t *)pvDst + cbSrc, 0, cbExtra);
633 }
634 return pvDst;
635}
636
637
638
639
640/*
641 *
642 * The NP (no position) versions.
643 *
644 */
645
646
647
648RTDECL(void *) RTMemEfTmpAllocNP(size_t cb, const char *pszTag) RT_NO_THROW
649{
650 return rtR3MemAlloc("TmpAlloc", RTMEMTYPE_RTMEMALLOC, cb, cb, pszTag, ASMReturnAddress(), NULL, 0, NULL);
651}
652
653
654RTDECL(void *) RTMemEfTmpAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW
655{
656 return rtR3MemAlloc("TmpAllocZ", RTMEMTYPE_RTMEMALLOCZ, cb, cb, pszTag, ASMReturnAddress(), NULL, 0, NULL);
657}
658
659
660RTDECL(void) RTMemEfTmpFreeNP(void *pv) RT_NO_THROW
661{
662 if (pv)
663 rtR3MemFree("Free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), NULL, 0, NULL);
664}
665
666
667RTDECL(void *) RTMemEfAllocNP(size_t cb, const char *pszTag) RT_NO_THROW
668{
669 return rtR3MemAlloc("Alloc", RTMEMTYPE_RTMEMALLOC, cb, cb, pszTag, ASMReturnAddress(), NULL, 0, NULL);
670}
671
672
673RTDECL(void *) RTMemEfAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW
674{
675 return rtR3MemAlloc("AllocZ", RTMEMTYPE_RTMEMALLOCZ, cb, cb, pszTag, ASMReturnAddress(), NULL, 0, NULL);
676}
677
678
679RTDECL(void *) RTMemEfAllocVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW
680{
681 size_t cbAligned;
682 if (cbUnaligned >= 16)
683 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
684 else
685 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
686 return rtR3MemAlloc("Alloc", RTMEMTYPE_RTMEMALLOC, cbUnaligned, cbAligned, pszTag, ASMReturnAddress(), NULL, 0, NULL);
687}
688
689
690RTDECL(void *) RTMemEfAllocZVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW
691{
692 size_t cbAligned;
693 if (cbUnaligned >= 16)
694 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
695 else
696 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
697 return rtR3MemAlloc("AllocZ", RTMEMTYPE_RTMEMALLOCZ, cbUnaligned, cbAligned, pszTag, ASMReturnAddress(), NULL, 0, NULL);
698}
699
700
701RTDECL(void *) RTMemEfReallocNP(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW
702{
703 return rtR3MemRealloc("Realloc", RTMEMTYPE_RTMEMREALLOC, pvOld, cbNew, pszTag, ASMReturnAddress(), NULL, 0, NULL);
704}
705
706
707RTDECL(void) RTMemEfFreeNP(void *pv) RT_NO_THROW
708{
709 if (pv)
710 rtR3MemFree("Free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), NULL, 0, NULL);
711}
712
713
714RTDECL(void *) RTMemEfDupNP(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW
715{
716 void *pvDst = RTMemEfAlloc(cb, pszTag, NULL, 0, NULL);
717 if (pvDst)
718 memcpy(pvDst, pvSrc, cb);
719 return pvDst;
720}
721
722
723RTDECL(void *) RTMemEfDupExNP(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW
724{
725 void *pvDst = RTMemEfAlloc(cbSrc + cbExtra, pszTag, NULL, 0, NULL);
726 if (pvDst)
727 {
728 memcpy(pvDst, pvSrc, cbSrc);
729 memset((uint8_t *)pvDst + cbSrc, 0, cbExtra);
730 }
731 return pvDst;
732}
733
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette