Release 970215
[wine/multimedia.git] / win32 / memory.c
blob8cb1ae5db5da70bb3f60bf1cf4aa25fab2c1869a
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 */
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/mman.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "windows.h"
17 #include "winerror.h"
18 #include "winbase.h"
19 #include "heap.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
27 typedef struct {
28 caddr_t ptr;
29 long size;
30 } virtual_mem_t;
32 typedef struct _VRANGE_OBJECT
34 DWORD start;
35 DWORD size;
36 struct _VRANGE_OBJECT *next;
37 } VRANGE_OBJECT;
39 virtual_mem_t *mem = 0;
40 int mem_count = 0;
41 int mem_used = 0;
43 /*******************************************************************
44 * VRANGE
45 * A VRANGE denotes a contiguous part of the address space. It is used
46 * for house keeping, and will be obtained by higher-level memory allocation
47 * functions (VirtualAlloc, MapViewOfFile)
48 * There can be at most one VRANGE object covering any address at any time.
49 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
50 * attempt to give a complete list of in-use address ranges, only those
51 * allocated via Win32.
52 * An exception is IsVrangeFree, which should test the OS specific
53 * mappings, too. As a default, an range not known to be allocated is
54 * considered free.
55 *******************************************************************/
57 VRANGE_OBJECT *MEMORY_ranges=0;
59 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
61 VRANGE_OBJECT *range;
62 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
64 if(range->start<start && start<range->start+range->size)
65 return range;
67 return 0;
70 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
72 DWORD end;
73 VRANGE_OBJECT *range;
74 if(!size)
75 return 1;
76 /* First, check our lists*/
77 end=start+size;
78 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
80 if((range->start<start && start<range->start+range->size) ||
81 (range->start<end && end<range->start+range->size))
82 return 0;
84 /* Now, check the maps that are not under our control */
85 #ifdef linux
87 FILE *f=fopen("/proc/self/maps","r");
88 char line[80];
89 int found=0;
90 while(1)
92 char *it;
93 int lower,upper;
94 if(!fgets(line,sizeof(line),f))
95 break;
96 it=line;
97 lower=strtoul(it,&it,16);
98 if(*it++!='-')
99 fprintf(stderr,"Format of /proc/self/maps changed\n");
100 upper=strtoul(it,&it,16);
101 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
103 found=1;
104 break;
107 fclose(f);
108 return !found;
110 #else
112 static int warned=0;
113 if(!warned)
115 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
116 "this system.\n Please fix\n");
117 warned=0;
119 return 1;
121 #endif
124 /* FIXME: might need to consolidate ranges */
125 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
127 VRANGE_OBJECT *it,*last;
128 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
130 r->next=MEMORY_ranges;
131 MEMORY_ranges=r;
133 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
134 last=it;
135 r->next=last->next;
136 last->next=r;
140 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
142 VRANGE_OBJECT *ret=HeapAlloc( SystemHeap, 0, sizeof(VRANGE_OBJECT));
143 MEMORY_InsertVrange(ret);
144 return ret;
147 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
149 VRANGE_OBJECT *it;
150 if(MEMORY_ranges==r)
152 MEMORY_ranges=r->next;
153 HeapFree( SystemHeap, 0, r );
154 return;
156 for(it=MEMORY_ranges;it;it=it->next)
157 if(it->next==r)break;
158 if(!it)
160 fprintf(stderr,"VRANGE not found\n");
161 return;
163 it->next=r->next;
164 HeapFree( SystemHeap, 0, r );
167 /***********************************************************************
168 * VirtualAlloc (KERNEL32.548)
170 int TranslateProtectionFlags(DWORD);
171 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
172 DWORD fdwAllocationType, DWORD fdwProtect)
174 caddr_t ptr;
175 int i;
176 virtual_mem_t *tmp_mem;
177 int prot;
178 static int fdzero = -1;
180 if (fdzero == -1)
182 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
184 perror( "/dev/zero: open" );
185 return (LPVOID)NULL;
189 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
190 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
191 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
192 + 0x00010000L),
193 cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 );
194 if (ptr == (caddr_t) -1) {
195 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
196 return (LPVOID) NULL;
198 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
199 munmap(ptr, cbSize);
200 cbSize += 65535;
201 ptr = mmap(lpvAddress, cbSize,
202 PROT_NONE, MAP_PRIVATE, fdzero, 0 );
203 if (ptr == (caddr_t) -1) {
204 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
205 return (LPVOID) NULL;
207 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
209 /* remember the size for VirtualFree since it's going to be handed
210 a zero len */
211 if (ptr) {
212 if (mem_count == mem_used) {
213 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
214 if (!tmp_mem) return 0;
215 mem = tmp_mem;
216 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
217 mem_count += 10;
219 for (i=0; i<mem_count; i++) {
220 if (!(mem+i)->ptr) {
221 (mem+i)->ptr = ptr;
222 (mem+i)->size = cbSize;
223 mem_used++;
224 break;
228 } else {
229 ptr = lpvAddress;
231 if (fdwAllocationType & MEM_COMMIT) {
232 prot = TranslateProtectionFlags(fdwProtect &
233 ~(PAGE_GUARD | PAGE_NOCACHE));
234 mprotect(ptr, cbSize, prot);
236 #if 0
237 /* kludge for gnu-win32 */
238 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
239 ptr = malloc(cbSize + 65536);
240 if(ptr)
242 /* Round it up to the next 64K boundary and zero it.
244 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
245 memset(ptr, 0, cbSize);
247 #endif
248 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
249 return ptr;
252 /***********************************************************************
253 * VirtualFree (KERNEL32.550)
255 BOOL32 VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
257 int i;
259 if (fdwFreeType & MEM_RELEASE) {
260 for (i=0; i<mem_count; i++) {
261 if ((mem+i)->ptr == lpvAddress) {
262 munmap(lpvAddress, (mem+i)->size);
263 (mem+i)->ptr = 0;
264 mem_used--;
265 break;
268 } else {
269 mprotect(lpvAddress, cbSize, PROT_NONE);
271 #if 0
272 if(lpvAddress)
273 free(lpvAddress);
274 #endif
275 return 1;
278 /***********************************************************************
279 * VirtualQuery (KERNEL32.554)
281 BOOL32 VirtualQuery(LPCVOID address,LPMEMORY_BASIC_INFORMATION buf,DWORD len)
283 /* FIXME: fill out structure ... */
284 return TRUE;
287 /***********************************************************************
288 * VirtualProtect (KERNEL32.552)
290 BOOL32 VirtualProtect(LPVOID lpAddress,DWORD dwSize,DWORD flNewProtect,LPDWORD lpflOldProtect) {
291 /* FIXME: do protection ... see mprotect(). */
292 return TRUE;
296 int TranslateProtectionFlags(DWORD protection_flags)
298 int prot;
300 switch(protection_flags) {
301 case PAGE_READONLY:
302 prot=PROT_READ;
303 break;
304 case PAGE_READWRITE:
305 prot=PROT_READ|PROT_WRITE;
306 break;
307 case PAGE_WRITECOPY:
308 prot=PROT_WRITE;
309 break;
310 case PAGE_EXECUTE:
311 prot=PROT_EXEC;
312 break;
313 case PAGE_EXECUTE_READ:
314 prot=PROT_EXEC|PROT_READ;
315 break;
316 case PAGE_EXECUTE_READWRITE:
317 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
318 break;
319 case PAGE_EXECUTE_WRITECOPY:
320 prot=PROT_EXEC|PROT_WRITE;
321 break;
322 case PAGE_NOACCESS:
323 default:
324 prot=PROT_NONE;
325 break;
327 return prot;
331 /******************************************************************
332 * IsBadReadPtr
334 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
336 dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",(int)ptr,bytes);
337 /* FIXME: Should make check based on actual mappings, here */
338 return FALSE;
341 /******************************************************************
342 * IsBadWritePtr
344 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
346 dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",(int)ptr,bytes);
347 /* FIXME: Should make check based on actual mappings, here */
348 return FALSE;
350 /******************************************************************
351 * IsBadWritePtr
353 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
355 dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",(int)ptr,bytes);
356 /* FIXME: Should make check based on actual mappings, here */
357 return FALSE;