VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/allocex-r3-posix.cpp@ 46729

Last change on this file since 46729 was 46729, checked in by vboxsync, 12 years ago

RTMEMALLOCEX_FLAGS_32BIT_REACH for linux r3.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: allocex-r3-posix.cpp 46729 2013-06-21 16:58:49Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation, Extended Alloc and Free Functions for Ring-3, posix.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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#include <iprt/assert.h>
36#include <iprt/string.h>
37#include "internal/magics.h"
38
39#include <sys/mman.h>
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/**
46 * Heading for extended memory allocations in ring-3.
47 */
48typedef struct RTMEMHDRR3
49{
50 /** Magic (RTMEMHDR_MAGIC). */
51 uint32_t u32Magic;
52 /** Block flags (RTMEMALLOCEX_FLAGS_*). */
53 uint32_t fFlags;
54 /** The actual size of the block, header not included. */
55 uint32_t cb;
56 /** The requested allocation size. */
57 uint32_t cbReq;
58} RTMEMHDRR3;
59/** Pointer to a ring-3 extended memory header. */
60typedef RTMEMHDRR3 *PRTMEMHDRR3;
61
62
63/**
64 * Allocates memory with upper boundrary.
65 *
66 * @returns Pointer to mmap allocation.
67 * @param cbAlloc Number of bytes to alloacate.
68 * @param fFlags Allocation flags.
69 */
70static void *rtMemAllocExAllocLow(size_t cbAlloc, uint32_t fFlags)
71{
72 int fProt = PROT_READ | PROT_WRITE | (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PROT_EXEC : 0);
73 void *pv = NULL;
74 if (fFlags & RTMEMALLOCEX_FLAGS_16BIT_REACH)
75 {
76 AssertReturn(cbAlloc < _64K, NULL);
77
78 /*
79 * Try with every possible address hint since the possible range is very limited.
80 */
81 uintptr_t uAddr = fFlags & RTMEMALLOCEX_FLAGS_16BIT_REACH ? 0x1000 : _1M;
82 uintptr_t uAddrLast = _64K - uAddr - cbAlloc;
83 while (uAddr <= uAddrLast)
84 {
85 pv = mmap((void *)uAddr, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
86 if (pv && (uintptr_t)pv <= uAddrLast)
87 break;
88 if (pv)
89 {
90 munmap(pv, cbAlloc);
91 pv = NULL;
92 }
93 uAddr += _4K;
94 }
95 }
96 else
97 {
98#if ARCH_BITS == 32
99 pv = mmap(NULL, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
100
101#elif defined(RT_OS_LINUX)
102# ifdef MAP_32BIT
103 pv = mmap(NULL, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
104 if (pv)
105 return pv;
106# endif
107
108 /** @todo On linux, we need an accurate hint. Since I don't need this branch of
109 * the code right now, I won't bother starting to parse
110 * /proc/curproc/mmap right now... */
111 pv = NULL;
112#else
113 pv = NULL;
114#endif
115 }
116 return pv;
117}
118
119
120RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW
121{
122 /*
123 * Validate and adjust input.
124 */
125 AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
126 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
127 AssertReturn(RT_IS_POWER_OF_TWO(cbAlignment), VERR_INVALID_PARAMETER);
128 AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
129
130 if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX)
131 return VERR_NOT_SUPPORTED;
132
133 /*
134 * Align the request.
135 */
136 size_t cbAligned = cb;
137 if (cbAlignment)
138 cbAligned = RT_ALIGN_Z(cb, cbAlignment);
139 else
140 cbAligned = RT_ALIGN_Z(cb, sizeof(uint64_t));
141 AssertMsgReturn(cbAligned >= cb && cbAligned <= ~(size_t)0, ("cbAligned=%#zx cb=%#zx", cbAligned, cb),
142 VERR_INVALID_PARAMETER);
143
144 /*
145 * Allocate the requested memory.
146 */
147 void *pv;
148 if (fFlags & (RTMEMALLOCEX_FLAGS_16BIT_REACH | RTMEMALLOCEX_FLAGS_32BIT_REACH))
149 pv = rtMemAllocExAllocLow(cbAligned + sizeof(RTMEMHDRR3), fFlags);
150 else if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
151 {
152 pv = RTMemExecAlloc(cbAligned + sizeof(RTMEMHDRR3));
153 if ((fFlags & RTMEMALLOCEX_FLAGS_ZEROED) && pv)
154 RT_BZERO(pv, cbAligned + sizeof(RTMEMHDRR3));
155 }
156 else if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
157 pv = RTMemAllocZ(cbAligned + sizeof(RTMEMHDRR3));
158 else
159 pv = RTMemAlloc(cbAligned + sizeof(RTMEMHDRR3));
160 if (!pv)
161 return VERR_NO_MEMORY;
162
163 /*
164 * Fill in the header and return.
165 */
166 PRTMEMHDRR3 pHdr = (PRTMEMHDRR3)pv;
167 pHdr->u32Magic = RTMEMHDR_MAGIC;
168 pHdr->fFlags = fFlags;
169 pHdr->cb = cbAligned;
170 pHdr->cbReq = cb;
171
172 *ppv = pHdr + 1;
173 return VINF_SUCCESS;
174}
175RT_EXPORT_SYMBOL(RTMemAllocExTag);
176
177
178RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW
179{
180 if (!pv)
181 return;
182 AssertPtr(pv);
183
184 PRTMEMHDRR3 pHdr = (PRTMEMHDRR3)pv - 1;
185 AssertMsg(pHdr->u32Magic == RTMEMHDR_MAGIC, ("pHdr->u32Magic=%RX32 pv=%p cb=%#x\n", pHdr->u32Magic, pv, cb));
186 pHdr->u32Magic = RTMEMHDR_MAGIC_DEAD;
187 Assert(pHdr->cbReq == cb);
188
189 if (pHdr->fFlags & (RTMEMALLOCEX_FLAGS_16BIT_REACH | RTMEMALLOCEX_FLAGS_32BIT_REACH))
190 munmap(pHdr, pHdr->cb + sizeof(*pHdr));
191 else if (pHdr->fFlags & RTMEMALLOCEX_FLAGS_EXEC)
192 RTMemExecFree(pHdr, pHdr->cb + sizeof(*pHdr));
193 else
194 RTMemFree(pHdr);
195}
196RT_EXPORT_SYMBOL(RTMemFreeEx);
197
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette