Using mmap(2) with a hint address

Ganael LAPLANCHE ganael.laplanche at martymac.org
Tue Dec 20 08:25:45 UTC 2011


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 at martymac.org>
http://www.martymac.org | http://contribs.martymac.org
FreeBSD: martymac <martymac at FreeBSD.org>, http://www.FreeBSD.org


More information about the freebsd-stable mailing list