Release 960414
[wine.git] / win32 / memory.c
blobba58f6f726343d1d2d843105c2c07ac79eb6d47b
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 */
7 #include <malloc.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include "windows.h"
16 #include "winerror.h"
17 #include "kernel32.h"
18 #include "winbase.h"
19 #include "handle32.h"
20 #include "stddebug.h"
21 #include "debug.h"
23 #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */
24 #define PROT_NONE 0
25 #endif
26 #ifndef MAP_ANON
27 #define MAP_ANON 0
28 #endif
30 typedef struct {
31 caddr_t ptr;
32 long size;
33 } virtual_mem_t;
35 virtual_mem_t *mem = 0;
36 int mem_count = 0;
37 int mem_used = 0;
39 /*******************************************************************
40 * VRANGE
41 * A VRANGE denotes a contiguous part of the address space. It is used
42 * for house keeping, and will be obtained by higher-level memory allocation
43 * functions (VirtualAlloc, MapViewOfFile)
44 * There can be at most one VRANGE object covering any address at any time.
45 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
46 * attempt to give a complete list of in-use address ranges, only those
47 * allocated via Win32.
48 * An exception is IsVrangeFree, which should test the OS specific
49 * mappings, too. As a default, an range not known to be allocated is
50 * considered free.
51 *******************************************************************/
53 VRANGE_OBJECT *MEMORY_ranges=0;
55 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
57 VRANGE_OBJECT *range;
58 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
60 if(range->start<start && start<range->start+range->size)
61 return range;
63 return 0;
66 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
68 DWORD end;
69 VRANGE_OBJECT *range;
70 if(!size)
71 return 1;
72 /* First, check our lists*/
73 end=start+size;
74 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
76 if((range->start<start && start<range->start+range->size) ||
77 (range->start<end && end<range->start+range->size))
78 return 0;
80 /* Now, check the maps that are not under our control */
81 #ifdef linux
83 FILE *f=fopen("/proc/self/maps","r");
84 char line[80];
85 int found=0;
86 while(1)
88 char *it;
89 int lower,upper;
90 if(!fgets(line,sizeof(line),f))
91 break;
92 it=line;
93 lower=strtoul(it,&it,16);
94 if(*it++!='-')
95 fprintf(stderr,"Format of /proc/self/maps changed\n");
96 upper=strtoul(it,&it,16);
97 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
99 found=1;
100 break;
103 fclose(f);
104 return !found;
106 #else
108 static int warned=0;
109 if(!warned)
111 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
112 "this system.\n Please fix\n");
113 warned=0;
115 return 1;
117 #endif
120 /* FIXME: might need to consolidate ranges */
121 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
123 VRANGE_OBJECT *it,*last;
124 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
126 r->next=MEMORY_ranges;
127 MEMORY_ranges=r;
129 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
130 last=it;
131 r->next=last->next;
132 last->next=r;
136 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
138 VRANGE_OBJECT *ret=CreateKernelObject(sizeof(VRANGE_OBJECT));
139 ret->common.magic=KERNEL_OBJECT_VRANGE;
140 MEMORY_InsertVrange(ret);
141 return ret;
144 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
146 VRANGE_OBJECT *it;
147 if(MEMORY_ranges==r)
149 MEMORY_ranges=r->next;
150 ReleaseKernelObject(r);
151 return;
153 for(it=MEMORY_ranges;it;it=it->next)
154 if(it->next==r)break;
155 if(!it)
157 fprintf(stderr,"VRANGE not found\n");
158 return;
160 it->next=r->next;
161 ReleaseKernelObject(r);
164 /***********************************************************************
165 * VirtualAlloc (KERNEL32.548)
167 int TranslateProtectionFlags(DWORD);
168 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
169 DWORD fdwAllocationType, DWORD fdwProtect)
171 caddr_t ptr;
172 int i;
173 virtual_mem_t *tmp_mem;
174 int prot;
176 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
177 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
178 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
179 + 0x00010000L),
180 cbSize, PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0);
181 if (ptr == (caddr_t) -1) {
182 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
183 return (LPVOID) NULL;
185 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
186 munmap(ptr, cbSize);
187 cbSize += 65535;
188 ptr = mmap(lpvAddress, cbSize,
189 PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0);
190 if (ptr == (caddr_t) -1) {
191 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
192 return (LPVOID) NULL;
194 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
196 /* remember the size for VirtualFree since it's going to be handed
197 a zero len */
198 if (ptr) {
199 if (mem_count == mem_used) {
200 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
201 if (!tmp_mem) return 0;
202 mem = tmp_mem;
203 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
204 mem_count += 10;
206 for (i=0; i<mem_count; i++) {
207 if (!(mem+i)->ptr) {
208 (mem+i)->ptr = ptr;
209 (mem+i)->size = cbSize;
210 mem_used++;
211 break;
215 } else {
216 ptr = lpvAddress;
218 if (fdwAllocationType & MEM_COMMIT) {
219 prot = TranslateProtectionFlags(fdwProtect &
220 ~(PAGE_GUARD | PAGE_NOCACHE));
221 mprotect(ptr, cbSize, prot);
223 #if 0
224 /* kludge for gnu-win32 */
225 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
226 ptr = malloc(cbSize + 65536);
227 if(ptr)
229 /* Round it up to the next 64K boundary and zero it.
231 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
232 memset(ptr, 0, cbSize);
234 #endif
235 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
236 return ptr;
239 /***********************************************************************
240 * VirtualFree (KERNEL32.550)
242 BOOL VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
244 int i;
246 if (fdwFreeType & MEM_RELEASE) {
247 for (i=0; i<mem_count; i++) {
248 if ((mem+i)->ptr == lpvAddress) {
249 munmap(lpvAddress, (mem+i)->size);
250 (mem+i)->ptr = 0;
251 mem_used--;
252 break;
255 } else {
256 mprotect(lpvAddress, cbSize, PROT_NONE);
258 #if 0
259 if(lpvAddress)
260 free(lpvAddress);
261 #endif
262 return 1;
265 int TranslateProtectionFlags(DWORD protection_flags)
267 int prot;
269 switch(protection_flags) {
270 case PAGE_READONLY:
271 prot=PROT_READ;
272 break;
273 case PAGE_READWRITE:
274 prot=PROT_READ|PROT_WRITE;
275 break;
276 case PAGE_WRITECOPY:
277 prot=PROT_WRITE;
278 break;
279 case PAGE_EXECUTE:
280 prot=PROT_EXEC;
281 break;
282 case PAGE_EXECUTE_READ:
283 prot=PROT_EXEC|PROT_READ;
284 break;
285 case PAGE_EXECUTE_READWRITE:
286 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
287 break;
288 case PAGE_EXECUTE_WRITECOPY:
289 prot=PROT_EXEC|PROT_WRITE;
290 break;
291 case PAGE_NOACCESS:
292 default:
293 prot=PROT_NONE;
294 break;
296 return prot;