VirtualBox

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

Last change on this file since 97907 was 97907, checked in by vboxsync, 2 years ago

IPRT: Removed the RTMemExecAlloc interface.

  • 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 97907 2022-12-29 18:33:45Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation, Ring-0 Driver.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define RTMEM_NO_WRAP_TO_EF_APIS
42#include <iprt/mem.h>
43#include "internal/iprt.h"
44
45#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
46# include <iprt/asm-amd64-x86.h>
47#endif
48#include <iprt/assert.h>
49#include <iprt/err.h>
50#ifdef RT_MORE_STRICT
51# include <iprt/mp.h>
52#endif
53#include <iprt/param.h>
54#include <iprt/string.h>
55#include <iprt/thread.h>
56#include "r0drv/alloc-r0drv.h"
57
58
59/*********************************************************************************************************************************
60* Defined Constants And Macros *
61*********************************************************************************************************************************/
62#ifdef RT_STRICT
63# define RTR0MEM_STRICT
64#endif
65
66#ifdef RTR0MEM_STRICT
67# define RTR0MEM_FENCE_EXTRA 16
68#else
69# define RTR0MEM_FENCE_EXTRA 0
70#endif
71
72
73/*********************************************************************************************************************************
74* Global Variables *
75*********************************************************************************************************************************/
76#ifdef RTR0MEM_STRICT
77/** Fence data. */
78static uint8_t const g_abFence[RTR0MEM_FENCE_EXTRA] =
79{
80 0x77, 0x88, 0x66, 0x99, 0x55, 0xaa, 0x44, 0xbb,
81 0x33, 0xcc, 0x22, 0xdd, 0x11, 0xee, 0x00, 0xff
82};
83#endif
84
85
86/**
87 * Wrapper around rtR0MemAllocEx.
88 *
89 * @returns Pointer to the allocated memory block header.
90 * @param cb The number of bytes to allocate (sans header).
91 * @param fFlags The allocation flags.
92 */
93DECLINLINE(PRTMEMHDR) rtR0MemAlloc(size_t cb, uint32_t fFlags)
94{
95 PRTMEMHDR pHdr;
96 int rc = rtR0MemAllocEx(cb, fFlags, &pHdr);
97 if (RT_FAILURE(rc))
98 return NULL;
99 return pHdr;
100}
101
102
103RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
104{
105 return RTMemAllocTag(cb, pszTag);
106}
107RT_EXPORT_SYMBOL(RTMemTmpAllocTag);
108
109
110RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
111{
112 return RTMemAllocZTag(cb, pszTag);
113}
114RT_EXPORT_SYMBOL(RTMemTmpAllocZTag);
115
116
117RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW_DEF
118{
119 return RTMemFree(pv);
120}
121RT_EXPORT_SYMBOL(RTMemTmpFree);
122
123
124RTDECL(void) RTMemTmpFreeZ(void *pv, size_t cb) RT_NO_THROW_DEF
125{
126 return RTMemFreeZ(pv, cb);
127}
128RT_EXPORT_SYMBOL(RTMemTmpFreeZ);
129
130
131
132
133
134RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
135{
136 PRTMEMHDR pHdr;
137 RT_ASSERT_INTS_ON();
138 RT_NOREF_PV(pszTag);
139
140 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, 0);
141 if (pHdr)
142 {
143#ifdef RTR0MEM_STRICT
144 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
145 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
146#endif
147 return pHdr + 1;
148 }
149 return NULL;
150}
151RT_EXPORT_SYMBOL(RTMemAllocTag);
152
153
154RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
155{
156 PRTMEMHDR pHdr;
157 RT_ASSERT_INTS_ON();
158 RT_NOREF_PV(pszTag);
159
160 pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_ZEROED);
161 if (pHdr)
162 {
163#ifdef RTR0MEM_STRICT
164 pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
165 memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
166 return memset(pHdr + 1, 0, cb);
167#else
168 return memset(pHdr + 1, 0, pHdr->cb);
169#endif
170 }
171 return NULL;
172}
173RT_EXPORT_SYMBOL(RTMemAllocZTag);
174
175
176RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
177{
178 size_t cbAligned;
179 if (cbUnaligned >= 16)
180 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
181 else
182 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
183 return RTMemAllocTag(cbAligned, pszTag);
184}
185RT_EXPORT_SYMBOL(RTMemAllocVarTag);
186
187
188RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
189{
190 size_t cbAligned;
191 if (cbUnaligned >= 16)
192 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
193 else
194 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
195 return RTMemAllocZTag(cbAligned, pszTag);
196}
197RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
198
199
200RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
201{
202 PRTMEMHDR pHdrOld;
203
204 /* Free. */
205 if (!cbNew && pvOld)
206 {
207 RTMemFree(pvOld);
208 return NULL;
209 }
210
211 /* Alloc. */
212 if (!pvOld)
213 return RTMemAllocTag(cbNew, pszTag);
214
215 /*
216 * Realloc.
217 */
218 pHdrOld = (PRTMEMHDR)pvOld - 1;
219 RT_ASSERT_PREEMPTIBLE();
220
221 if (pHdrOld->u32Magic == RTMEMHDR_MAGIC)
222 {
223 PRTMEMHDR pHdrNew;
224
225 /* If there is sufficient space in the old block and we don't cause
226 substantial internal fragmentation, reuse the old block. */
227 if ( pHdrOld->cb >= cbNew + RTR0MEM_FENCE_EXTRA
228 && pHdrOld->cb - (cbNew + RTR0MEM_FENCE_EXTRA) <= 128)
229 {
230 pHdrOld->cbReq = (uint32_t)cbNew; Assert(pHdrOld->cbReq == cbNew);
231#ifdef RTR0MEM_STRICT
232 memcpy((uint8_t *)(pHdrOld + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
233#endif
234 return pvOld;
235 }
236
237 /* Allocate a new block and copy over the content. */
238 pHdrNew = rtR0MemAlloc(cbNew + RTR0MEM_FENCE_EXTRA, 0);
239 if (pHdrNew)
240 {
241 size_t cbCopy = RT_MIN(pHdrOld->cb, pHdrNew->cb);
242 memcpy(pHdrNew + 1, pvOld, cbCopy);
243#ifdef RTR0MEM_STRICT
244 pHdrNew->cbReq = (uint32_t)cbNew; Assert(pHdrNew->cbReq == cbNew);
245 memcpy((uint8_t *)(pHdrNew + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
246 AssertReleaseMsg(!memcmp((uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
247 ("pHdr=%p pvOld=%p cbReq=%u cb=%u cbNew=%zu fFlags=%#x\n"
248 "fence: %.*Rhxs\n"
249 "expected: %.*Rhxs\n",
250 pHdrOld, pvOld, pHdrOld->cbReq, pHdrOld->cb, cbNew, pHdrOld->fFlags,
251 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq,
252 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
253#endif
254 rtR0MemFree(pHdrOld);
255 return pHdrNew + 1;
256 }
257 }
258 else
259 AssertMsgFailed(("pHdrOld->u32Magic=%RX32 pvOld=%p cbNew=%#zx\n", pHdrOld->u32Magic, pvOld, cbNew));
260
261 return NULL;
262}
263RT_EXPORT_SYMBOL(RTMemReallocTag);
264
265
266RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF
267{
268 PRTMEMHDR pHdr;
269 RT_ASSERT_INTS_ON();
270
271 if (!pv)
272 return;
273 pHdr = (PRTMEMHDR)pv - 1;
274 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
275 {
276 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
277 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
278#ifdef RTR0MEM_STRICT
279 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
280 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
281 "fence: %.*Rhxs\n"
282 "expected: %.*Rhxs\n",
283 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
284 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
285 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
286#endif
287 rtR0MemFree(pHdr);
288 }
289 else
290 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
291}
292RT_EXPORT_SYMBOL(RTMemFree);
293
294
295RTDECL(void) RTMemFreeZ(void *pv, size_t cb) RT_NO_THROW_DEF
296{
297 PRTMEMHDR pHdr;
298 RT_ASSERT_INTS_ON();
299
300 if (!pv)
301 return;
302 pHdr = (PRTMEMHDR)pv - 1;
303 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
304 {
305 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
306 Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
307#ifdef RTR0MEM_STRICT
308 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
309 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
310 "fence: %.*Rhxs\n"
311 "expected: %.*Rhxs\n",
312 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
313 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
314 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
315#endif
316 AssertMsgStmt(cb == pHdr->cbReq, ("cb=%#zx cbReq=%#x\n", cb, pHdr->cbReq), cb = pHdr->cbReq);
317 RT_BZERO(pv, cb);
318 rtR0MemFree(pHdr);
319 }
320 else
321 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
322}
323RT_EXPORT_SYMBOL(RTMemFreeZ);
324
325
326RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW_DEF
327{
328 uint32_t fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
329 PRTMEMHDR pHdr;
330 int rc;
331 RT_NOREF_PV(pszTag);
332
333 RT_ASSERT_PREEMPT_CPUID_VAR();
334 if (!(fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC))
335 RT_ASSERT_INTS_ON();
336
337 /*
338 * Fake up some alignment support.
339 */
340 AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
341 if (cb < cbAlignment)
342 cb = cbAlignment;
343
344 /*
345 * Validate and convert flags.
346 */
347 AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK_R0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
348 if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
349 fHdrFlags |= RTMEMHDR_FLAG_ZEROED;
350 if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
351 fHdrFlags |= RTMEMHDR_FLAG_EXEC;
352 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC)
353 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_ALLOC;
354 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
355 fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_FREE;
356
357 /*
358 * Do the allocation.
359 */
360 rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
361 if (RT_SUCCESS(rc))
362 {
363 void *pv;
364
365 Assert(pHdr->cbReq == cb + RTR0MEM_FENCE_EXTRA);
366 Assert((pHdr->fFlags & fFlags) == fFlags);
367
368 /*
369 * Calc user pointer, initialize the memory if requested, and if
370 * memory strictness is enable set up the fence.
371 */
372 pv = pHdr + 1;
373 *ppv = pv;
374 if (fFlags & RTMEMHDR_FLAG_ZEROED)
375 memset(pv, 0, pHdr->cb);
376
377#ifdef RTR0MEM_STRICT
378 pHdr->cbReq = (uint32_t)cb;
379 memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
380#endif
381 }
382 else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
383 rc = VERR_NO_EXEC_MEMORY;
384
385 RT_ASSERT_PREEMPT_CPUID();
386 return rc;
387}
388RT_EXPORT_SYMBOL(RTMemAllocExTag);
389
390
391RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW_DEF
392{
393 PRTMEMHDR pHdr;
394 RT_NOREF_PV(cb);
395
396 if (!pv)
397 return;
398
399 AssertPtr(pv);
400 pHdr = (PRTMEMHDR)pv - 1;
401 if (pHdr->u32Magic == RTMEMHDR_MAGIC)
402 {
403 RT_ASSERT_PREEMPT_CPUID_VAR();
404
405 Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
406 if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
407 RT_ASSERT_INTS_ON();
408 AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
409
410#ifdef RTR0MEM_STRICT
411 AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
412 ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
413 "fence: %.*Rhxs\n"
414 "expected: %.*Rhxs\n",
415 pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
416 RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
417 RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
418#endif
419 rtR0MemFree(pHdr);
420 RT_ASSERT_PREEMPT_CPUID();
421 }
422 else
423 AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
424}
425RT_EXPORT_SYMBOL(RTMemFreeEx);
426
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