|
Packit |
2d622a |
/***************************************************************************
|
|
Packit |
2d622a |
* User front end for using huge pages Copyright (C) 2008, IBM *
|
|
Packit |
2d622a |
* *
|
|
Packit |
2d622a |
* This program is free software; you can redistribute it and/or modify *
|
|
Packit |
2d622a |
* it under the terms of the Lesser GNU General Public License as *
|
|
Packit |
2d622a |
* published by the Free Software Foundation; either version 2.1 of the *
|
|
Packit |
2d622a |
* License, or at your option) any later version. *
|
|
Packit |
2d622a |
* *
|
|
Packit |
2d622a |
* This program is distributed in the hope that it will be useful, *
|
|
Packit |
2d622a |
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
Packit |
2d622a |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
Packit |
2d622a |
* GNU Lesser General Public License for more details. *
|
|
Packit |
2d622a |
* *
|
|
Packit |
2d622a |
* You should have received a copy of the Lesser GNU General Public *
|
|
Packit |
2d622a |
* License along with this program; if not, write to the *
|
|
Packit |
2d622a |
* Free Software Foundation, Inc., *
|
|
Packit |
2d622a |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
Packit |
2d622a |
***************************************************************************/
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* hugectl is inspired by numactl as a single front end to a large number of
|
|
Packit |
2d622a |
* options for controlling a very specific environment. Eventually it will
|
|
Packit |
2d622a |
* have support for controlling the all of the environment variables for
|
|
Packit |
2d622a |
* libhugetlbfs, but options will only be added after they have been in the
|
|
Packit |
2d622a |
* library for some time and are throughly tested and stable.
|
|
Packit |
2d622a |
*
|
|
Packit |
2d622a |
* This program should be treated as an ABI for using libhugetlbfs.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#include <stdlib.h>
|
|
Packit |
2d622a |
#include <stdio.h>
|
|
Packit |
2d622a |
#include <errno.h>
|
|
Packit |
2d622a |
#include <string.h>
|
|
Packit |
2d622a |
#include <limits.h>
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define _GNU_SOURCE /* for getopt_long */
|
|
Packit |
2d622a |
#include <unistd.h>
|
|
Packit |
2d622a |
#include <getopt.h>
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define REPORT(level, prefix, format, ...) \
|
|
Packit |
2d622a |
do { \
|
|
Packit |
2d622a |
if (verbose_level >= level) \
|
|
Packit |
2d622a |
fprintf(stderr, "hugectl: " prefix ": " format, \
|
|
Packit |
2d622a |
##__VA_ARGS__); \
|
|
Packit |
2d622a |
} while (0);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#include "libhugetlbfs_debug.h"
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
extern int errno;
|
|
Packit |
2d622a |
extern int optind;
|
|
Packit |
2d622a |
extern char *optarg;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define OPTION(opts, text) fprintf(stderr, " %-25s %s\n", opts, text)
|
|
Packit |
2d622a |
#define CONT(text) fprintf(stderr, " %-25s %s\n", "", text)
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void print_usage()
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
fprintf(stderr, "hugectl [options] target\n");
|
|
Packit |
2d622a |
fprintf(stderr, "options:\n");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
OPTION("--help, -h", "Prints this message");
|
|
Packit |
2d622a |
OPTION("--verbose <level>, -v", "Increases/sets tracing levels");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
OPTION("--text[=<size>]", "Requests remapping of the program text");
|
|
Packit |
2d622a |
OPTION("--data[=<size>]", "Requests remapping of the program data");
|
|
Packit |
2d622a |
OPTION("--bss[=<size>]", "Requests remapping of the program bss");
|
|
Packit |
2d622a |
OPTION("--heap[=<size>]", "Requests remapping of the program heap");
|
|
Packit |
2d622a |
CONT("(malloc space)");
|
|
Packit |
2d622a |
OPTION("--shm", "Requests remapping of shared memory segments");
|
|
Packit |
2d622a |
OPTION("--thp", "Setup the heap space to be aligned for merging");
|
|
Packit |
2d622a |
CONT("by khugepaged into huge pages. This requires");
|
|
Packit |
2d622a |
CONT("kernel support for transparent huge pages to be");
|
|
Packit |
2d622a |
CONT("enabled");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
OPTION("--no-preload", "Disable preloading the libhugetlbfs library");
|
|
Packit |
2d622a |
OPTION("--no-reserve", "Disable huge page reservation for segments");
|
|
Packit |
2d622a |
OPTION("--force-preload", "Force preloading the libhugetlbfs library");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
OPTION("--dry-run", "describe what would be done without doing it");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
OPTION("--library-use-path", "Use the system library path");
|
|
Packit |
2d622a |
OPTION("--share-text", "Share text segments between multiple");
|
|
Packit |
2d622a |
CONT("application instances");
|
|
Packit |
2d622a |
OPTION("--library-path <path>", "Select a library prefix");
|
|
Packit |
2d622a |
CONT("(Default: "
|
|
Packit |
2d622a |
#ifdef LIBDIR32
|
|
Packit |
2d622a |
LIBDIR32 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
#ifdef LIBDIR32
|
|
Packit |
2d622a |
LIBDIR32 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
")");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
int opt_dry_run = 0;
|
|
Packit |
2d622a |
int opt_force_preload = 0;
|
|
Packit |
2d622a |
int verbose_level = VERBOSITY_DEFAULT;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void verbose_init(void)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
char *env;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
env = getenv("HUGETLB_VERBOSE");
|
|
Packit |
2d622a |
if (env)
|
|
Packit |
2d622a |
verbose_level = atoi(env);
|
|
Packit |
2d622a |
env = getenv("HUGETLB_DEBUG");
|
|
Packit |
2d622a |
if (env)
|
|
Packit |
2d622a |
verbose_level = VERBOSITY_MAX;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void verbose(char *which)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
int new_level;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (which) {
|
|
Packit |
2d622a |
new_level = atoi(which);
|
|
Packit |
2d622a |
if (new_level < 0 || new_level > 99) {
|
|
Packit |
2d622a |
ERROR("%d: verbosity out of range 0-99\n",
|
|
Packit |
2d622a |
new_level);
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
} else {
|
|
Packit |
2d622a |
new_level = verbose_level + 1;
|
|
Packit |
2d622a |
if (new_level == 100) {
|
|
Packit |
2d622a |
WARNING("verbosity limited to 99\n");
|
|
Packit |
2d622a |
new_level--;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
verbose_level = new_level;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void quiet(void)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
int new_level = verbose_level - 1;
|
|
Packit |
2d622a |
if (new_level < 0) {
|
|
Packit |
2d622a |
WARNING("verbosity must be at least 0\n");
|
|
Packit |
2d622a |
new_level = 0;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
verbose_level = new_level;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void setup_environment(char *var, char *val)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
setenv(var, val, 1);
|
|
Packit |
2d622a |
INFO("%s='%s'\n", var, val);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_dry_run)
|
|
Packit |
2d622a |
printf("%s='%s'\n", var, val);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void verbose_expose(void)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
char level[3];
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (verbose_level == 99) {
|
|
Packit |
2d622a |
setup_environment("HUGETLB_DEBUG", "yes");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
snprintf(level, sizeof(level), "%d", verbose_level);
|
|
Packit |
2d622a |
setup_environment("HUGETLB_VERBOSE", level);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* getopts return values for options which are long only.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
#define MAP_BASE 0x1000
|
|
Packit |
2d622a |
#define LONG_BASE 0x2000
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define LONG_NO_PRELOAD (LONG_BASE | 'p')
|
|
Packit |
2d622a |
#define LONG_NO_RESERVE (LONG_BASE | 'r')
|
|
Packit |
2d622a |
#define LONG_FORCE_PRELOAD (LONG_BASE | 'F')
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define LONG_DRY_RUN (LONG_BASE | 'd')
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define LONG_SHARE (LONG_BASE | 's')
|
|
Packit |
2d622a |
#define LONG_NO_LIBRARY (LONG_BASE | 'L')
|
|
Packit |
2d622a |
#define LONG_LIBRARY (LONG_BASE | 'l')
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define LONG_THP_HEAP ('t')
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* Mapping selectors, one per remappable/backable area as requested
|
|
Packit |
2d622a |
* by the user. These are also used as returns from getopts where they
|
|
Packit |
2d622a |
* are offset from MAP_BASE, which must be removed before they are compared.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
enum {
|
|
Packit |
2d622a |
MAP_TEXT,
|
|
Packit |
2d622a |
MAP_DATA,
|
|
Packit |
2d622a |
MAP_BSS,
|
|
Packit |
2d622a |
MAP_HEAP,
|
|
Packit |
2d622a |
MAP_SHM,
|
|
Packit |
2d622a |
MAP_DISABLE,
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
MAP_COUNT,
|
|
Packit |
2d622a |
};
|
|
Packit |
2d622a |
char *map_size[MAP_COUNT];
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
char default_size[] = "the default hugepage size";
|
|
Packit |
2d622a |
#define DEFAULT_SIZE default_size
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define available(buf, ptr) ((int)(sizeof(buf) - (ptr - buf)))
|
|
Packit |
2d622a |
void setup_mappings(int count)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
char value[128];
|
|
Packit |
2d622a |
char *ptr = value;
|
|
Packit |
2d622a |
int needed;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* HUGETLB_ELFMAP should be set to either a combination of 'R' and 'W'
|
|
Packit |
2d622a |
* which indicate which segments should be remapped. Each may take
|
|
Packit |
2d622a |
* an optional page size. It may also be set to 'no' to prevent
|
|
Packit |
2d622a |
* remapping.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* Accumulate sections each with a ':' prefix to simplify later
|
|
Packit |
2d622a |
* handling. We will elide the initial ':' before use.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
if (map_size[MAP_TEXT]) {
|
|
Packit |
2d622a |
if (map_size[MAP_TEXT] == DEFAULT_SIZE)
|
|
Packit |
2d622a |
needed = snprintf(ptr, available(value, ptr), ":R");
|
|
Packit |
2d622a |
else
|
|
Packit |
2d622a |
needed = snprintf(ptr, available(value, ptr),
|
|
Packit |
2d622a |
":R=%s", map_size[MAP_TEXT]);
|
|
Packit |
2d622a |
ptr += needed;
|
|
Packit |
2d622a |
if (needed < 0 || available(value, ptr) < 0) {
|
|
Packit |
2d622a |
ERROR("%s: bad size specification\n", map_size[MAP_TEXT]);
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
if (map_size[MAP_DATA] != 0 || map_size[MAP_BSS] != 0) {
|
|
Packit |
2d622a |
char *size = map_size[MAP_BSS];
|
|
Packit |
2d622a |
if (map_size[MAP_DATA])
|
|
Packit |
2d622a |
size = map_size[MAP_DATA];
|
|
Packit |
2d622a |
if (map_size[MAP_DATA] != map_size[MAP_BSS])
|
|
Packit |
2d622a |
WARNING("data and bss remapped together in %s\n", size);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (size == DEFAULT_SIZE)
|
|
Packit |
2d622a |
needed = snprintf(ptr, available(value, ptr), ":W");
|
|
Packit |
2d622a |
else
|
|
Packit |
2d622a |
needed = snprintf(ptr, available(value, ptr),
|
|
Packit |
2d622a |
":W=%s", size);
|
|
Packit |
2d622a |
ptr += needed;
|
|
Packit |
2d622a |
if (needed < 0 || available(value, ptr) < 0) {
|
|
Packit |
2d622a |
ERROR("%s: bad size specification\n", size);
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
*ptr = '\0';
|
|
Packit |
2d622a |
if (ptr != value)
|
|
Packit |
2d622a |
setup_environment("HUGETLB_ELFMAP", &value[1]);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (map_size[MAP_DISABLE]) {
|
|
Packit |
2d622a |
if (ptr != value)
|
|
Packit |
2d622a |
WARNING("--disable masks requested remap\n");
|
|
Packit |
2d622a |
setup_environment("HUGETLB_ELFMAP", "no");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (map_size[MAP_HEAP] == DEFAULT_SIZE)
|
|
Packit |
2d622a |
setup_environment("HUGETLB_MORECORE", "yes");
|
|
Packit |
2d622a |
else if (map_size[MAP_HEAP])
|
|
Packit |
2d622a |
setup_environment("HUGETLB_MORECORE", map_size[MAP_HEAP]);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (map_size[MAP_SHM] && map_size[MAP_SHM] != DEFAULT_SIZE)
|
|
Packit |
2d622a |
WARNING("shm segments may only be mapped in the "
|
|
Packit |
2d622a |
"default hugepage size\n");
|
|
Packit |
2d622a |
if (map_size[MAP_SHM])
|
|
Packit |
2d622a |
setup_environment("HUGETLB_SHM", "yes");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
#define LIBRARY_DISABLE ((void *)-1)
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void library_path(char *path)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
char val[PATH_MAX] = "";
|
|
Packit |
2d622a |
char *env;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
env = getenv("LD_LIBRARY_PATH");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
/*
|
|
Packit |
2d622a |
* Select which libraries we wish to use. If the path is NULL
|
|
Packit |
2d622a |
* use the libraries included with hugectl. If the path is valid
|
|
Packit |
2d622a |
* and points to a directory including a libhugetlbfs.so use it
|
|
Packit |
2d622a |
* directly. Else path is assumed to be a prefix to the 32/64 bit
|
|
Packit |
2d622a |
* directories both of which are added, where available.
|
|
Packit |
2d622a |
*/
|
|
Packit |
2d622a |
if (path) {
|
|
Packit |
2d622a |
snprintf(val, sizeof(val), "%s/libhugetlbfs.so", path);
|
|
Packit |
2d622a |
if (access(val, F_OK) == 0) {
|
|
Packit |
2d622a |
/* $PATH */
|
|
Packit |
2d622a |
snprintf(val, sizeof(val), "%s:%s",
|
|
Packit |
2d622a |
path, env ? env : "");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
} else {
|
|
Packit |
2d622a |
/* [$PATH/LIB32:][$PATH/LIB64:]$LD_LIBRARY_PATH */
|
|
Packit |
2d622a |
snprintf(val, sizeof(val), ""
|
|
Packit |
2d622a |
#ifdef LIBDIR32
|
|
Packit |
2d622a |
"%s/" LIB32 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
#ifdef LIBDIR64
|
|
Packit |
2d622a |
"%s/" LIB64 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
"%s",
|
|
Packit |
2d622a |
#ifdef LIBDIR32
|
|
Packit |
2d622a |
path,
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
#ifdef LIBDIR64
|
|
Packit |
2d622a |
path,
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
env ? env : "");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
} else {
|
|
Packit |
2d622a |
/* [LIBDIR32:][LIBDIR64:]$LD_LIBRARY_PATH */
|
|
Packit |
2d622a |
snprintf(val, sizeof(val), ""
|
|
Packit |
2d622a |
#ifdef LIBDIR32
|
|
Packit |
2d622a |
LIBDIR32 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
#ifdef LIBDIR64
|
|
Packit |
2d622a |
LIBDIR64 ":"
|
|
Packit |
2d622a |
#endif
|
|
Packit |
2d622a |
"%s", env ? env : "");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
setup_environment("LD_LIBRARY_PATH", val);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
void ldpreload(int count)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
int allowed = 0;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (map_size[MAP_HEAP])
|
|
Packit |
2d622a |
allowed++;
|
|
Packit |
2d622a |
if (map_size[MAP_SHM])
|
|
Packit |
2d622a |
allowed++;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if ((allowed == count) || opt_force_preload) {
|
|
Packit |
2d622a |
setup_environment("LD_PRELOAD", "libhugetlbfs.so");
|
|
Packit |
2d622a |
if (allowed == count)
|
|
Packit |
2d622a |
INFO("LD_PRELOAD in use for lone --heap/--shm\n");
|
|
Packit |
2d622a |
} else {
|
|
Packit |
2d622a |
WARNING("LD_PRELOAD not appropriate for this map combination\n");
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
int main(int argc, char** argv)
|
|
Packit |
2d622a |
{
|
|
Packit |
2d622a |
int opt_mappings = 0;
|
|
Packit |
2d622a |
int opt_preload = 1;
|
|
Packit |
2d622a |
int opt_no_reserve = 0;
|
|
Packit |
2d622a |
int opt_share = 0;
|
|
Packit |
2d622a |
int opt_thp_heap = 0;
|
|
Packit |
2d622a |
char *opt_library = NULL;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
char opts[] = "+hvq";
|
|
Packit |
2d622a |
int ret = 0, index = 0;
|
|
Packit |
2d622a |
struct option long_opts[] = {
|
|
Packit |
2d622a |
{"help", no_argument, NULL, 'h'},
|
|
Packit |
2d622a |
{"verbose", required_argument, NULL, 'v' },
|
|
Packit |
2d622a |
{"no-preload", no_argument, NULL, LONG_NO_PRELOAD},
|
|
Packit |
2d622a |
{"no-reserve", no_argument, NULL, LONG_NO_RESERVE},
|
|
Packit |
2d622a |
{"force-preload",
|
|
Packit |
2d622a |
no_argument, NULL, LONG_FORCE_PRELOAD},
|
|
Packit |
2d622a |
{"dry-run", no_argument, NULL, LONG_DRY_RUN},
|
|
Packit |
2d622a |
{"library-path",
|
|
Packit |
2d622a |
required_argument, NULL, LONG_LIBRARY},
|
|
Packit |
2d622a |
{"library-use-path",
|
|
Packit |
2d622a |
no_argument, NULL, LONG_NO_LIBRARY},
|
|
Packit |
2d622a |
{"share-text", no_argument, NULL, LONG_SHARE},
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
{"disable", optional_argument, NULL, MAP_BASE|MAP_DISABLE},
|
|
Packit |
2d622a |
{"text", optional_argument, NULL, MAP_BASE|MAP_TEXT},
|
|
Packit |
2d622a |
{"data", optional_argument, NULL, MAP_BASE|MAP_DATA},
|
|
Packit |
2d622a |
{"bss", optional_argument, NULL, MAP_BASE|MAP_BSS},
|
|
Packit |
2d622a |
{"heap", optional_argument, NULL, MAP_BASE|MAP_HEAP},
|
|
Packit |
2d622a |
{"shm", optional_argument, NULL, MAP_BASE|MAP_SHM},
|
|
Packit |
2d622a |
{"thp", no_argument, NULL, LONG_THP_HEAP},
|
|
Packit |
2d622a |
{0},
|
|
Packit |
2d622a |
};
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
verbose_init();
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
while (ret != -1) {
|
|
Packit |
2d622a |
ret = getopt_long(argc, argv, opts, long_opts, &index);
|
|
Packit |
2d622a |
if (ret > 0 && (ret & MAP_BASE)) {
|
|
Packit |
2d622a |
if (optarg)
|
|
Packit |
2d622a |
map_size[ret & ~MAP_BASE] = optarg;
|
|
Packit |
2d622a |
else
|
|
Packit |
2d622a |
map_size[ret & ~MAP_BASE] = DEFAULT_SIZE;
|
|
Packit |
2d622a |
opt_mappings++;
|
|
Packit |
2d622a |
continue;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
switch (ret) {
|
|
Packit |
2d622a |
case '?':
|
|
Packit |
2d622a |
print_usage();
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case 'h':
|
|
Packit |
2d622a |
print_usage();
|
|
Packit |
2d622a |
exit(EXIT_SUCCESS);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case 'v':
|
|
Packit |
2d622a |
verbose(optarg);
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case 'q':
|
|
Packit |
2d622a |
quiet();
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_THP_HEAP:
|
|
Packit |
2d622a |
opt_thp_heap = 1;
|
|
Packit |
2d622a |
INFO("Aligning heap for use with THP\n");
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_NO_PRELOAD:
|
|
Packit |
2d622a |
opt_preload = 0;
|
|
Packit |
2d622a |
INFO("LD_PRELOAD disabled\n");
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_NO_RESERVE:
|
|
Packit |
2d622a |
opt_no_reserve = 1;
|
|
Packit |
2d622a |
INFO("MAP_NORESERVE used for huge page mappings\n");
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_FORCE_PRELOAD:
|
|
Packit |
2d622a |
opt_preload = 1;
|
|
Packit |
2d622a |
opt_force_preload = 1;
|
|
Packit |
2d622a |
INFO("Forcing ld preload\n");
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_DRY_RUN:
|
|
Packit |
2d622a |
opt_dry_run = 1;
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_NO_LIBRARY:
|
|
Packit |
2d622a |
opt_library = LIBRARY_DISABLE;
|
|
Packit |
2d622a |
INFO("using LD_LIBRARY_PATH to find library\n");
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_LIBRARY:
|
|
Packit |
2d622a |
opt_library = optarg;
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case LONG_SHARE:
|
|
Packit |
2d622a |
opt_share = 1;
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
case -1:
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
default:
|
|
Packit |
2d622a |
WARNING("unparsed option %08x\n", ret);
|
|
Packit |
2d622a |
ret = -1;
|
|
Packit |
2d622a |
break;
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
index = optind;
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (!opt_dry_run && (argc - index) < 1) {
|
|
Packit |
2d622a |
print_usage();
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
}
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
verbose_expose();
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_library != LIBRARY_DISABLE)
|
|
Packit |
2d622a |
library_path(opt_library);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_mappings)
|
|
Packit |
2d622a |
setup_mappings(opt_mappings);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_preload)
|
|
Packit |
2d622a |
ldpreload(opt_mappings);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_no_reserve)
|
|
Packit |
2d622a |
setup_environment("HUGETLB_NO_RESERVE", "yes");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_share)
|
|
Packit |
2d622a |
setup_environment("HUGETLB_SHARE", "1");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_thp_heap)
|
|
Packit |
2d622a |
setup_environment("HUGETLB_MORECORE", "thp");
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
if (opt_dry_run)
|
|
Packit |
2d622a |
exit(EXIT_SUCCESS);
|
|
Packit |
2d622a |
|
|
Packit |
2d622a |
execvp(argv[index], &argv[index]);
|
|
Packit |
2d622a |
ERROR("exec failed: %s\n", strerror(errno));
|
|
Packit |
2d622a |
exit(EXIT_FAILURE);
|
|
Packit |
2d622a |
}
|