VirtualBox

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

Last change on this file since 78365 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.3 KB
Line 
1/* $Id: alloc-r0drv.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation, Ring-0 Driver.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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
114
115
116
117RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
118{
119 PRTMEMHDR pHdr;
120 RT_ASSERT_INTS_ON();
121 RT_NOREF_PV(pszTag);
122
123 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, 0);
124 if (pHdr)
125 {
126#ifdef RTR0MEM_STRICT
127 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
128 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
129#endif
130 return pHdr + 1;
131 }
132 return NULL;
133}
134RT_EXPORT_SYMBOL(RTMemAllocTag);
135
136
137RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
138{
139 PRTMEMHDR pHdr;
140 RT_ASSERT_INTS_ON();
141 RT_NOREF_PV(pszTag);
142
143 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_ZEROED);
144 if (pHdr)
145 {
146#ifdef RTR0MEM_STRICT
147 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
148 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
149 return memset(pHdr + 1, 0, cb);
150#else
151 return memset(pHdr + 1, 0, pHdr->cb);
152#endif
153 }
154 return NULL;
155}
156RT_EXPORT_SYMBOL(RTMemAllocZTag);
157
158
159RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
160{
161 size_t cbAligned;
162 if (cbUnaligned >= 16)
163 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
164 else
165 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
166 return RTMemAllocTag(cbAligned, pszTag);
167}
168RT_EXPORT_SYMBOL(RTMemAllocVarTag);
169
170
171RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
172{
173 size_t cbAligned;
174 if (cbUnaligned >= 16)
175 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
176 else
177 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
178 return RTMemAllocZTag(cbAligned, pszTag);
179}
180RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
181
182
183RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
184{
185 PRTMEMHDR pHdrOld;
186
187 /* Free. */
188 if (!cbNew && pvOld)
189 {
190 RTMemFree(pvOld);
191 return NULL;
192 }
193
194 /* Alloc. */
195 if (!pvOld)
196 return RTMemAllocTag(cbNew, pszTag);
197
198 /*
199 * Realloc.
200 */
201 pHdrOld = (PRTMEMHDR)pvOld - 1;
202 RT_ASSERT_PREEMPTIBLE();
203
204 if (pHdrOld->u32Magic == RTMEMHDR_MAGIC)
205 {
206 PRTMEMHDR pHdrNew;
207
208 /* If there is sufficient space in the old block and we don't cause
209 substantial internal fragmentation, reuse the old block. */
210 if ( pHdrOld->cb >= cbNew + RTR0MEM_FENCE_EXTRA
211 && pHdrOld->cb - (cbNew + RTR0MEM_FENCE_EXTRA) <= 128)
212 {
213 pHdrOld->cbReq = (uint32_t)cbNew; Assert(pHdrOld->cbReq == cbNew);
214#ifdef RTR0MEM_STRICT
215 memcpy((uint8_t *)(pHdrOld + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
216#endif
217 return pvOld;
218 }
219
220 /* Allocate a new block and copy over the content. */
221 pHdrNew = rtR0MemAlloc(cbNew + RTR0MEM_FENCE_EXTRA, 0);
222 if (pHdrNew)
223 {
224 size_t cbCopy = RT_MIN(pHdrOld->cb, pHdrNew->cb);
225 memcpy(pHdrNew + 1, pvOld, cbCopy);
226#ifdef RTR0MEM_STRICT
227 pHdrNew->cbReq = (uint32_t)cbNew; Assert(pHdrNew->cbReq == cbNew);
228 memcpy((uint8_t *)(pHdrNew + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
229 AssertReleaseMsg(!memcmp((uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
230 ("pHdr=%p pvOld=%p cbReq=%u cb=%u cbNew=%zu fFlags=%#x\n"
231 "fence: %.*Rhxs\n"
232 "expected: %.*Rhxs\n",
233 pHdrOld, pvOld, pHdrOld->cbReq, pHdrOld->cb, cbNew, pHdrOld->fFlags,
234 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq,
235 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
236#endif
237 rtR0MemFree(pHdrOld);
238 return pHdrNew + 1;
239 }
240 }
241 else
242 AssertMsgFailed(("pHdrOld->u32Magic=%RX32 pvOld=%p cbNew=%#zx\n", pHdrOld->u32Magic, pvOld, cbNew));
243
244 return NULL;
245}
246RT_EXPORT_SYMBOL(RTMemReallocTag);
247
248
249RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF
250{
251 PRTMEMHDR pHdr;
252 RT_ASSERT_INTS_ON();
253
254 if (!pv)
255 return;
256 pHdr = (PRTMEMHDR)pv - 1;
257 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
258 {
259 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
260 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
261#ifdef RTR0MEM_STRICT
262 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
263 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
264 "fence: %.*Rhxs\n"
265 "expected: %.*Rhxs\n",
266 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
267 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
268 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
269#endif
270 rtR0MemFree(pHdr);
271 }
272 else
273 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
274}
275RT_EXPORT_SYMBOL(RTMemFree);
276
277
278
279
280
281
282RTDECL(void *) RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
283{
284 PRTMEMHDR pHdr;
285#ifdef RT_OS_SOLARIS /** @todo figure out why */
286 RT_ASSERT_INTS_ON();
287#else
288 RT_ASSERT_PREEMPTIBLE();
289#endif
290 RT_NOREF_PV(pszTag);
291
292
293 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_EXEC);
294 if (pHdr)
295 {
296#ifdef RTR0MEM_STRICT
297 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
298 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
299#endif
300 return pHdr + 1;
301 }
302 return NULL;
303}
304RT_EXPORT_SYMBOL(RTMemExecAllocTag);
305
306
307RTDECL(void) RTMemExecFree(void *pv, size_t cb) RT_NO_THROW_DEF
308{
309 PRTMEMHDR pHdr;
310 RT_ASSERT_INTS_ON();
311 RT_NOREF_PV(cb);
312
313 if (!pv)
314 return;
315 pHdr = (PRTMEMHDR)pv - 1;
316 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
317 {
318 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
319#ifdef RTR0MEM_STRICT
320 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
321 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
322 "fence: %.*Rhxs\n"
323 "expected: %.*Rhxs\n",
324 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
325 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
326 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
327#endif
328 rtR0MemFree(pHdr);
329 }
330 else
331 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
332}
333RT_EXPORT_SYMBOL(RTMemExecFree);
334
335
336
337
338RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW_DEF
339{
340 uint32_t fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
341 PRTMEMHDR pHdr;
342 int rc;
343 RT_NOREF_PV(pszTag);
344
345 RT_ASSERT_PREEMPT_CPUID_VAR();
346 if (!(fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC))
347 RT_ASSERT_INTS_ON();
348
349 /*
350 * Fake up some alignment support.
351 */
352 AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
353 if (cb < cbAlignment)
354 cb = cbAlignment;
355
356 /*
357 * Validate and convert flags.
358 */
359 AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK_R0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
360 if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
361 fHdrFlags |= RTMEMHDR_FLAG_ZEROED;
362 if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
363 fHdrFlags |= RTMEMHDR_FLAG_EXEC;
364 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC)
365 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_ALLOC;
366 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
367 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_FREE;
368
369 /*
370 * Do the allocation.
371 */
372 rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
373 if (RT_SUCCESS(rc))
374 {
375 void *pv;
376
377 Assert(pHdr->cbReq == cb + RTR0MEM_FENCE_EXTRA);
378 Assert((pHdr->fFlags & fFlags) == fFlags);
379
380 /*
381 * Calc user pointer, initialize the memory if requested, and if
382 * memory strictness is enable set up the fence.
383 */
384 pv = pHdr + 1;
385 *ppv = pv;
386 if (fFlags & RTMEMHDR_FLAG_ZEROED)
387 memset(pv, 0, pHdr->cb);
388
389#ifdef RTR0MEM_STRICT
390 pHdr->cbReq = (uint32_t)cb;
391 memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
392#endif
393 }
394 else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
395 rc = VERR_NO_EXEC_MEMORY;
396
397 RT_ASSERT_PREEMPT_CPUID();
398 return rc;
399}
400RT_EXPORT_SYMBOL(RTMemAllocExTag);
401
402
403RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW_DEF
404{
405 PRTMEMHDR pHdr;
406 RT_NOREF_PV(cb);
407
408 if (!pv)
409 return;
410
411 AssertPtr(pv);
412 pHdr = (PRTMEMHDR)pv - 1;
413 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
414 {
415 RT_ASSERT_PREEMPT_CPUID_VAR();
416
417 Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
418 if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
419 RT_ASSERT_INTS_ON();
420 AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
421
422#ifdef RTR0MEM_STRICT
423 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
424 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
425 "fence: %.*Rhxs\n"
426 "expected: %.*Rhxs\n",
427 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
428 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
429 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
430#endif
431 rtR0MemFree(pHdr);
432 RT_ASSERT_PREEMPT_CPUID();
433 }
434 else
435 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
436}
437RT_EXPORT_SYMBOL(RTMemFreeEx);
438
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