Release 960606
[wine/multimedia.git] / win32 / memory.c
blobc50a45c76d41784f4cea2f9d251d25d147e7d807
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 */
7 #include <fcntl.h>
8 #include <malloc.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "windows.h"
17 #include "winerror.h"
18 #include "kernel32.h"
19 #include "winbase.h"
20 #include "handle32.h"
21 #include "stddebug.h"
22 #include "debug.h"
24 #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */
25 #define PROT_NONE 0
26 #endif
28 typedef struct {
29 caddr_t ptr;
30 long size;
31 } virtual_mem_t;
33 virtual_mem_t *mem = 0;
34 int mem_count = 0;
35 int mem_used = 0;
37 /*******************************************************************
38 * VRANGE
39 * A VRANGE denotes a contiguous part of the address space. It is used
40 * for house keeping, and will be obtained by higher-level memory allocation
41 * functions (VirtualAlloc, MapViewOfFile)
42 * There can be at most one VRANGE object covering any address at any time.
43 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
44 * attempt to give a complete list of in-use address ranges, only those
45 * allocated via Win32.
46 * An exception is IsVrangeFree, which should test the OS specific
47 * mappings, too. As a default, an range not known to be allocated is
48 * considered free.
49 *******************************************************************/
51 VRANGE_OBJECT *MEMORY_ranges=0;
53 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
55 VRANGE_OBJECT *range;
56 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
58 if(range->start<start && start<range->start+range->size)
59 return range;
61 return 0;
64 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
66 DWORD end;
67 VRANGE_OBJECT *range;
68 if(!size)
69 return 1;
70 /* First, check our lists*/
71 end=start+size;
72 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
74 if((range->start<start && start<range->start+range->size) ||
75 (range->start<end && end<range->start+range->size))
76 return 0;
78 /* Now, check the maps that are not under our control */
79 #ifdef linux
81 FILE *f=fopen("/proc/self/maps","r");
82 char line[80];
83 int found=0;
84 while(1)
86 char *it;
87 int lower,upper;
88 if(!fgets(line,sizeof(line),f))
89 break;
90 it=line;
91 lower=strtoul(it,&it,16);
92 if(*it++!='-')
93 fprintf(stderr,"Format of /proc/self/maps changed\n");
94 upper=strtoul(it,&it,16);
95 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
97 found=1;
98 break;
101 fclose(f);
102 return !found;
104 #else
106 static int warned=0;
107 if(!warned)
109 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
110 "this system.\n Please fix\n");
111 warned=0;
113 return 1;
115 #endif
118 /* FIXME: might need to consolidate ranges */
119 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
121 VRANGE_OBJECT *it,*last;
122 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
124 r->next=MEMORY_ranges;
125 MEMORY_ranges=r;
127 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
128 last=it;
129 r->next=last->next;
130 last->next=r;
134 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
136 VRANGE_OBJECT *ret=CreateKernelObject(sizeof(VRANGE_OBJECT));
137 ret->common.magic=KERNEL_OBJECT_VRANGE;
138 MEMORY_InsertVrange(ret);
139 return ret;
142 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
144 VRANGE_OBJECT *it;
145 if(MEMORY_ranges==r)
147 MEMORY_ranges=r->next;
148 ReleaseKernelObject(r);
149 return;
151 for(it=MEMORY_ranges;it;it=it->next)
152 if(it->next==r)break;
153 if(!it)
155 fprintf(stderr,"VRANGE not found\n");
156 return;
158 it->next=r->next;
159 ReleaseKernelObject(r);
162 /***********************************************************************
163 * VirtualAlloc (KERNEL32.548)
165 int TranslateProtectionFlags(DWORD);
166 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
167 DWORD fdwAllocationType, DWORD fdwProtect)
169 caddr_t ptr;
170 int i;
171 virtual_mem_t *tmp_mem;
172 int prot;
173 static int fdzero = -1;
175 if (fdzero == -1)
177 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
179 perror( "/dev/zero: open" );
180 return (LPVOID)NULL;
184 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
185 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
186 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
187 + 0x00010000L),
188 cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 );
189 if (ptr == (caddr_t) -1) {
190 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
191 return (LPVOID) NULL;
193 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
194 munmap(ptr, cbSize);
195 cbSize += 65535;
196 ptr = mmap(lpvAddress, cbSize,
197 PROT_NONE, MAP_PRIVATE, fdzero, 0 );
198 if (ptr == (caddr_t) -1) {
199 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
200 return (LPVOID) NULL;
202 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
204 /* remember the size for VirtualFree since it's going to be handed
205 a zero len */
206 if (ptr) {
207 if (mem_count == mem_used) {
208 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
209 if (!tmp_mem) return 0;
210 mem = tmp_mem;
211 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
212 mem_count += 10;
214 for (i=0; i<mem_count; i++) {
215 if (!(mem+i)->ptr) {
216 (mem+i)->ptr = ptr;
217 (mem+i)->size = cbSize;
218 mem_used++;
219 break;
223 } else {
224 ptr = lpvAddress;
226 if (fdwAllocationType & MEM_COMMIT) {
227 prot = TranslateProtectionFlags(fdwProtect &
228 ~(PAGE_GUARD | PAGE_NOCACHE));
229 mprotect(ptr, cbSize, prot);
231 #if 0
232 /* kludge for gnu-win32 */
233 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
234 ptr = malloc(cbSize + 65536);
235 if(ptr)
237 /* Round it up to the next 64K boundary and zero it.
239 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
240 memset(ptr, 0, cbSize);
242 #endif
243 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
244 return ptr;
247 /***********************************************************************
248 * VirtualFree (KERNEL32.550)
250 BOOL VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
252 int i;
254 if (fdwFreeType & MEM_RELEASE) {
255 for (i=0; i<mem_count; i++) {
256 if ((mem+i)->ptr == lpvAddress) {
257 munmap(lpvAddress, (mem+i)->size);
258 (mem+i)->ptr = 0;
259 mem_used--;
260 break;
263 } else {
264 mprotect(lpvAddress, cbSize, PROT_NONE);
266 #if 0
267 if(lpvAddress)
268 free(lpvAddress);
269 #endif
270 return 1;
273 int TranslateProtectionFlags(DWORD protection_flags)
275 int prot;
277 switch(protection_flags) {
278 case PAGE_READONLY:
279 prot=PROT_READ;
280 break;
281 case PAGE_READWRITE:
282 prot=PROT_READ|PROT_WRITE;
283 break;
284 case PAGE_WRITECOPY:
285 prot=PROT_WRITE;
286 break;
287 case PAGE_EXECUTE:
288 prot=PROT_EXEC;
289 break;
290 case PAGE_EXECUTE_READ:
291 prot=PROT_EXEC|PROT_READ;
292 break;
293 case PAGE_EXECUTE_READWRITE:
294 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
295 break;
296 case PAGE_EXECUTE_WRITECOPY:
297 prot=PROT_EXEC|PROT_WRITE;
298 break;
299 case PAGE_NOACCESS:
300 default:
301 prot=PROT_NONE;
302 break;
304 return prot;
308 /******************************************************************
309 * IsBadReadPtr
311 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
313 dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",ptr,bytes);
314 /* FIXME: Should make check based on actual mappings, here */
315 return FALSE;
318 /******************************************************************
319 * IsBadWritePtr
321 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
323 dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",ptr,bytes);
324 /* FIXME: Should make check based on actual mappings, here */
325 return FALSE;
327 /******************************************************************
328 * IsBadWritePtr
330 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
332 dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",ptr,bytes);
333 /* FIXME: Should make check based on actual mappings, here */
334 return FALSE;