VirtualBox

source: kStuff/trunk/kHlp/Generic/kHlpPage.c@ 2

Last change on this file since 2 was 2, checked in by bird, 17 years ago

Imported http://svn.netlabs.org/repos/libc/trunk/kStuff, revision 3612.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.1 KB
Line 
1/* $Id: kHlpPage.c 2 2007-11-16 16:07:14Z bird $ */
2/** @file
3 * kHlp - Generic Page Memory Functions.
4 */
5
6/*
7 * Copyright (c) 2006-2007 knut st. osmundsen <[email protected]>
8 *
9 * This file is part of kStuff.
10 *
11 * kStuff is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * In addition to the permissions in the GNU Lesser General Public
17 * License, you are granted unlimited permission to link the compiled
18 * version of this file into combinations with other programs, and to
19 * distribute those combinations without any restriction coming from
20 * the use of this file.
21 *
22 * kStuff is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with kStuff; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA
31 */
32
33/*******************************************************************************
34* Header Files *
35*******************************************************************************/
36#include <k/kHlpAlloc.h>
37#include <k/kHlpAssert.h>
38
39#if K_OS == K_OS_DARWIN \
40 || K_OS == K_OS_FREEBSD \
41 || K_OS == K_OS_LINUX \
42 || K_OS == K_OS_NETBSD \
43 || K_OS == K_OS_OPENBSD \
44 || K_OS == K_OS_SOLARIS
45# include <k/kHlpSys.h>
46# include <sys/mman.h>
47
48#elif K_OS == K_OS_OS2
49# define INCL_BASE
50# define INCL_ERRORS
51# include <os2.h>
52
53#elif K_OS == K_OS_WINDOWS
54# include <Windows.h>
55
56#else
57# error "port me"
58#endif
59
60
61/*******************************************************************************
62* Global Variables *
63*******************************************************************************/
64#if K_OS == K_OS_DARWIN \
65 || K_OS == K_OS_FREEBSD \
66 || K_OS == K_OS_LINUX \
67 || K_OS == K_OS_NETBSD \
68 || K_OS == K_OS_OPENBSD \
69 || K_OS == K_OS_SOLARIS
70/* nothing */
71#elif K_OS == K_OS_OS2
72/** The base of the loader stub object. <kLdr Hack>
73 * The OS/2 exe stub consists of a single data object. When allocating memory
74 * for an executable, we'll have to reuse this. */
75static void *g_pvStub = NULL;
76/** The size of the stub object - 0 if no stub. <kLdr Hack> */
77static KSIZE g_cbStub = 0;
78
79#elif K_OS == K_OS_WINDOWS
80/** The system info. */
81static SYSTEM_INFO g_SystemInfo;
82#else
83# error "port me"
84#endif
85
86
87
88#if K_OS == K_OS_DARWIN \
89 || K_OS == K_OS_FREEBSD \
90 || K_OS == K_OS_LINUX \
91 || K_OS == K_OS_NETBSD \
92 || K_OS == K_OS_OPENBSD \
93 || K_OS == K_OS_SOLARIS
94static int kHlpPageProtToNative(KPROT enmProt)
95{
96 switch (enmProt)
97 {
98 case KPROT_NOACCESS: return PROT_NONE;
99 case KPROT_READONLY: return PROT_READ;
100 case KPROT_READWRITE: return PROT_READ | PROT_WRITE;
101 case KPROT_EXECUTE: return PROT_EXEC;
102 case KPROT_EXECUTE_READ: return PROT_EXEC | PROT_READ;
103 case KPROT_EXECUTE_READWRITE: return PROT_EXEC | PROT_READ | PROT_WRITE;
104 default:
105 kHlpAssert(0);
106 return ~0U;
107 }
108}
109
110#elif K_OS == K_OS_OS2
111static ULONG kHlpPageProtToNative(KPROT enmProt)
112{
113 switch (enmProt)
114 {
115 case KPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
116 case KPROT_READONLY: return PAG_COMMIT | PAG_READ;
117 case KPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
118 case KPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
119 case KPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
120 case KPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
121 default:
122 kHlpAssert(0);
123 return ~0U;
124 }
125}
126#elif K_OS == K_OS_WINDOWS
127static DWORD kHlpPageProtToNative(KPROT enmProt)
128{
129 switch (enmProt)
130 {
131 case KPROT_NOACCESS: return PAGE_NOACCESS;
132 case KPROT_READONLY: return PAGE_READONLY;
133 case KPROT_READWRITE: return PAGE_READWRITE;
134 case KPROT_EXECUTE: return PAGE_EXECUTE;
135 case KPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
136 case KPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
137 default:
138 kHlpAssert(0);
139 return ~0U;
140 }
141}
142#endif
143
144
145
146/**
147 * Allocate a chunk of memory with page granularity.
148 *
149 * @returns 0 on success, non-zero OS status code on failure.
150 * @param ppv Where to store the address of the allocated memory.
151 * If fFixed is set, *ppv will on entry contain the desired address (page aligned).
152 * @param cb Number of bytes. Page aligned.
153 * @param enmProt The new protection. Copy-on-write is invalid.
154 */
155KHLP_DECL(int) kHlpPageAlloc(void **ppv, KSIZE cb, KPROT enmProt, KBOOL fFixed)
156{
157#if K_OS == K_OS_DARWIN \
158 || K_OS == K_OS_FREEBSD \
159 || K_OS == K_OS_LINUX \
160 || K_OS == K_OS_NETBSD \
161 || K_OS == K_OS_OPENBSD \
162 || K_OS == K_OS_SOLARIS
163 void *pv;
164
165 pv = kHlpSys_mmap(fFixed ? *ppv : NULL, cb, kHlpPageProtToNative(enmProt),
166 fFixed ? MAP_FIXED | MAP_ANON: MAP_ANON, -1, 0);
167 if ((KIPTR)pv < 256)
168 {
169 kHlpAssert(0);
170 return (int)(KIPTR)pv; /** @todo convert errno to kErrors */
171 }
172 *ppv = pv;
173 return 0;
174
175#elif K_OS == K_OS_OS2
176 APIRET rc;
177 ULONG fFlags = kHlpPageProtToNative(enmProt);
178
179 if (!fFixed)
180 {
181 /* simple */
182 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
183 if (rc == ERROR_INVALID_PARAMETER)
184 rc = DosAllocMem(ppv, cb, fFlags);
185 }
186 else
187 {
188 /* not so simple. */
189 /** @todo I've got code for this in libc somewhere. */
190 rc = -1;
191 }
192 if (!rc)
193 return 0;
194 kHlpAssert(0);
195 return rc;
196
197#elif K_OS == K_OS_WINDOWS
198 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
199 int rc;
200 DWORD fProt = kHlpPageProtToNative(enmProt);
201
202 if (!g_SystemInfo.dwPageSize)
203 GetSystemInfo(&g_SystemInfo);
204
205 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
206 if (*ppv != NULL)
207 return 0;
208 rc = GetLastError();
209 kHlpAssert(0);
210 return rc;
211
212#else
213# error "port me"
214#endif
215}
216
217
218/**
219 * Change the protection of one or more pages in an allocation.
220 *
221 * (This will of course only work correctly on memory allocated by kHlpPageAlloc().)
222 *
223 * @returns 0 on success, non-zero OS status code on failure.
224 * @param pv First page. Page aligned.
225 * @param cb Number of bytes. Page aligned.
226 * @param enmProt The new protection. Copy-on-write is invalid.
227 */
228KHLP_DECL(int) kHlpPageProtect(void *pv, KSIZE cb, KPROT enmProt)
229{
230#if K_OS == K_OS_DARWIN \
231 || K_OS == K_OS_FREEBSD \
232 || K_OS == K_OS_LINUX \
233 || K_OS == K_OS_NETBSD \
234 || K_OS == K_OS_OPENBSD \
235 || K_OS == K_OS_SOLARIS
236 int rc;
237
238 rc = kHlpSys_mprotect(pv, cb, kHlpPageProtToNative(enmProt));
239 if (!rc)
240 return 0;
241 /** @todo convert errno -> kErrors */
242 kHlpAssert(0);
243 return rc;
244
245#elif K_OS == K_OS_OS2
246 APIRET rc;
247 ULONG fFlags = kHlpPageProtToNative(enmProt);
248
249 /*
250 * The non-stub pages.
251 */
252 rc = DosSetMem(pv, cb, fFlags);
253 if (rc && fFlags != PAG_DECOMMIT)
254 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
255 if (rc)
256 {
257 /* Try page by page. */
258 while (cb > 0)
259 {
260 rc = DosSetMem(pv, 0x1000, fFlags);
261 if (rc && fFlags != PAG_DECOMMIT)
262 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
263 if (rc)
264 return rc;
265 pv = (void *)((KUPTR)pv + 0x1000);
266 cb -= 0x1000;
267 }
268 }
269 kHlpAssert(!rc);
270 return rc;
271
272#elif K_OS == K_OS_WINDOWS
273 DWORD fOldProt = 0;
274 DWORD fProt = kHlpPageProtToNative(enmProt);
275 int rc = 0;
276
277 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
278 {
279 rc = GetLastError();
280 kHlpAssert(0);
281 }
282 return rc;
283#else
284# error "port me"
285#endif
286}
287
288
289/**
290 * Free memory allocated by kHlpPageAlloc().
291 *
292 * @returns 0 on success, non-zero OS status code on failure.
293 * @param pv The address returned by kHlpPageAlloc().
294 * @param cb The byte count requested from kHlpPageAlloc().
295 */
296KHLP_DECL(int) kHlpPageFree(void *pv, KSIZE cb)
297{
298#if K_OS == K_OS_DARWIN \
299 || K_OS == K_OS_FREEBSD \
300 || K_OS == K_OS_LINUX \
301 || K_OS == K_OS_NETBSD \
302 || K_OS == K_OS_OPENBSD \
303 || K_OS == K_OS_SOLARIS
304 int rc;
305
306 rc = kHlpSys_munmap(pv, cb);
307 if (!rc)
308 return 0;
309 /** @todo convert errno -> kErrors */
310 return rc;
311
312#elif K_OS == K_OS_OS2
313 APIRET rc;
314
315 /*
316 * Deal with any portion overlapping with the stub.
317 */
318 KUPTR offStub = (KUPTR)pv - (KUPTR)g_pvStub;
319 if (offStub < g_cbStub)
320 {
321 /* decommit the pages in the stub. */
322 KSIZE cbStub = K_MIN(g_cbStub - offStub, cb);
323 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
324 if (rc)
325 {
326 /* Page by page, ignoring errors after the first success. */
327 while (cbStub > 0)
328 {
329 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
330 rc = 0;
331 pv = (void *)((KUPTR)pv + 0x1000);
332 cbStub -= 0x1000;
333 cb -= 0x1000;
334 }
335 if (rc)
336 {
337 kHlpAssert(!rc);
338 return rc;
339 }
340 }
341 else
342 {
343 cb -= cbStub;
344 if (!cb)
345 return 0;
346 pv = (void *)((KUPTR)pv + cbStub);
347 }
348 }
349
350 /*
351 * Free the object.
352 */
353 rc = DosFreeMem(pv);
354 kHlpAssert(!rc);
355 return rc;
356
357#elif K_OS == K_OS_WINDOWS
358 /*
359 * Free the object.
360 */
361 int rc = 0;
362 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
363 {
364 rc = GetLastError();
365 kHlpAssert(0);
366 }
367 return rc;
368
369#else
370# error "port me"
371#endif
372}
373
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