~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/r0drv/alloc-r0drv.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: alloc-r0drv.cpp $ */
 
1
/* $Id: alloc-r0drv.cpp 33269 2010-10-20 15:42:28Z vboxsync $ */
2
2
/** @file
3
3
 * IPRT - Memory Allocation, Ring-0 Driver.
4
4
 */
5
5
 
6
6
/*
7
 
 * Copyright (C) 2006-2007 Oracle Corporation
 
7
 * Copyright (C) 2006-2010 Oracle Corporation
8
8
 *
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>
36
36
#endif
37
37
#include <iprt/assert.h>
 
38
#ifdef RT_MORE_STRICT
 
39
# include <iprt/mp.h>
 
40
#endif
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"
42
45
 
 
46
 
 
47
/*******************************************************************************
 
48
*   Defined Constants And Macros                                               *
 
49
*******************************************************************************/
 
50
#ifdef RT_STRICT
 
51
# define RTR0MEM_STRICT
 
52
#endif
 
53
 
 
54
#ifdef RTR0MEM_STRICT
 
55
# define RTR0MEM_FENCE_EXTRA    16
 
56
#else
 
57
# define RTR0MEM_FENCE_EXTRA    0
 
58
#endif
 
59
 
 
60
 
43
61
#undef RTMemTmpAlloc
 
62
#undef RTMemTmpAllocTag
44
63
#undef RTMemTmpAllocZ
 
64
#undef RTMemTmpAllocZTag
45
65
#undef RTMemTmpFree
46
66
#undef RTMemAlloc
 
67
#undef RTMemAllocTag
47
68
#undef RTMemAllocZ
 
69
#undef RTMemAllocZTag
48
70
#undef RTMemAllocVar
 
71
#undef RTMemAllocVarTag
49
72
#undef RTMemAllocZVar
 
73
#undef RTMemAllocZVarTag
50
74
#undef RTMemRealloc
 
75
#undef RTMemReallocTag
51
76
#undef RTMemFree
52
77
#undef RTMemDup
 
78
#undef RTMemDupTag
53
79
#undef RTMemDupEx
54
 
 
55
 
 
56
 
/*******************************************************************************
57
 
*   Defined Constants And Macros                                               *
58
 
*******************************************************************************/
59
 
#ifdef RT_STRICT
60
 
# define RTR0MEM_STRICT
61
 
#endif
62
 
 
63
 
#ifdef RTR0MEM_STRICT
64
 
# define RTR0MEM_FENCE_EXTRA    16
65
 
#else
66
 
# define RTR0MEM_FENCE_EXTRA    0
67
 
#endif
 
80
#undef RTMemDupExTag
 
81
#undef rtR0MemAllocEx
 
82
#undef rtR0MemAllocExTag
 
83
#undef rtR0MemFreeEx
68
84
 
69
85
 
70
86
/*******************************************************************************
80
96
#endif
81
97
 
82
98
 
83
 
 
84
 
/**
85
 
 * Allocates temporary memory.
86
 
 *
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.
91
 
 *
92
 
 * @returns Pointer to the allocated memory.
93
 
 * @returns NULL on failure.
94
 
 * @param   cb      Size in bytes of the memory block to allocated.
95
 
 */
96
 
RTDECL(void *)  RTMemTmpAlloc(size_t cb) RT_NO_THROW
97
 
{
98
 
    return RTMemAlloc(cb);
99
 
}
100
 
RT_EXPORT_SYMBOL(RTMemTmpAlloc);
101
 
 
102
 
 
103
 
/**
104
 
 * Allocates zero'ed temporary memory.
105
 
 *
106
 
 * Same as RTMemTmpAlloc() but the memory will be zero'ed.
107
 
 *
108
 
 * @returns Pointer to the allocated memory.
109
 
 * @returns NULL on failure.
110
 
 * @param   cb      Size in bytes of the memory block to allocated.
111
 
 */
112
 
RTDECL(void *)  RTMemTmpAllocZ(size_t cb) RT_NO_THROW
113
 
{
114
 
    return RTMemAllocZ(cb);
115
 
}
116
 
RT_EXPORT_SYMBOL(RTMemTmpAllocZ);
117
 
 
118
 
 
119
 
/**
120
 
 * Free temporary memory.
121
 
 *
122
 
 * @param   pv      Pointer to memory block.
123
 
 */
 
99
/**
 
100
 * Wrapper around rtR0MemAllocEx.
 
101
 *
 
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.
 
105
 */
 
106
DECLINLINE(PRTMEMHDR) rtR0MemAlloc(size_t cb, uint32_t fFlags)
 
107
{
 
108
    PRTMEMHDR pHdr;
 
109
    int rc = rtR0MemAllocEx(cb, fFlags, &pHdr);
 
110
    if (RT_FAILURE(rc))
 
111
        return NULL;
 
112
    return pHdr;
 
113
}
 
114
 
 
115
 
 
116
RTDECL(void *)  RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
 
117
{
 
118
    return RTMemAllocTag(cb, pszTag);
 
119
}
 
120
RT_EXPORT_SYMBOL(RTMemTmpAllocTag);
 
121
 
 
122
 
 
123
RTDECL(void *)  RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
 
124
{
 
125
    return RTMemAllocZTag(cb, pszTag);
 
126
}
 
127
RT_EXPORT_SYMBOL(RTMemTmpAllocZTag);
 
128
 
 
129
 
124
130
RTDECL(void)    RTMemTmpFree(void *pv) RT_NO_THROW
125
131
{
126
132
    return RTMemFree(pv);
128
134
RT_EXPORT_SYMBOL(RTMemTmpFree);
129
135
 
130
136
 
131
 
/**
132
 
 * Allocates memory.
133
 
 *
134
 
 * @returns Pointer to the allocated memory.
135
 
 * @returns NULL on failure.
136
 
 * @param   cb      Size in bytes of the memory block to allocated.
137
 
 */
138
 
RTDECL(void *)  RTMemAlloc(size_t cb) RT_NO_THROW
 
137
 
 
138
 
 
139
 
 
140
RTDECL(void *)  RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
139
141
{
140
142
    PRTMEMHDR pHdr;
141
143
    RT_ASSERT_INTS_ON();
151
153
    }
152
154
    return NULL;
153
155
}
154
 
RT_EXPORT_SYMBOL(RTMemAlloc);
155
 
 
156
 
 
157
 
/**
158
 
 * Allocates zero'ed memory.
159
 
 *
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 :-).
163
 
 *
164
 
 * @returns Pointer to the allocated memory.
165
 
 * @returns NULL on failure.
166
 
 * @param   cb      Size in bytes of the memory block to allocated.
167
 
 */
168
 
RTDECL(void *)  RTMemAllocZ(size_t cb) RT_NO_THROW
 
156
RT_EXPORT_SYMBOL(RTMemAllocTag);
 
157
 
 
158
 
 
159
RTDECL(void *)  RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
169
160
{
170
161
    PRTMEMHDR pHdr;
171
162
    RT_ASSERT_INTS_ON();
183
174
    }
184
175
    return NULL;
185
176
}
186
 
RT_EXPORT_SYMBOL(RTMemAllocZ);
187
 
 
188
 
 
189
 
/**
190
 
 * Wrapper around RTMemAlloc for automatically aligning variable sized
191
 
 * allocations so that the various electric fence heaps works correctly.
192
 
 *
193
 
 * @returns See RTMemAlloc.
194
 
 * @param   cbUnaligned         The unaligned size.
195
 
 */
196
 
RTDECL(void *) RTMemAllocVar(size_t cbUnaligned)
197
 
{
198
 
    size_t cbAligned;
199
 
    if (cbUnaligned >= 16)
200
 
        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
201
 
    else
202
 
        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
203
 
    return RTMemAlloc(cbAligned);
204
 
}
205
 
RT_EXPORT_SYMBOL(RTMemAllocVar);
206
 
 
207
 
 
208
 
/**
209
 
 * Wrapper around RTMemAllocZ for automatically aligning variable sized
210
 
 * allocations so that the various electric fence heaps works correctly.
211
 
 *
212
 
 * @returns See RTMemAllocZ.
213
 
 * @param   cbUnaligned         The unaligned size.
214
 
 */
215
 
RTDECL(void *) RTMemAllocZVar(size_t cbUnaligned)
216
 
{
217
 
    size_t cbAligned;
218
 
    if (cbUnaligned >= 16)
219
 
        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
220
 
    else
221
 
        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
222
 
    return RTMemAllocZ(cbAligned);
223
 
}
224
 
RT_EXPORT_SYMBOL(RTMemAllocZVar);
225
 
 
226
 
 
227
 
/**
228
 
 * Reallocates memory.
229
 
 *
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).
234
 
 */
235
 
RTDECL(void *) RTMemRealloc(void *pvOld, size_t cbNew) RT_NO_THROW
 
177
RT_EXPORT_SYMBOL(RTMemAllocZTag);
 
178
 
 
179
 
 
180
RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
 
181
{
 
182
    size_t cbAligned;
 
183
    if (cbUnaligned >= 16)
 
184
        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
 
185
    else
 
186
        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
 
187
    return RTMemAllocTag(cbAligned, pszTag);
 
188
}
 
189
RT_EXPORT_SYMBOL(RTMemAllocVarTag);
 
190
 
 
191
 
 
192
RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
 
193
{
 
194
    size_t cbAligned;
 
195
    if (cbUnaligned >= 16)
 
196
        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
 
197
    else
 
198
        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
 
199
    return RTMemAllocZTag(cbAligned, pszTag);
 
200
}
 
201
RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
 
202
 
 
203
 
 
204
RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW
236
205
{
237
206
    if (!cbNew)
238
207
        RTMemFree(pvOld);
239
208
    else if (!pvOld)
240
 
        return RTMemAlloc(cbNew);
 
209
        return RTMemAllocTag(cbNew, pszTag);
241
210
    else
242
211
    {
243
212
        PRTMEMHDR pHdrOld = (PRTMEMHDR)pvOld - 1;
274
243
 
275
244
    return NULL;
276
245
}
277
 
RT_EXPORT_SYMBOL(RTMemRealloc);
278
 
 
279
 
 
280
 
/**
281
 
 * Free memory related to an virtual machine
282
 
 *
283
 
 * @param   pv      Pointer to memory block.
284
 
 */
 
246
RT_EXPORT_SYMBOL(RTMemReallocTag);
 
247
 
 
248
 
285
249
RTDECL(void) RTMemFree(void *pv) RT_NO_THROW
286
250
{
287
251
    PRTMEMHDR pHdr;
292
256
    pHdr = (PRTMEMHDR)pv - 1;
293
257
    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
294
258
    {
 
259
        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
295
260
        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
296
261
#ifdef RTR0MEM_STRICT
297
262
        AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
310
275
RT_EXPORT_SYMBOL(RTMemFree);
311
276
 
312
277
 
313
 
/**
314
 
 * Allocates memory which may contain code.
315
 
 *
316
 
 * @returns Pointer to the allocated memory.
317
 
 * @returns NULL on failure.
318
 
 * @param   cb      Size in bytes of the memory block to allocate.
319
 
 */
320
 
RTDECL(void *)    RTMemExecAlloc(size_t cb) RT_NO_THROW
 
278
 
 
279
 
 
280
 
 
281
 
 
282
RTDECL(void *)    RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
321
283
{
322
284
    PRTMEMHDR pHdr;
323
285
#ifdef RT_OS_SOLARIS /** @todo figure out why */
337
299
    }
338
300
    return NULL;
339
301
}
340
 
RT_EXPORT_SYMBOL(RTMemExecAlloc);
341
 
 
342
 
 
343
 
/**
344
 
 * Free executable/read/write memory allocated by RTMemExecAlloc().
345
 
 *
346
 
 * @param   pv      Pointer to memory block.
347
 
 */
348
 
RTDECL(void)      RTMemExecFree(void *pv) RT_NO_THROW
 
302
RT_EXPORT_SYMBOL(RTMemExecAllocTag);
 
303
 
 
304
 
 
305
RTDECL(void)      RTMemExecFree(void *pv, size_t cb) RT_NO_THROW
349
306
{
350
307
    PRTMEMHDR pHdr;
351
308
    RT_ASSERT_INTS_ON();
355
312
    pHdr = (PRTMEMHDR)pv - 1;
356
313
    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
357
314
    {
 
315
        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
358
316
#ifdef RTR0MEM_STRICT
359
317
        AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
360
318
                         ("pHdr=%p pv=%p cb=%zu\n"
371
329
}
372
330
RT_EXPORT_SYMBOL(RTMemExecFree);
373
331
 
 
332
 
 
333
 
 
334
 
 
335
RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW
 
336
{
 
337
    uint32_t    fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
 
338
    PRTMEMHDR   pHdr;
 
339
    int         rc;
 
340
 
 
341
    RT_ASSERT_PREEMPT_CPUID_VAR();
 
342
    if (!(fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC))
 
343
        RT_ASSERT_INTS_ON();
 
344
 
 
345
    /*
 
346
     * Fake up some alignment support.
 
347
     */
 
348
    AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
 
349
    if (cb < cbAlignment)
 
350
        cb = cbAlignment;
 
351
 
 
352
    /*
 
353
     * Validate and convert flags.
 
354
     */
 
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;
 
364
 
 
365
    /*
 
366
     * Do the allocation.
 
367
     */
 
368
    rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
 
369
    if (RT_SUCCESS(rc))
 
370
    {
 
371
        void *pv;
 
372
 
 
373
        Assert(pHdr->cbReq  == cb + RTR0MEM_FENCE_EXTRA);
 
374
        Assert((pHdr->fFlags & fFlags) == fFlags);
 
375
 
 
376
        /*
 
377
         * Calc user pointer, initialize the memory if requested, and if
 
378
         * memory strictness is enable set up the fence.
 
379
         */
 
380
        pv = pHdr + 1;
 
381
        *ppv = pv;
 
382
        if (fFlags & RTMEMHDR_FLAG_ZEROED)
 
383
            memset(pv, 0, pHdr->cb);
 
384
 
 
385
#ifdef RTR0MEM_STRICT
 
386
        pHdr->cbReq = (uint32_t)cb;
 
387
        memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
 
388
#endif
 
389
    }
 
390
    else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
 
391
        rc = VERR_NO_EXEC_MEMORY;
 
392
 
 
393
    RT_ASSERT_PREEMPT_CPUID();
 
394
    return rc;
 
395
}
 
396
RT_EXPORT_SYMBOL(RTMemAllocExTag);
 
397
 
 
398
 
 
399
RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW
 
400
{
 
401
    PRTMEMHDR pHdr;
 
402
 
 
403
    if (!pv)
 
404
        return;
 
405
 
 
406
    AssertPtr(pv);
 
407
    pHdr = (PRTMEMHDR)pv - 1;
 
408
    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
 
409
    {
 
410
        RT_ASSERT_PREEMPT_CPUID_VAR();
 
411
 
 
412
        Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
 
413
        if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
 
414
            RT_ASSERT_INTS_ON();
 
415
        AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
 
416
 
 
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"
 
420
                          "fence:    %.*Rhxs\n"
 
421
                          "expected: %.*Rhxs\n",
 
422
                          pHdr, pv, pHdr->cb,
 
423
                          RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cb,
 
424
                          RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
 
425
#endif
 
426
        rtR0MemFree(pHdr);
 
427
        RT_ASSERT_PREEMPT_CPUID();
 
428
    }
 
429
    else
 
430
        AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
 
431
}
 
432
RT_EXPORT_SYMBOL(RTMemFreeEx);
 
433