1
/* $Id: alloc-r0drv.cpp $ */
1
/* $Id: alloc-r0drv.cpp 33269 2010-10-20 15:42:28Z vboxsync $ */
3
3
* IPRT - Memory Allocation, Ring-0 Driver.
7
* Copyright (C) 2006-2007 Oracle Corporation
7
* Copyright (C) 2006-2010 Oracle Corporation
9
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
10
* available from http://www.virtualbox.org. This file is free software;
35
35
# include <iprt/asm-amd64-x86.h>
37
37
#include <iprt/assert.h>
38
41
#include <iprt/param.h>
39
42
#include <iprt/string.h>
40
43
#include <iprt/thread.h>
41
44
#include "r0drv/alloc-r0drv.h"
47
/*******************************************************************************
48
* Defined Constants And Macros *
49
*******************************************************************************/
51
# define RTR0MEM_STRICT
55
# define RTR0MEM_FENCE_EXTRA 16
57
# define RTR0MEM_FENCE_EXTRA 0
43
61
#undef RTMemTmpAlloc
62
#undef RTMemTmpAllocTag
44
63
#undef RTMemTmpAllocZ
64
#undef RTMemTmpAllocZTag
45
65
#undef RTMemTmpFree
48
70
#undef RTMemAllocVar
71
#undef RTMemAllocVarTag
49
72
#undef RTMemAllocZVar
73
#undef RTMemAllocZVarTag
50
74
#undef RTMemRealloc
75
#undef RTMemReallocTag
56
/*******************************************************************************
57
* Defined Constants And Macros *
58
*******************************************************************************/
60
# define RTR0MEM_STRICT
64
# define RTR0MEM_FENCE_EXTRA 16
66
# define RTR0MEM_FENCE_EXTRA 0
82
#undef rtR0MemAllocExTag
70
86
/*******************************************************************************
85
* Allocates temporary memory.
87
* Temporary memory blocks are used for not too large memory blocks which
88
* are believed not to stick around for too long. Using this API instead
89
* of RTMemAlloc() not only gives the heap manager room for optimization
90
* but makes the code easier to read.
92
* @returns Pointer to the allocated memory.
93
* @returns NULL on failure.
94
* @param cb Size in bytes of the memory block to allocated.
96
RTDECL(void *) RTMemTmpAlloc(size_t cb) RT_NO_THROW
98
return RTMemAlloc(cb);
100
RT_EXPORT_SYMBOL(RTMemTmpAlloc);
104
* Allocates zero'ed temporary memory.
106
* Same as RTMemTmpAlloc() but the memory will be zero'ed.
108
* @returns Pointer to the allocated memory.
109
* @returns NULL on failure.
110
* @param cb Size in bytes of the memory block to allocated.
112
RTDECL(void *) RTMemTmpAllocZ(size_t cb) RT_NO_THROW
114
return RTMemAllocZ(cb);
116
RT_EXPORT_SYMBOL(RTMemTmpAllocZ);
120
* Free temporary memory.
122
* @param pv Pointer to memory block.
100
* Wrapper around rtR0MemAllocEx.
102
* @returns Pointer to the allocated memory block header.
103
* @param cb The number of bytes to allocate (sans header).
104
* @param fFlags The allocation flags.
106
DECLINLINE(PRTMEMHDR) rtR0MemAlloc(size_t cb, uint32_t fFlags)
109
int rc = rtR0MemAllocEx(cb, fFlags, &pHdr);
116
RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
118
return RTMemAllocTag(cb, pszTag);
120
RT_EXPORT_SYMBOL(RTMemTmpAllocTag);
123
RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
125
return RTMemAllocZTag(cb, pszTag);
127
RT_EXPORT_SYMBOL(RTMemTmpAllocZTag);
124
130
RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW
126
132
return RTMemFree(pv);
154
RT_EXPORT_SYMBOL(RTMemAlloc);
158
* Allocates zero'ed memory.
160
* Instead of memset(pv, 0, sizeof()) use this when you want zero'ed
161
* memory. This keeps the code smaller and the heap can skip the memset
162
* in about 0.42% of calls :-).
164
* @returns Pointer to the allocated memory.
165
* @returns NULL on failure.
166
* @param cb Size in bytes of the memory block to allocated.
168
RTDECL(void *) RTMemAllocZ(size_t cb) RT_NO_THROW
156
RT_EXPORT_SYMBOL(RTMemAllocTag);
159
RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
171
162
RT_ASSERT_INTS_ON();
186
RT_EXPORT_SYMBOL(RTMemAllocZ);
190
* Wrapper around RTMemAlloc for automatically aligning variable sized
191
* allocations so that the various electric fence heaps works correctly.
193
* @returns See RTMemAlloc.
194
* @param cbUnaligned The unaligned size.
196
RTDECL(void *) RTMemAllocVar(size_t cbUnaligned)
199
if (cbUnaligned >= 16)
200
cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
202
cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
203
return RTMemAlloc(cbAligned);
205
RT_EXPORT_SYMBOL(RTMemAllocVar);
209
* Wrapper around RTMemAllocZ for automatically aligning variable sized
210
* allocations so that the various electric fence heaps works correctly.
212
* @returns See RTMemAllocZ.
213
* @param cbUnaligned The unaligned size.
215
RTDECL(void *) RTMemAllocZVar(size_t cbUnaligned)
218
if (cbUnaligned >= 16)
219
cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
221
cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
222
return RTMemAllocZ(cbAligned);
224
RT_EXPORT_SYMBOL(RTMemAllocZVar);
228
* Reallocates memory.
230
* @returns Pointer to the allocated memory.
231
* @returns NULL on failure.
232
* @param pvOld The memory block to reallocate.
233
* @param cbNew The new block size (in bytes).
235
RTDECL(void *) RTMemRealloc(void *pvOld, size_t cbNew) RT_NO_THROW
177
RT_EXPORT_SYMBOL(RTMemAllocZTag);
180
RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
183
if (cbUnaligned >= 16)
184
cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
186
cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
187
return RTMemAllocTag(cbAligned, pszTag);
189
RT_EXPORT_SYMBOL(RTMemAllocVarTag);
192
RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
195
if (cbUnaligned >= 16)
196
cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
198
cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
199
return RTMemAllocZTag(cbAligned, pszTag);
201
RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
204
RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW
238
207
RTMemFree(pvOld);
240
return RTMemAlloc(cbNew);
209
return RTMemAllocTag(cbNew, pszTag);
243
212
PRTMEMHDR pHdrOld = (PRTMEMHDR)pvOld - 1;
310
275
RT_EXPORT_SYMBOL(RTMemFree);
314
* Allocates memory which may contain code.
316
* @returns Pointer to the allocated memory.
317
* @returns NULL on failure.
318
* @param cb Size in bytes of the memory block to allocate.
320
RTDECL(void *) RTMemExecAlloc(size_t cb) RT_NO_THROW
282
RTDECL(void *) RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
323
285
#ifdef RT_OS_SOLARIS /** @todo figure out why */
372
330
RT_EXPORT_SYMBOL(RTMemExecFree);
335
RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW
337
uint32_t fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
341
RT_ASSERT_PREEMPT_CPUID_VAR();
342
if (!(fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC))
346
* Fake up some alignment support.
348
AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
349
if (cb < cbAlignment)
353
* Validate and convert flags.
355
AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
356
if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
357
fHdrFlags |= RTMEMHDR_FLAG_ZEROED;
358
if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
359
fHdrFlags |= RTMEMHDR_FLAG_EXEC;
360
if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC)
361
fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_ALLOC;
362
if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
363
fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_FREE;
368
rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
373
Assert(pHdr->cbReq == cb + RTR0MEM_FENCE_EXTRA);
374
Assert((pHdr->fFlags & fFlags) == fFlags);
377
* Calc user pointer, initialize the memory if requested, and if
378
* memory strictness is enable set up the fence.
382
if (fFlags & RTMEMHDR_FLAG_ZEROED)
383
memset(pv, 0, pHdr->cb);
385
#ifdef RTR0MEM_STRICT
386
pHdr->cbReq = (uint32_t)cb;
387
memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
390
else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
391
rc = VERR_NO_EXEC_MEMORY;
393
RT_ASSERT_PREEMPT_CPUID();
396
RT_EXPORT_SYMBOL(RTMemAllocExTag);
399
RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW
407
pHdr = (PRTMEMHDR)pv - 1;
408
if (pHdr->u32Magic == RTMEMHDR_MAGIC)
410
RT_ASSERT_PREEMPT_CPUID_VAR();
412
Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
413
if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
415
AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
417
#ifdef RTR0MEM_STRICT
418
AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
419
("pHdr=%p pv=%p cb=%zu\n"
421
"expected: %.*Rhxs\n",
423
RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cb,
424
RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
427
RT_ASSERT_PREEMPT_CPUID();
430
AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
432
RT_EXPORT_SYMBOL(RTMemFreeEx);