mirror of https://gitee.com/openkylin/numactl.git
146 lines
3.1 KiB
C
146 lines
3.1 KiB
C
/* 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);
|
|
}
|