Hi folks, I am trying to use mmap(2) with a hint address. Unfortunately, this address seems to be ignored and I never manage to get the desired one, while it seems to be free. Here is my code (the same code on NetBSD and GNU/Linux returns the hint address) : 8< ----------- >8 #include <stdio.h> #include <string.h> #include <errno.h> /* mmap */ #include <sys/mman.h> /* getpagesize */ #include <unistd.h> /* round_page */ #include <machine/param.h> int main(void) { size_t map_size = getpagesize(); /* first call, ask for one page, with hint */ char *map_hint = (char*)round_page(512*1024*1024); printf("=> calling mmap with hint = %p, size = %zu\n", map_hint, map_size); void *addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); if (addr == MAP_FAILED) { printf("mmap failed: %s\n", strerror(errno)); } else { printf("mmap succeeded: addr = %p\n", addr); #ifdef SLEEP /* leave time to use 'procstat -v' */ sleep(10); #endif if(munmap(addr, map_size) != 0) { printf("munmap failed: %s\n", strerror(errno)); } } /* second call, one page, without hint */ map_hint = 0; printf("=> calling mmap without hint, size = %zu\n", map_size); addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); if (addr == MAP_FAILED) { printf("mmap failed: %s\n", strerror(errno)); } else { printf("mmap succeeded: addr = %p\n", addr); #ifdef SLEEP /* leave time to use 'procstat -v' */ sleep(10); #endif if(munmap(addr, map_size) != 0) { printf("munmap failed: %s\n", strerror(errno)); } } return (0); } 8< ----------- >8 and its output : 1) On an i386 machine, FreeBSD 8.2-RELEASE : $ ./test-mmap => calling mmap with hint = 0x20000000, size = 4096 mmap succeeded: addr = 0x281a8000 => calling mmap without hint, size = 4096 mmap succeeded: addr = 0x281a8000 $ procstat -v 1685 PID START END PRT RES PRES REF SHD FL TP PATH 1685 0x8048000 0x8049000 r-x 1 0 1 0 CN vn /tmp/test-mmap 1685 0x8049000 0x8100000 rw- 1 0 1 0 -- df 1685 0x28049000 0x28078000 r-x 47 0 82 41 CN vn /libexec/ld-elf.so.1 1685 0x28078000 0x2807a000 rw- 2 0 1 0 C- vn /libexec/ld-elf.so.1 1685 0x2807a000 0x2808d000 rw- 12 0 1 0 -- df 1685 0x2808d000 0x2818b000 r-x 134 0 82 41 CN vn /lib/libc.so.7 1685 0x2818b000 0x28191000 rw- 6 0 1 0 C- vn /lib/libc.so.7 1685 0x28191000 0x281a8000 rw- 5 0 1 0 -- df 1685 0x281a8000 0x281a9000 rwx 0 0 0 0 -- -- 1685 0x28200000 0x28300000 rw- 2 0 1 0 -- df 1685 0xbfbe0000 0xbfc00000 rwx 3 0 1 0 -- df 2) On an amd64 machine, FreeBSD 8.2-RELEASE : $ ./test-mmap => calling mmap with hint = 0x20000000, size = 4096 mmap succeeded: addr = 0x800538000 => calling mmap without hint, size = 4096 mmap succeeded: addr = 0x800538000 $ procstat -v 38899 PID START END PRT RES PRES REF SHD FL TP PATH 38899 0x400000 0x401000 r-x 1 0 1 0 CN vn /tmp/test-mmap 38899 0x500000 0x600000 rw- 2 0 1 0 -- df 38899 0x800500000 0x800530000 r-x 48 0 218 95 CN vn /libexec/ld-elf.so.1 38899 0x800530000 0x800538000 rw- 7 0 2 0 -- df 38899 0x800538000 0x800539000 rwx 0 0 2 0 -- df 38899 0x80062f000 0x800637000 rw- 8 0 1 0 C- vn /libexec/ld-elf.so.1 38899 0x800637000 0x800646000 rw- 5 0 1 0 -- df 38899 0x800646000 0x80074e000 r-x 146 0 218 95 CN vn /lib/libc.so.7 38899 0x80074e000 0x80084e000 --- 0 0 2 0 -- df 38899 0x80084e000 0x80086d000 rw- 31 0 1 0 C- vn /lib/libc.so.7 38899 0x80086d000 0x800888000 rw- 6 0 2 0 -- df 38899 0x800a00000 0x800c00000 rw- 5 0 1 0 -- df 38899 0x7ffffffe0000 0x800000000000 rwx 3 0 1 0 -- df Using MAP_FIXED, I can get the desired address, but it is overkill (it replaces any previous mappings and its use is discouraged, see mmap(2)) and should not be needed here. Am I doing something wrong here ? -- Ganael LAPLANCHE <ganael.laplanche@martymac.org> http://www.martymac.org | http://contribs.martymac.org FreeBSD: martymac <martymac@FreeBSD.org>, http://www.FreeBSD.org
on 20/12/2011 10:08 Ganael LAPLANCHE said the following:> Hi folks, > > I am trying to use mmap(2) with a hint address. Unfortunately, this address > seems to be ignored and I never manage to get the desired one, while it > seems to be free.[snip]> Using MAP_FIXED, I can get the desired address, but it is overkill (it > replaces > any previous mappings and its use is discouraged, see mmap(2)) and > should not > be needed here. > > Am I doing something wrong here ?Can the following code explain what you are seeing? /* * XXX for non-fixed mappings where no hint is provided or * the hint would fall in the potential heap space, * place it after the end of the largest possible heap. * * There should really be a pmap call to determine a reasonable * location. */ PROC_LOCK(td->td_proc); if (addr == 0 || (addr >= round_page((vm_offset_t)vms->vm_taddr) && addr < round_page((vm_offset_t)vms->vm_daddr + lim_max(td->td_proc, RLIMIT_DATA)))) addr = round_page((vm_offset_t)vms->vm_daddr + lim_max(td->td_proc, RLIMIT_DATA)); PROC_UNLOCK(td->td_proc); -- Andriy Gapon
On Tuesday 20 December 2011 09:08:18 Ganael LAPLANCHE wrote:> Hi folks, > > I am trying to use mmap(2) with a hint address. Unfortunately, this address > seems to be ignored and I never manage to get the desired one, while it > seems to be free. > > Here is my code (the same code on NetBSD and GNU/Linux returns the hint > address) : > > 8< ----------- >8 > #include <stdio.h> > #include <string.h> > #include <errno.h> > > /* mmap */ > #include <sys/mman.h> > > /* getpagesize */ > #include <unistd.h> > > /* round_page */ > #include <machine/param.h> > > int main(void) > { > size_t map_size = getpagesize(); > > /* first call, ask for one page, with hint */ > char *map_hint = (char*)round_page(512*1024*1024); > printf("=> calling mmap with hint = %p, size = %zu\n", map_hint, > map_size); > void *addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE | > PROT_EXEC, > MAP_ANON | MAP_PRIVATE, -1, 0); > if (addr == MAP_FAILED) { > printf("mmap failed: %s\n", strerror(errno)); > } > else { > printf("mmap succeeded: addr = %p\n", addr); > #ifdef SLEEP > /* leave time to use 'procstat -v' */ > sleep(10); > #endif > if(munmap(addr, map_size) != 0) { > printf("munmap failed: %s\n", strerror(errno)); > } > } > > /* second call, one page, without hint */ > map_hint = 0; > printf("=> calling mmap without hint, size = %zu\n", map_size); > addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE | PROT_EXEC, > MAP_ANON | MAP_PRIVATE, -1, 0); > if (addr == MAP_FAILED) { > printf("mmap failed: %s\n", strerror(errno)); > } > else { > printf("mmap succeeded: addr = %p\n", addr); > #ifdef SLEEP > /* leave time to use 'procstat -v' */ > sleep(10); > #endif > if(munmap(addr, map_size) != 0) { > printf("munmap failed: %s\n", strerror(errno)); > } > } > return (0); > } > 8< ----------- >8 > > and its output : > > 1) On an i386 machine, FreeBSD 8.2-RELEASE : > > $ ./test-mmap > => calling mmap with hint = 0x20000000, size = 4096 > mmap succeeded: addr = 0x281a8000 > => calling mmap without hint, size = 4096 > mmap succeeded: addr = 0x281a8000 > > $ procstat -v 1685 > PID START END PRT RES PRES REF SHD FL TP PATH > 1685 0x8048000 0x8049000 r-x 1 0 1 0 CN vn /tmp/test-mmap > 1685 0x8049000 0x8100000 rw- 1 0 1 0 -- df > 1685 0x28049000 0x28078000 r-x 47 0 82 41 CN vn /libexec/ld-elf.so.1 > 1685 0x28078000 0x2807a000 rw- 2 0 1 0 C- vn /libexec/ld-elf.so.1 > 1685 0x2807a000 0x2808d000 rw- 12 0 1 0 -- df > 1685 0x2808d000 0x2818b000 r-x 134 0 82 41 CN vn /lib/libc.so.7 > 1685 0x2818b000 0x28191000 rw- 6 0 1 0 C- vn /lib/libc.so.7 > 1685 0x28191000 0x281a8000 rw- 5 0 1 0 -- df > 1685 0x281a8000 0x281a9000 rwx 0 0 0 0 -- -- > 1685 0x28200000 0x28300000 rw- 2 0 1 0 -- df > 1685 0xbfbe0000 0xbfc00000 rwx 3 0 1 0 -- df > > 2) On an amd64 machine, FreeBSD 8.2-RELEASE : > > $ ./test-mmap > => calling mmap with hint = 0x20000000, size = 4096 > mmap succeeded: addr = 0x800538000 > => calling mmap without hint, size = 4096 > mmap succeeded: addr = 0x800538000 > > $ procstat -v 38899 > PID START END PRT RES PRES REF SHD FL TP PATH > 38899 0x400000 0x401000 r-x 1 0 1 0 CN vn > /tmp/test-mmap > 38899 0x500000 0x600000 rw- 2 0 1 0 -- df > 38899 0x800500000 0x800530000 r-x 48 0 218 95 CN vn > /libexec/ld-elf.so.1 > 38899 0x800530000 0x800538000 rw- 7 0 2 0 -- df > 38899 0x800538000 0x800539000 rwx 0 0 2 0 -- df > 38899 0x80062f000 0x800637000 rw- 8 0 1 0 C- vn > /libexec/ld-elf.so.1 > 38899 0x800637000 0x800646000 rw- 5 0 1 0 -- df > 38899 0x800646000 0x80074e000 r-x 146 0 218 95 CN vn > /lib/libc.so.7 > 38899 0x80074e000 0x80084e000 --- 0 0 2 0 -- df > 38899 0x80084e000 0x80086d000 rw- 31 0 1 0 C- vn > /lib/libc.so.7 > 38899 0x80086d000 0x800888000 rw- 6 0 2 0 -- df > 38899 0x800a00000 0x800c00000 rw- 5 0 1 0 -- df > 38899 0x7ffffffe0000 0x800000000000 rwx 3 0 1 0 -- df > > Using MAP_FIXED, I can get the desired address, but it is overkill (it > replaces > any previous mappings and its use is discouraged, see mmap(2)) and > should not > be needed here. > > Am I doing something wrong here ?FreeBSD reserves quite a bit of space for brk(2) style heap. Your program will work if you use higher addresses. You can also shrink the reserved space either system wide by setting kern.maxdsiz sysctl in /boot/loader.conf, or in your program by setting the maximum RLIMIT_DATA with setrlimit(2). -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 228 bytes Desc: This is a digitally signed message part. Url : http://lists.freebsd.org/pipermail/freebsd-stable/attachments/20111220/2b5f7235/attachment.pgp