drdot
drdot

Reputation: 3347

Why mmap cannot allocate memory?

I ran the program with root priviledge but it keeps complaining that mmap cannot allocate memory. Code snippet is below:

#define PROTECTION (PROT_READ | PROT_WRITE)
#define LENGTH (4*1024)

#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000
#endif

#define ADDR (void *) (0x0UL)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)

int main (int argc, char *argv[]){
...
  // allocate a buffer with the same size as the LLC using huge pages
  buf = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
  if (buf == MAP_FAILED) {
    perror("mmap");
    exit(1);
  }
...}

Hardware: I have 8G RAM. Processor is ivybridge

Uname output:

Linux mymachine 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

EDIT 1: The output of perror

mmap: Cannot allocate memory

Also added one line to print errno

printf("something is wrong: %d\n", errno);

But the output is:

something is wrong: 12

EDIT 2: The huge tlb related information from /proc/meminfo

HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

Upvotes: 13

Views: 33251

Answers (3)

world watera
world watera

Reputation: 3

A practical solution if you're surely knowing physical memory is enough:

echo 1 > /proc/sys/vm/overcommit_memory

Upvotes: -4

When you use MAP_HUGETLB, the mmap(2) call can fail (e.g. if your system does not have huge pages configured, or if some resource is exhausted), so you almost always should call mmap without MAP_HUGETLB as a fail back. Also, you should not define MAP_HUGETLB. If it is not defined (by system headers internal to <sys/mman.h>; it might be different according to architectures or kernel versions), don't use it!

// allocate a buffer with the same size as the LLC using huge pages
buf = mmap(NULL, LENGTH, PROTECTION,
#ifdef MAP_HUGETLB
           MAP_HUGETLB |
#endif
           MAP_PRIVATE | MAP_ANONYMOUS,
           0, 0);
#ifdef MAP_HUGETLB
  if (buf == MAP_FAILED) {
    // try again without huge pages:
    buf = mmap(NULL, LENGTH, PROTECTION, 
               MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
  };
#endif
if (buf == MAP_FAILED) {
   perror("mmap");
   exit(EXIT_FAILURE);
}

The kernel's Documentation/vm/hugetlspage.txt mention that huge pages are -or may be- limited (e.g. if you pass hugepages=N to the kernel, or if you do things thru /proc/ or /sys/, or if this was not configured in the kernel, etc...). So you are not sure to get them. And using huge pages for a small mapping of only 4Kbytes is a mistake (or perhaps a failure). Huge pages are worthwhile only when asking many megabytes (e.g. a gigabyte or more) and are always an optimization (e.g. you would want your application to be able to run on a kernel without them).

Upvotes: 10

D3Hunter
D3Hunter

Reputation: 1349

Well, as Documentation/vm/hugetlspage.txt suggested, do

echo 20 > /proc/sys/vm/nr_hugepages

solved the problem. Tested on ubuntu 14.04. Check Why I can't map memory with mmap also.

Upvotes: 22

Related Questions