| /* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs. |
| Allocate memory with policy for testing. |
| |
| numactl is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public |
| License as published by the Free Software Foundation; version |
| 2. |
| |
| numactl is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should find a copy of v2 of the GNU General Public License somewhere |
| on your Linux system; if not, write to the Free Software Foundation, |
| Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <sys/mman.h> |
| #include <sys/fcntl.h> |
| #include <string.h> |
| #include <stdbool.h> |
| #include "numa.h" |
| #include "numaif.h" |
| #include "util.h" |
| |
| #define terr(x) perror(x) |
| |
| enum { |
| UNIT = 10*1024*1024, |
| }; |
| |
| #ifndef MADV_NOHUGEPAGE |
| #define MADV_NOHUGEPAGE 15 |
| #endif |
| |
| int repeat = 1; |
| |
| void usage(void) |
| { |
| printf("memhog [-rNUM] size[kmg] [policy [nodeset]]\n"); |
| printf("-rNUM repeat memset NUM times\n"); |
| printf("-H disable transparent hugepages\n"); |
| print_policies(); |
| exit(1); |
| } |
| |
| long length; |
| |
| void hog(void *map) |
| { |
| long i; |
| for (i = 0; i < length; i += UNIT) { |
| long left = length - i; |
| if (left > UNIT) |
| left = UNIT; |
| putchar('.'); |
| fflush(stdout); |
| memset(map + i, 0xff, left); |
| } |
| putchar('\n'); |
| } |
| |
| int main(int ac, char **av) |
| { |
| char *map; |
| struct bitmask *nodes, *gnodes; |
| int policy, gpolicy; |
| int ret = 0; |
| int loose = 0; |
| int i; |
| int fd = -1; |
| bool disable_hugepage = false; |
| |
| nodes = numa_allocate_nodemask(); |
| gnodes = numa_allocate_nodemask(); |
| |
| while (av[1] && av[1][0] == '-') { |
| switch (av[1][1]) { |
| case 'f': |
| fd = open(av[1]+2, O_RDWR); |
| if (fd < 0) |
| perror(av[1]+2); |
| break; |
| case 'r': |
| repeat = atoi(av[1] + 2); |
| break; |
| case 'H': |
| disable_hugepage = true; |
| break; |
| default: |
| usage(); |
| } |
| av++; |
| } |
| |
| if (!av[1]) usage(); |
| |
| length = memsize(av[1]); |
| if (av[2] && numa_available() < 0) { |
| printf("Kernel doesn't support NUMA policy\n"); |
| exit(1); |
| } else |
| loose = 1; |
| policy = parse_policy(av[2], av[3]); |
| if (policy != MPOL_DEFAULT) |
| nodes = numa_parse_nodestring(av[3]); |
| if (!nodes) { |
| printf ("<%s> is invalid\n", av[3]); |
| exit(1); |
| } |
| |
| if (fd >= 0) |
| map = mmap(NULL,length,PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
| else |
| map = mmap(NULL, length, PROT_READ|PROT_WRITE, |
| MAP_PRIVATE|MAP_ANONYMOUS, |
| 0, 0); |
| if (map == (char*)-1) |
| err("mmap"); |
| |
| if (mbind(map, length, policy, nodes->maskp, nodes->size, 0) < 0) |
| terr("mbind"); |
| |
| if (disable_hugepage) |
| madvise(map, length, MADV_NOHUGEPAGE); |
| |
| gpolicy = -1; |
| if (get_mempolicy(&gpolicy, gnodes->maskp, gnodes->size, map, MPOL_F_ADDR) < 0) |
| terr("get_mempolicy"); |
| if (!loose && policy != gpolicy) { |
| ret = 1; |
| printf("policy %d gpolicy %d\n", policy, gpolicy); |
| } |
| if (!loose && !numa_bitmask_equal(gnodes, nodes)) { |
| printf("nodes differ %lx, %lx!\n", |
| gnodes->maskp[0], nodes->maskp[0]); |
| ret = 1; |
| } |
| |
| for (i = 0; i < repeat; i++) |
| hog(map); |
| exit(ret); |
| } |