VirtualBox

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

Last change on this file since 37233 was 36982, checked in by vboxsync, 14 years ago

alloc-r0drv.cpp: Fixed bug in RTMemReallocTag when RTR0MEM_STRICT is defined - the case reusing the old block didn't take the fence into account. Fixed fence violation messages (cbReq and cb was mixed so we got the bits after the block instead of the broken fence).

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