VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/alloc-posix.cpp@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1/* $Id: alloc-posix.cpp 1 1970-01-01 00:00:00Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime - Memory Allocation, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/alloc.h>
27#include <iprt/assert.h>
28#include <iprt/param.h>
29#include <iprt/err.h>
30#include <iprt/string.h>
31
32#include <stdlib.h>
33#include <malloc.h>
34#include <errno.h>
35#include <sys/mman.h>
36
37
38#ifdef IN_RING3
39
40/**
41 * Allocates memory which may contain code.
42 *
43 * @returns Pointer to the allocated memory.
44 * @returns NULL on failure.
45 * @param cb Size in bytes of the memory block to allocate.
46 */
47RTDECL(void *) RTMemExecAlloc(size_t cb)
48{
49 /*
50 * Allocate first.
51 */
52 AssertMsg(cb, ("Allocating ZERO bytes is really not a good idea! Good luck with the next assertion!\n"));
53 cb = RT_ALIGN_Z(cb, 32);
54 void *pv = NULL;
55 int rc = posix_memalign(&pv, 32, cb);
56 AssertMsg(!rc && pv, ("posix_memalign(%zd) failed!!! rc=%d\n", cb, rc));
57 if (pv && !rc)
58 {
59 /*
60 * Add PROT_EXEC flag to the page.
61 *
62 * This is in violation of the SuS where I think it saith that mprotect() shall
63 * only be used with mmap()'ed memory. Works on linux and OS/2 LIBC v0.6.
64 */
65 memset(pv, 0xcc, cb);
66 void *pvProt = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
67 size_t cbProt = ((uintptr_t)pv & PAGE_OFFSET_MASK) + cb;
68 cbProt = RT_ALIGN_Z(cbProt, PAGE_SIZE);
69 rc = mprotect(pvProt, cbProt, PROT_READ | PROT_WRITE | PROT_EXEC);
70 if (rc)
71 {
72 AssertMsgFailed(("mprotect(%p, %#zx,,) -> rc=%d, errno=%d\n", pvProt, cbProt, rc, errno));
73 free(pv);
74 pv = NULL;
75 }
76 }
77 return pv;
78}
79
80
81/**
82 * Free executable/read/write memory allocated by RTMemExecAlloc().
83 *
84 * @param pv Pointer to memory block.
85 */
86RTDECL(void) RTMemExecFree(void *pv)
87{
88 if (pv)
89 free(pv);
90}
91
92
93/**
94 * Allocate page aligned memory.
95 *
96 * @returns Pointer to the allocated memory.
97 * @returns NULL if we're out of memory.
98 * @param cb Size of the memory block. Will be rounded up to page size.
99 */
100RTDECL(void *) RTMemPageAlloc(size_t cb)
101{
102#if 0 /** @todo huh? we're using posix_memalign in the next function... */
103 void *pv;
104 int rc = posix_memalign(&pv, PAGE_SIZE, RT_ALIGN_Z(cb, PAGE_SIZE));
105 if (!rc)
106 return pv;
107 return NULL;
108#else
109 return memalign(PAGE_SIZE, cb);
110#endif
111}
112
113
114/**
115 * Allocate zero'ed page aligned memory.
116 *
117 * @returns Pointer to the allocated memory.
118 * @returns NULL if we're out of memory.
119 * @param cb Size of the memory block. Will be rounded up to page size.
120 */
121RTDECL(void *) RTMemPageAllocZ(size_t cb)
122{
123 void *pv;
124 int rc = posix_memalign(&pv, PAGE_SIZE, RT_ALIGN_Z(cb, PAGE_SIZE));
125 if (!rc)
126 {
127 bzero(pv, RT_ALIGN_Z(cb, PAGE_SIZE));
128 return pv;
129 }
130 return NULL;
131}
132
133
134/**
135 * Free a memory block allocated with RTMemPageAlloc() or RTMemPageAllocZ().
136 *
137 * @param pv Pointer to the block as it was returned by the allocation function.
138 * NULL will be ignored.
139 */
140RTDECL(void) RTMemPageFree(void *pv)
141{
142 if (pv)
143 free(pv);
144}
145
146
147/**
148 * Change the page level protection of a memory region.
149 *
150 * @returns iprt status code.
151 * @param pv Start of the region. Will be rounded down to nearest page boundary.
152 * @param cb Size of the region. Will be rounded up to the nearest page boundary.
153 * @param fProtect The new protection, a combination of the RTMEM_PROT_* defines.
154 */
155RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect)
156{
157 /*
158 * Validate input.
159 */
160 if (cb == 0)
161 {
162 AssertMsgFailed(("!cb\n"));
163 return VERR_INVALID_PARAMETER;
164 }
165 if (fProtect & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC))
166 {
167 AssertMsgFailed(("fProtect=%#x\n", fProtect));
168 return VERR_INVALID_PARAMETER;
169 }
170
171 /*
172 * Convert the flags.
173 */
174 int fProt;
175#if RTMEM_PROT_NONE == PROT_NONE \
176 && RTMEM_PROT_READ == PROT_READ \
177 && RTMEM_PROT_WRITE == PROT_WRITE \
178 && RTMEM_PROT_EXEC == PROT_EXEC
179 fProt = fProtect;
180#else
181 Assert(!RTMEM_PROT_NONE);
182 if (!fProtect)
183 fProt = PROT_NONE;
184 else
185 {
186 fProt = 0;
187 if (fProtect & RTMEM_PROT_READ)
188 fProt |= PROT_READ;
189 if (fProtect & RTMEM_PROT_WRITE)
190 fProt |= PROT_WRITE;
191 if (fProtect & RTMEM_PROT_EXEC)
192 fProt |= PROT_EXEC;
193 }
194#endif
195
196 /*
197 * Align the request.
198 */
199 cb += (uintptr_t)pv & PAGE_OFFSET_MASK;
200 pv = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
201
202 /*
203 * Change the page attributes.
204 */
205 int rc = mprotect(pv, cb, fProt);
206 if (!rc)
207 return rc;
208 return RTErrConvertFromErrno(errno);
209}
210
211#endif
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