libwine: Reap child process to avoid leaving a zombie.
[wine] / libs / wine / mmap.c
1 /*
2  * Wine memory mappings support
3  *
4  * Copyright 2000, 2004 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_MMAN_H
32 #include <sys/mman.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #ifdef HAVE_STDINT_H
38 # include <stdint.h>
39 #endif
40
41 #include "wine/library.h"
42 #include "wine/list.h"
43
44 #ifdef HAVE_MMAP
45
46 struct reserved_area
47 {
48     struct list entry;
49     void       *base;
50     size_t      size;
51 };
52
53 static struct list reserved_areas = LIST_INIT(reserved_areas);
54 static const unsigned int granularity_mask = 0xffff;  /* reserved areas have 64k granularity */
55
56 #ifndef MAP_NORESERVE
57 #define MAP_NORESERVE 0
58 #endif
59 #ifndef MAP_PRIVATE
60 #define MAP_PRIVATE 0
61 #endif
62 #ifndef MAP_ANON
63 #define MAP_ANON 0
64 #endif
65
66 static inline int get_fdzero(void)
67 {
68     static int fd = -1;
69
70     if (MAP_ANON == 0 && fd == -1)
71     {
72         if ((fd = open( "/dev/zero", O_RDONLY )) == -1)
73         {
74             perror( "/dev/zero: open" );
75             exit(1);
76         }
77     }
78     return fd;
79 }
80
81 #if (defined(__svr4__) || defined(__NetBSD__)) && !defined(MAP_TRYFIXED)
82 /***********************************************************************
83  *             try_mmap_fixed
84  *
85  * The purpose of this routine is to emulate the behaviour of
86  * the Linux mmap() routine if a non-NULL address is passed,
87  * but the MAP_FIXED flag is not set.  Linux in this case tries
88  * to place the mapping at the specified address, *unless* the
89  * range is already in use.  Solaris, however, completely ignores
90  * the address argument in this case.
91  *
92  * As Wine code occasionally relies on the Linux behaviour, e.g. to
93  * be able to map non-relocatable PE executables to their proper
94  * start addresses, or to map the DOS memory to 0, this routine
95  * emulates the Linux behaviour by checking whether the desired
96  * address range is still available, and placing the mapping there
97  * using MAP_FIXED if so.
98  */
99 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
100                            int fildes, off_t off)
101 {
102     char * volatile result = NULL;
103     int pagesize = getpagesize();
104     pid_t pid, wret;
105
106     /* We only try to map to a fixed address if
107        addr is non-NULL and properly aligned,
108        and MAP_FIXED isn't already specified. */
109
110     if ( !addr )
111         return 0;
112     if ( (uintptr_t)addr & (pagesize-1) )
113         return 0;
114     if ( flags & MAP_FIXED )
115         return 0;
116
117     /* We use vfork() to freeze all threads of the
118        current process.  This allows us to check without
119        race condition whether the desired memory range is
120        already in use.  Note that because vfork() shares
121        the address spaces between parent and child, we
122        can actually perform the mapping in the child. */
123
124     if ( (pid = vfork()) == -1 )
125     {
126         perror("try_mmap_fixed: vfork");
127         exit(1);
128     }
129     if ( pid == 0 )
130     {
131         int i;
132         char vec;
133
134         /* We call mincore() for every page in the desired range.
135            If any of these calls succeeds, the page is already
136            mapped and we must fail. */
137         for ( i = 0; i < len; i += pagesize )
138             if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
139                _exit(1);
140
141         /* Perform the mapping with MAP_FIXED set.  This is safe
142            now, as none of the pages is currently in use. */
143         result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
144         if ( result == addr )
145             _exit(0);
146
147         if ( result != (void *) -1 ) /* This should never happen ... */
148             munmap( result, len );
149
150        _exit(1);
151     }
152
153     /* reap child */
154     do {
155         wret = waitpid(pid, NULL, 0);
156     } while (wret < 0 && errno == EINTR);
157
158     return result == addr;
159 }
160
161 #elif defined(__APPLE__)
162
163 #include <mach/mach_init.h>
164 #include <mach/vm_map.h>
165
166 /*
167  * On Darwin, we can use the Mach call vm_allocate to allocate
168  * anonymous memory at the specified address, and then use mmap with
169  * MAP_FIXED to replace the mapping.
170  */
171 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
172                            int fildes, off_t off)
173 {
174     vm_address_t result = (vm_address_t)addr;
175
176     if (!vm_allocate(mach_task_self(),&result,len,0))
177     {
178         if (mmap( (void *)result, len, prot, flags | MAP_FIXED, fildes, off ) != MAP_FAILED)
179             return 1;
180         vm_deallocate(mach_task_self(),result,len);
181     }
182     return 0;
183 }
184
185 #endif  /* (__svr4__ || __NetBSD__) && !MAP_TRYFIXED */
186
187
188 /***********************************************************************
189  *              wine_anon_mmap
190  *
191  * Portable wrapper for anonymous mmaps
192  */
193 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
194 {
195 #ifdef MAP_SHARED
196     flags &= ~MAP_SHARED;
197 #endif
198
199     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
200     flags |= MAP_PRIVATE | MAP_ANON;
201
202     if (!(flags & MAP_FIXED))
203     {
204 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
205         /* Even FreeBSD 5.3 does not properly support NULL here. */
206         if( start == NULL ) start = (void *)0x110000;
207 #endif
208
209 #ifdef MAP_TRYFIXED
210         /* If available, this will attempt a fixed mapping in-kernel */
211         flags |= MAP_TRYFIXED;
212 #elif defined(__svr4__) || defined(__NetBSD__) || defined(__APPLE__)
213         if ( try_mmap_fixed( start, size, prot, flags, get_fdzero(), 0 ) )
214             return start;
215 #endif
216     }
217     return mmap( start, size, prot, flags, get_fdzero(), 0 );
218 }
219
220
221 /***********************************************************************
222  *              mmap_reserve
223  *
224  * mmap wrapper used for reservations, only maps the specified address
225  */
226 static inline int mmap_reserve( void *addr, size_t size )
227 {
228     void *ptr;
229     int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE;
230
231 #ifdef MAP_TRYFIXED
232     flags |= MAP_TRYFIXED;
233 #elif defined(__APPLE__)
234     return try_mmap_fixed( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
235 #endif
236     ptr = mmap( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
237     if (ptr != addr && ptr != (void *)-1)  munmap( ptr, size );
238     return (ptr == addr);
239 }
240
241
242 /***********************************************************************
243  *           reserve_area
244  *
245  * Reserve as much memory as possible in the given area.
246  */
247 static inline void reserve_area( void *addr, void *end )
248 {
249     size_t size = (char *)end - (char *)addr;
250
251 #if (defined(__svr4__) || defined(__NetBSD__)) && !defined(MAP_TRYFIXED)
252     /* try_mmap_fixed is inefficient when using vfork, so we need a different algorithm here */
253     /* we assume no other thread is running at this point */
254     size_t i, pagesize = getpagesize();
255     char vec;
256
257     while (size)
258     {
259         for (i = 0; i < size; i += pagesize)
260             if (mincore( (caddr_t)addr + i, pagesize, &vec ) != -1) break;
261
262         i &= ~granularity_mask;
263         if (i && mmap( addr, i, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
264                        get_fdzero(), 0 ) != (void *)-1)
265             wine_mmap_add_reserved_area( addr, i );
266
267         i += granularity_mask + 1;
268         if ((char *)addr + i < (char *)addr) break;  /* overflow */
269         addr = (char *)addr + i;
270         if (addr >= end) break;
271         size = (char *)end - (char *)addr;
272     }
273 #else
274     if (!size) return;
275
276     if (mmap_reserve( addr, size ))
277     {
278         wine_mmap_add_reserved_area( addr, size );
279         return;
280     }
281     size = (size / 2) & ~granularity_mask;
282     if (size)
283     {
284         reserve_area( addr, (char *)addr + size );
285         reserve_area( (char *)addr + size, end );
286     }
287 #endif
288 }
289
290
291 /***********************************************************************
292  *           reserve_malloc_space
293  *
294  * Solaris malloc is not smart enough to obtain space through mmap(), so try to make
295  * sure that there is some available sbrk() space before we reserve other things.
296  */
297 static inline void reserve_malloc_space( size_t size )
298 {
299 #ifdef __sun
300     size_t i, count = size / 1024;
301     void **ptrs = malloc( count * sizeof(ptrs[0]) );
302
303     if (!ptrs) return;
304
305     for (i = 0; i < count; i++) if (!(ptrs[i] = malloc( 1024 ))) break;
306     if (i--)  /* free everything except the last one */
307         while (i) free( ptrs[--i] );
308     free( ptrs );
309 #endif
310 }
311
312
313 /***********************************************************************
314  *           reserve_dos_area
315  *
316  * Reserve the DOS area (0x00000000-0x00110000).
317  */
318 static inline void reserve_dos_area(void)
319 {
320     const size_t page_size = getpagesize();
321     const size_t dos_area_size = 0x110000;
322     void *ptr;
323
324     /* first page has to be handled specially */
325     ptr = wine_anon_mmap( (void *)page_size, dos_area_size - page_size, PROT_NONE, MAP_NORESERVE );
326     if (ptr != (void *)page_size)
327     {
328         if (ptr != (void *)-1) munmap( ptr, dos_area_size - page_size );
329         return;
330     }
331     /* now add first page with MAP_FIXED */
332     wine_anon_mmap( NULL, page_size, PROT_NONE, MAP_NORESERVE|MAP_FIXED );
333     wine_mmap_add_reserved_area( NULL, dos_area_size );
334 }
335
336
337 /***********************************************************************
338  *           mmap_init
339  */
340 void mmap_init(void)
341 {
342 #ifdef __i386__
343     struct reserved_area *area;
344     struct list *ptr;
345     char stack;
346     char * const stack_ptr = &stack;
347     char *user_space_limit = (char *)0x7ffe0000;
348
349     reserve_malloc_space( 8 * 1024 * 1024 );
350
351     if (!list_head( &reserved_areas ))
352     {
353         /* if we don't have a preloader, try to reserve some space below 2Gb */
354         reserve_area( (void *)0x00110000, (void *)0x40000000 );
355     }
356
357     /* check for a reserved area starting at the user space limit */
358     /* to avoid wasting time trying to allocate it again */
359     LIST_FOR_EACH( ptr, &reserved_areas )
360     {
361         area = LIST_ENTRY( ptr, struct reserved_area, entry );
362         if ((char *)area->base > user_space_limit) break;
363         if ((char *)area->base + area->size > user_space_limit)
364         {
365             user_space_limit = (char *)area->base + area->size;
366             break;
367         }
368     }
369
370     if (stack_ptr >= user_space_limit)
371     {
372         char *end = 0;
373         char *base = stack_ptr - ((unsigned int)stack_ptr & granularity_mask) - (granularity_mask + 1);
374         if (base > user_space_limit) reserve_area( user_space_limit, base );
375         base = stack_ptr - ((unsigned int)stack_ptr & granularity_mask) + (granularity_mask + 1);
376 #if defined(linux) || defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
377         /* Heuristic: assume the stack is near the end of the address */
378         /* space, this avoids a lot of futile allocation attempts */
379         end = (char *)(((unsigned long)base + 0x0fffffff) & 0xf0000000);
380 #endif
381         reserve_area( base, end );
382     }
383     else reserve_area( user_space_limit, 0 );
384
385     /* reserve the DOS area if not already done */
386
387     ptr = list_head( &reserved_areas );
388     if (ptr)
389     {
390         area = LIST_ENTRY( ptr, struct reserved_area, entry );
391         if (!area->base) return;  /* already reserved */
392     }
393     reserve_dos_area();
394
395 #elif defined(__x86_64__)
396
397     if (!list_head( &reserved_areas ))
398     {
399         /* if we don't have a preloader, try to reserve the space now */
400         reserve_area( (void *)0x000000010000, (void *)0x000068000000 );
401         reserve_area( (void *)0x00007ff00000, (void *)0x00007fff0000 );
402         reserve_area( (void *)0x7ffffe000000, (void *)0x7fffffff0000 );
403     }
404
405 #endif
406 }
407
408
409 /***********************************************************************
410  *           wine_mmap_add_reserved_area
411  *
412  * Add an address range to the list of reserved areas.
413  * Caller must have made sure the range is not used by anything else.
414  *
415  * Note: the reserved areas functions are not reentrant, caller is
416  * responsible for proper locking.
417  */
418 void wine_mmap_add_reserved_area( void *addr, size_t size )
419 {
420     struct reserved_area *area;
421     struct list *ptr;
422
423     if (!((char *)addr + size)) size--;  /* avoid wrap-around */
424
425     LIST_FOR_EACH( ptr, &reserved_areas )
426     {
427         area = LIST_ENTRY( ptr, struct reserved_area, entry );
428         if (area->base > addr)
429         {
430             /* try to merge with the next one */
431             if ((char *)addr + size == (char *)area->base)
432             {
433                 area->base = addr;
434                 area->size += size;
435                 return;
436             }
437             break;
438         }
439         else if ((char *)area->base + area->size == (char *)addr)
440         {
441             /* merge with the previous one */
442             area->size += size;
443
444             /* try to merge with the next one too */
445             if ((ptr = list_next( &reserved_areas, ptr )))
446             {
447                 struct reserved_area *next = LIST_ENTRY( ptr, struct reserved_area, entry );
448                 if ((char *)addr + size == (char *)next->base)
449                 {
450                     area->size += next->size;
451                     list_remove( &next->entry );
452                     free( next );
453                 }
454             }
455             return;
456         }
457     }
458
459     if ((area = malloc( sizeof(*area) )))
460     {
461         area->base = addr;
462         area->size = size;
463         list_add_before( ptr, &area->entry );
464     }
465 }
466
467
468 /***********************************************************************
469  *           wine_mmap_remove_reserved_area
470  *
471  * Remove an address range from the list of reserved areas.
472  * If 'unmap' is non-zero the range is unmapped too.
473  *
474  * Note: the reserved areas functions are not reentrant, caller is
475  * responsible for proper locking.
476  */
477 void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
478 {
479     struct reserved_area *area;
480     struct list *ptr;
481
482     if (!((char *)addr + size)) size--;  /* avoid wrap-around */
483
484     ptr = list_head( &reserved_areas );
485     /* find the first area covering address */
486     while (ptr)
487     {
488         area = LIST_ENTRY( ptr, struct reserved_area, entry );
489         if ((char *)area->base >= (char *)addr + size) break;  /* outside the range */
490         if ((char *)area->base + area->size > (char *)addr)  /* overlaps range */
491         {
492             if (area->base >= addr)
493             {
494                 if ((char *)area->base + area->size > (char *)addr + size)
495                 {
496                     /* range overlaps beginning of area only -> shrink area */
497                     if (unmap) munmap( area->base, (char *)addr + size - (char *)area->base );
498                     area->size -= (char *)addr + size - (char *)area->base;
499                     area->base = (char *)addr + size;
500                     break;
501                 }
502                 else
503                 {
504                     /* range contains the whole area -> remove area completely */
505                     ptr = list_next( &reserved_areas, ptr );
506                     if (unmap) munmap( area->base, area->size );
507                     list_remove( &area->entry );
508                     free( area );
509                     continue;
510                 }
511             }
512             else
513             {
514                 if ((char *)area->base + area->size > (char *)addr + size)
515                 {
516                     /* range is in the middle of area -> split area in two */
517                     struct reserved_area *new_area = malloc( sizeof(*new_area) );
518                     if (new_area)
519                     {
520                         new_area->base = (char *)addr + size;
521                         new_area->size = (char *)area->base + area->size - (char *)new_area->base;
522                         list_add_after( ptr, &new_area->entry );
523                     }
524                     else size = (char *)area->base + area->size - (char *)addr;
525                     area->size = (char *)addr - (char *)area->base;
526                     if (unmap) munmap( addr, size );
527                     break;
528                 }
529                 else
530                 {
531                     /* range overlaps end of area only -> shrink area */
532                     if (unmap) munmap( addr, (char *)area->base + area->size - (char *)addr );
533                     area->size = (char *)addr - (char *)area->base;
534                 }
535             }
536         }
537         ptr = list_next( &reserved_areas, ptr );
538     }
539 }
540
541
542 /***********************************************************************
543  *           wine_mmap_is_in_reserved_area
544  *
545  * Check if the specified range is included in a reserved area.
546  * Returns 1 if range is fully included, 0 if range is not included
547  * at all, and -1 if it is only partially included.
548  *
549  * Note: the reserved areas functions are not reentrant, caller is
550  * responsible for proper locking.
551  */
552 int wine_mmap_is_in_reserved_area( void *addr, size_t size )
553 {
554     struct reserved_area *area;
555     struct list *ptr;
556
557     LIST_FOR_EACH( ptr, &reserved_areas )
558     {
559         area = LIST_ENTRY( ptr, struct reserved_area, entry );
560         if (area->base > addr) break;
561         if ((char *)area->base + area->size <= (char *)addr) continue;
562         /* area must contain block completely */
563         if ((char *)area->base + area->size < (char *)addr + size) return -1;
564         return 1;
565     }
566     return 0;
567 }
568
569
570 /***********************************************************************
571  *           wine_mmap_enum_reserved_areas
572  *
573  * Enumerate the list of reserved areas, sorted by addresses.
574  * If enum_func returns a non-zero value, enumeration is stopped and the value is returned.
575  *
576  * Note: the reserved areas functions are not reentrant, caller is
577  * responsible for proper locking.
578  */
579 int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg,
580                                    int top_down )
581 {
582     int ret = 0;
583     struct list *ptr;
584
585     if (top_down)
586     {
587         for (ptr = reserved_areas.prev; ptr != &reserved_areas; ptr = ptr->prev)
588         {
589             struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry );
590             if ((ret = enum_func( area->base, area->size, arg ))) break;
591         }
592     }
593     else
594     {
595         for (ptr = reserved_areas.next; ptr != &reserved_areas; ptr = ptr->next)
596         {
597             struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry );
598             if ((ret = enum_func( area->base, area->size, arg ))) break;
599         }
600     }
601     return ret;
602 }
603
604 #else /* HAVE_MMAP */
605
606 void mmap_init(void)
607 {
608 }
609
610 #endif