VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/alloc-r0drv.cpp@ 86694

Last change on this file since 86694 was 83546, checked in by vboxsync, 5 years ago

IPRT: Added RTMemFreeZ, RTMemTmpFreeZ, and RTMemEf* variants. bugref:9698

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.6 KB
Line 
1/* $Id: alloc-r0drv.cpp 83546 2020-04-04 10:46:18Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation, Ring-0 Driver.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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#define RTMEM_NO_WRAP_TO_EF_APIS
32#include <iprt/mem.h>
33#include "internal/iprt.h"
34
35#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
36# include <iprt/asm-amd64-x86.h>
37#endif
38#include <iprt/assert.h>
39#include <iprt/err.h>
40#ifdef RT_MORE_STRICT
41# include <iprt/mp.h>
42#endif
43#include <iprt/param.h>
44#include <iprt/string.h>
45#include <iprt/thread.h>
46#include "r0drv/alloc-r0drv.h"
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52#ifdef RT_STRICT
53# define RTR0MEM_STRICT
54#endif
55
56#ifdef RTR0MEM_STRICT
57# define RTR0MEM_FENCE_EXTRA 16
58#else
59# define RTR0MEM_FENCE_EXTRA 0
60#endif
61
62
63/*********************************************************************************************************************************
64* Global Variables *
65*********************************************************************************************************************************/
66#ifdef RTR0MEM_STRICT
67/** Fence data. */
68static uint8_t const g_abFence[RTR0MEM_FENCE_EXTRA] =
69{
70 0x77, 0x88, 0x66, 0x99, 0x55, 0xaa, 0x44, 0xbb,
71 0x33, 0xcc, 0x22, 0xdd, 0x11, 0xee, 0x00, 0xff
72};
73#endif
74
75
76/**
77 * Wrapper around rtR0MemAllocEx.
78 *
79 * @returns Pointer to the allocated memory block header.
80 * @param cb The number of bytes to allocate (sans header).
81 * @param fFlags The allocation flags.
82 */
83DECLINLINE(PRTMEMHDR) rtR0MemAlloc(size_t cb, uint32_t fFlags)
84{
85 PRTMEMHDR pHdr;
86 int rc = rtR0MemAllocEx(cb, fFlags, &pHdr);
87 if (RT_FAILURE(rc))
88 return NULL;
89 return pHdr;
90}
91
92
93RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
94{
95 return RTMemAllocTag(cb, pszTag);
96}
97RT_EXPORT_SYMBOL(RTMemTmpAllocTag);
98
99
100RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
101{
102 return RTMemAllocZTag(cb, pszTag);
103}
104RT_EXPORT_SYMBOL(RTMemTmpAllocZTag);
105
106
107RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW_DEF
108{
109 return RTMemFree(pv);
110}
111RT_EXPORT_SYMBOL(RTMemTmpFree);
112
113
114RTDECL(void) RTMemTmpFreeZ(void *pv, size_t cb) RT_NO_THROW_DEF
115{
116 return RTMemFreeZ(pv, cb);
117}
118RT_EXPORT_SYMBOL(RTMemTmpFreeZ);
119
120
121
122
123
124RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
125{
126 PRTMEMHDR pHdr;
127 RT_ASSERT_INTS_ON();
128 RT_NOREF_PV(pszTag);
129
130 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, 0);
131 if (pHdr)
132 {
133#ifdef RTR0MEM_STRICT
134 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
135 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
136#endif
137 return pHdr + 1;
138 }
139 return NULL;
140}
141RT_EXPORT_SYMBOL(RTMemAllocTag);
142
143
144RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
145{
146 PRTMEMHDR pHdr;
147 RT_ASSERT_INTS_ON();
148 RT_NOREF_PV(pszTag);
149
150 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_ZEROED);
151 if (pHdr)
152 {
153#ifdef RTR0MEM_STRICT
154 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
155 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
156 return memset(pHdr + 1, 0, cb);
157#else
158 return memset(pHdr + 1, 0, pHdr->cb);
159#endif
160 }
161 return NULL;
162}
163RT_EXPORT_SYMBOL(RTMemAllocZTag);
164
165
166RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
167{
168 size_t cbAligned;
169 if (cbUnaligned >= 16)
170 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
171 else
172 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
173 return RTMemAllocTag(cbAligned, pszTag);
174}
175RT_EXPORT_SYMBOL(RTMemAllocVarTag);
176
177
178RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
179{
180 size_t cbAligned;
181 if (cbUnaligned >= 16)
182 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
183 else
184 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
185 return RTMemAllocZTag(cbAligned, pszTag);
186}
187RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
188
189
190RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
191{
192 PRTMEMHDR pHdrOld;
193
194 /* Free. */
195 if (!cbNew && pvOld)
196 {
197 RTMemFree(pvOld);
198 return NULL;
199 }
200
201 /* Alloc. */
202 if (!pvOld)
203 return RTMemAllocTag(cbNew, pszTag);
204
205 /*
206 * Realloc.
207 */
208 pHdrOld = (PRTMEMHDR)pvOld - 1;
209 RT_ASSERT_PREEMPTIBLE();
210
211 if (pHdrOld->u32Magic == RTMEMHDR_MAGIC)
212 {
213 PRTMEMHDR pHdrNew;
214
215 /* If there is sufficient space in the old block and we don't cause
216 substantial internal fragmentation, reuse the old block. */
217 if ( pHdrOld->cb >= cbNew + RTR0MEM_FENCE_EXTRA
218 && pHdrOld->cb - (cbNew + RTR0MEM_FENCE_EXTRA) <= 128)
219 {
220 pHdrOld->cbReq = (uint32_t)cbNew; Assert(pHdrOld->cbReq == cbNew);
221#ifdef RTR0MEM_STRICT
222 memcpy((uint8_t *)(pHdrOld + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
223#endif
224 return pvOld;
225 }
226
227 /* Allocate a new block and copy over the content. */
228 pHdrNew = rtR0MemAlloc(cbNew + RTR0MEM_FENCE_EXTRA, 0);
229 if (pHdrNew)
230 {
231 size_t cbCopy = RT_MIN(pHdrOld->cb, pHdrNew->cb);
232 memcpy(pHdrNew + 1, pvOld, cbCopy);
233#ifdef RTR0MEM_STRICT
234 pHdrNew->cbReq = (uint32_t)cbNew; Assert(pHdrNew->cbReq == cbNew);
235 memcpy((uint8_t *)(pHdrNew + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
236 AssertReleaseMsg(!memcmp((uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
237 ("pHdr=%p pvOld=%p cbReq=%u cb=%u cbNew=%zu fFlags=%#x\n"
238 "fence: %.*Rhxs\n"
239 "expected: %.*Rhxs\n",
240 pHdrOld, pvOld, pHdrOld->cbReq, pHdrOld->cb, cbNew, pHdrOld->fFlags,
241 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq,
242 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
243#endif
244 rtR0MemFree(pHdrOld);
245 return pHdrNew + 1;
246 }
247 }
248 else
249 AssertMsgFailed(("pHdrOld->u32Magic=%RX32 pvOld=%p cbNew=%#zx\n", pHdrOld->u32Magic, pvOld, cbNew));
250
251 return NULL;
252}
253RT_EXPORT_SYMBOL(RTMemReallocTag);
254
255
256RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF
257{
258 PRTMEMHDR pHdr;
259 RT_ASSERT_INTS_ON();
260
261 if (!pv)
262 return;
263 pHdr = (PRTMEMHDR)pv - 1;
264 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
265 {
266 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
267 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
268#ifdef RTR0MEM_STRICT
269 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
270 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
271 "fence: %.*Rhxs\n"
272 "expected: %.*Rhxs\n",
273 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
274 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
275 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
276#endif
277 rtR0MemFree(pHdr);
278 }
279 else
280 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
281}
282RT_EXPORT_SYMBOL(RTMemFree);
283
284
285RTDECL(void) RTMemFreeZ(void *pv, size_t cb) RT_NO_THROW_DEF
286{
287 PRTMEMHDR pHdr;
288 RT_ASSERT_INTS_ON();
289
290 if (!pv)
291 return;
292 pHdr = (PRTMEMHDR)pv - 1;
293 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
294 {
295 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
296 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
297#ifdef RTR0MEM_STRICT
298 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
299 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
300 "fence: %.*Rhxs\n"
301 "expected: %.*Rhxs\n",
302 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
303 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
304 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
305#endif
306 AssertMsgStmt(cb == pHdr->cbReq, ("cb=%#zx cbReq=%#x\n", cb, pHdr->cbReq), cb = pHdr->cbReq);
307 RT_BZERO(pv, cb);
308 rtR0MemFree(pHdr);
309 }
310 else
311 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
312}
313RT_EXPORT_SYMBOL(RTMemFreeZ);
314
315
316
317
318
319
320RTDECL(void *) RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
321{
322 PRTMEMHDR pHdr;
323#ifdef RT_OS_SOLARIS /** @todo figure out why */
324 RT_ASSERT_INTS_ON();
325#else
326 RT_ASSERT_PREEMPTIBLE();
327#endif
328 RT_NOREF_PV(pszTag);
329
330
331 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_EXEC);
332 if (pHdr)
333 {
334#ifdef RTR0MEM_STRICT
335 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
336 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
337#endif
338 return pHdr + 1;
339 }
340 return NULL;
341}
342RT_EXPORT_SYMBOL(RTMemExecAllocTag);
343
344
345RTDECL(void) RTMemExecFree(void *pv, size_t cb) RT_NO_THROW_DEF
346{
347 PRTMEMHDR pHdr;
348 RT_ASSERT_INTS_ON();
349 RT_NOREF_PV(cb);
350
351 if (!pv)
352 return;
353 pHdr = (PRTMEMHDR)pv - 1;
354 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
355 {
356 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
357#ifdef RTR0MEM_STRICT
358 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
359 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
360 "fence: %.*Rhxs\n"
361 "expected: %.*Rhxs\n",
362 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
363 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
364 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
365#endif
366 rtR0MemFree(pHdr);
367 }
368 else
369 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
370}
371RT_EXPORT_SYMBOL(RTMemExecFree);
372
373
374
375
376RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW_DEF
377{
378 uint32_t fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
379 PRTMEMHDR pHdr;
380 int rc;
381 RT_NOREF_PV(pszTag);
382
383 RT_ASSERT_PREEMPT_CPUID_VAR();
384 if (!(fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC))
385 RT_ASSERT_INTS_ON();
386
387 /*
388 * Fake up some alignment support.
389 */
390 AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
391 if (cb < cbAlignment)
392 cb = cbAlignment;
393
394 /*
395 * Validate and convert flags.
396 */
397 AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK_R0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
398 if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
399 fHdrFlags |= RTMEMHDR_FLAG_ZEROED;
400 if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
401 fHdrFlags |= RTMEMHDR_FLAG_EXEC;
402 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC)
403 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_ALLOC;
404 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
405 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_FREE;
406
407 /*
408 * Do the allocation.
409 */
410 rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
411 if (RT_SUCCESS(rc))
412 {
413 void *pv;
414
415 Assert(pHdr->cbReq == cb + RTR0MEM_FENCE_EXTRA);
416 Assert((pHdr->fFlags & fFlags) == fFlags);
417
418 /*
419 * Calc user pointer, initialize the memory if requested, and if
420 * memory strictness is enable set up the fence.
421 */
422 pv = pHdr + 1;
423 *ppv = pv;
424 if (fFlags & RTMEMHDR_FLAG_ZEROED)
425 memset(pv, 0, pHdr->cb);
426
427#ifdef RTR0MEM_STRICT
428 pHdr->cbReq = (uint32_t)cb;
429 memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
430#endif
431 }
432 else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
433 rc = VERR_NO_EXEC_MEMORY;
434
435 RT_ASSERT_PREEMPT_CPUID();
436 return rc;
437}
438RT_EXPORT_SYMBOL(RTMemAllocExTag);
439
440
441RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW_DEF
442{
443 PRTMEMHDR pHdr;
444 RT_NOREF_PV(cb);
445
446 if (!pv)
447 return;
448
449 AssertPtr(pv);
450 pHdr = (PRTMEMHDR)pv - 1;
451 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
452 {
453 RT_ASSERT_PREEMPT_CPUID_VAR();
454
455 Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
456 if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
457 RT_ASSERT_INTS_ON();
458 AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
459
460#ifdef RTR0MEM_STRICT
461 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
462 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
463 "fence: %.*Rhxs\n"
464 "expected: %.*Rhxs\n",
465 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
466 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
467 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
468#endif
469 rtR0MemFree(pHdr);
470 RT_ASSERT_PREEMPT_CPUID();
471 }
472 else
473 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
474}
475RT_EXPORT_SYMBOL(RTMemFreeEx);
476
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