This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH,HURD] mmap: Use addr parameter even without MAP_FIXED
- From: Samuel Thibault <samuel dot thibault at gnu dot org>
- To: libc-alpha at sourceware dot org, roland at gnu dot org
- Cc: bug-hurd at gnu dot org
- Date: Tue, 27 Dec 2011 16:13:18 +0100
- Subject: [PATCH,HURD] mmap: Use addr parameter even without MAP_FIXED
Hello,
POSIX says that mmap should take the addr parameter as a suggestion in
an implementation-defined manner. On GNU/Hurd it's atm not used at all.
Some applications (such as firefox) frown on this and just busy-loop.
This makes mmap try with anywhere = 0 when addr is non-zero, before
trying with anywhere = 1 if it failed.
Samuel
2011-12-26 Samuel Thibault <samuel.thibault@ens-lyon.org>
* sysdeps/mach/hurd/mmap.c (__mmap): When `mapaddr' is non zero, try
__vm_allocate and __vm_map with `anywhere' set to 0 first, and try with
`anywhere' set to 1 only on KERN_NO_SPACE error.
---
mmap.c | 44 ++++++++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/sysdeps/mach/hurd/mmap.c b/sysdeps/mach/hurd/mmap.c
index 1d1460c..96d7661 100644
--- a/sysdeps/mach/hurd/mmap.c
+++ b/sysdeps/mach/hurd/mmap.c
@@ -51,15 +51,20 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
/* vm_allocate has (a little) less overhead in the kernel too. */
err = __vm_allocate (__mach_task_self (), &mapaddr, len,
- !(flags & MAP_FIXED));
+ !mapaddr);
- if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
+ if (err == KERN_NO_SPACE)
{
- /* XXX this is not atomic as it is in unix! */
- /* The region is already allocated; deallocate it first. */
- err = __vm_deallocate (__mach_task_self (), mapaddr, len);
- if (!err)
- err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0);
+ if (flags & MAP_FIXED)
+ {
+ /* XXX this is not atomic as it is in unix! */
+ /* The region is already allocated; deallocate it first. */
+ err = __vm_deallocate (__mach_task_self (), mapaddr, len);
+ if (!err)
+ err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0);
+ }
+ else if (mapaddr)
+ err = __vm_allocate (__mach_task_self (), &mapaddr, len, 1);
}
return err ? (__ptr_t) (long int) __hurd_fail (err) : (__ptr_t) mapaddr;
@@ -135,21 +140,32 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
- ! (flags & MAP_FIXED),
+ !mapaddr,
memobj, (vm_offset_t) offset,
! (flags & MAP_SHARED),
vmprot, VM_PROT_ALL,
(flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
- if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
+ if (err == KERN_NO_SPACE)
{
- /* XXX this is not atomic as it is in unix! */
- /* The region is already allocated; deallocate it first. */
- err = __vm_deallocate (__mach_task_self (), mapaddr, len);
- if (! err)
+ if (flags & MAP_FIXED)
+ {
+ /* XXX this is not atomic as it is in unix! */
+ /* The region is already allocated; deallocate it first. */
+ err = __vm_deallocate (__mach_task_self (), mapaddr, len);
+ if (! err)
+ err = __vm_map (__mach_task_self (),
+ &mapaddr, (vm_size_t) len, (vm_address_t) 0,
+ 0, memobj, (vm_offset_t) offset,
+ ! (flags & MAP_SHARED),
+ vmprot, VM_PROT_ALL,
+ (flags & MAP_SHARED) ? VM_INHERIT_SHARE
+ : VM_INHERIT_COPY);
+ }
+ else if (mapaddr)
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
- 0, memobj, (vm_offset_t) offset,
+ 1, memobj, (vm_offset_t) offset,
! (flags & MAP_SHARED),
vmprot, VM_PROT_ALL,
(flags & MAP_SHARED) ? VM_INHERIT_SHARE