1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * memtoy: commands.c - command line interface 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * A brute force/ad hoc command interpreter: 5f08c3bdfSopenharmony_ci * + parse commands [interactive or batch] 6f08c3bdfSopenharmony_ci * + convert/validate arguments 7f08c3bdfSopenharmony_ci * + some general/administrative commands herein 8f08c3bdfSopenharmony_ci * + actual segment management routines in segment.c 9f08c3bdfSopenharmony_ci */ 10f08c3bdfSopenharmony_ci/* 11f08c3bdfSopenharmony_ci * Copyright (c) 2005 Hewlett-Packard, Inc 12f08c3bdfSopenharmony_ci * All rights reserved. 13f08c3bdfSopenharmony_ci */ 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci/* 16f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 17f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 18f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 19f08c3bdfSopenharmony_ci * (at your option) any later version. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 22f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 23f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24f08c3bdfSopenharmony_ci * GNU General Public License for more details. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 27f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 28f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29f08c3bdfSopenharmony_ci */ 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#include "config.h" 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 34f08c3bdfSopenharmony_ci#include <sys/types.h> 35f08c3bdfSopenharmony_ci#include <sys/time.h> 36f08c3bdfSopenharmony_ci#include <sys/mman.h> 37f08c3bdfSopenharmony_ci#include <ctype.h> 38f08c3bdfSopenharmony_ci#include <errno.h> 39f08c3bdfSopenharmony_ci#include <fcntl.h> 40f08c3bdfSopenharmony_ci#include <numa.h> 41f08c3bdfSopenharmony_ci#include <numaif.h> 42f08c3bdfSopenharmony_ci#include <stdarg.h> 43f08c3bdfSopenharmony_ci#include <stdlib.h> 44f08c3bdfSopenharmony_ci#include <stdio.h> 45f08c3bdfSopenharmony_ci#include <string.h> 46f08c3bdfSopenharmony_ci#include <unistd.h> 47f08c3bdfSopenharmony_ci#include <sys/syscall.h> 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci#include "memtoy.h" 50f08c3bdfSopenharmony_ci#include "test.h" 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci#define CMD_SUCCESS 0 53f08c3bdfSopenharmony_ci#define CMD_ERROR 1 54f08c3bdfSopenharmony_ci#define CMDBUFSZ 256 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci#ifndef __NR_migrate_pages 57f08c3bdfSopenharmony_ci#define __NR_migrate_pages 0 58f08c3bdfSopenharmony_ci#endif 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci#ifndef MPOL_MF_WAIT 61f08c3bdfSopenharmony_ci#define MPOL_MF_WAIT (1<<2) /* Wait for existing pages to migrate */ 62f08c3bdfSopenharmony_ci#endif 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_cistatic inline int nodemask_isset(nodemask_t * mask, int node) 65f08c3bdfSopenharmony_ci{ 66f08c3bdfSopenharmony_ci if ((unsigned)node >= NUMA_NUM_NODES) 67f08c3bdfSopenharmony_ci return 0; 68f08c3bdfSopenharmony_ci if (mask->n[node / (8 * sizeof(unsigned long))] & 69f08c3bdfSopenharmony_ci (1UL << (node % (8 * sizeof(unsigned long))))) 70f08c3bdfSopenharmony_ci return 1; 71f08c3bdfSopenharmony_ci return 0; 72f08c3bdfSopenharmony_ci} 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_cistatic inline void nodemask_set(nodemask_t * mask, int node) 75f08c3bdfSopenharmony_ci{ 76f08c3bdfSopenharmony_ci mask->n[node / (8 * sizeof(unsigned long))] |= 77f08c3bdfSopenharmony_ci (1UL << (node % (8 * sizeof(unsigned long)))); 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic char *whitespace = " \t"; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ciinline char *get_next_arg(char *args, char *nextarg) 83f08c3bdfSopenharmony_ci{ 84f08c3bdfSopenharmony_ci return nextarg ? nextarg + strspn(nextarg, whitespace) : args + strnlen(args, CMDBUFSZ); 85f08c3bdfSopenharmony_ci} 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci/* 88f08c3bdfSopenharmony_ci * ========================================================================= 89f08c3bdfSopenharmony_ci */ 90f08c3bdfSopenharmony_cistatic int help_me(char *); /* forward reference */ 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci/* 93f08c3bdfSopenharmony_ci * required_arg -- check for a required argument; issue message if not there 94f08c3bdfSopenharmony_ci * 95f08c3bdfSopenharmony_ci * return true if arg [something] exists; else return false 96f08c3bdfSopenharmony_ci */ 97f08c3bdfSopenharmony_cistatic bool required_arg(char *arg, char *arg_name) 98f08c3bdfSopenharmony_ci{ 99f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if (*arg != '\0') 102f08c3bdfSopenharmony_ci return true; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci fprintf(stderr, "%s: command '%s' missing required argument: %s\n\n", 105f08c3bdfSopenharmony_ci gcp->program_name, gcp->cmd_name, arg_name); 106f08c3bdfSopenharmony_ci help_me(gcp->cmd_name); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci return false; 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci/* 112f08c3bdfSopenharmony_ci * size_kmgp() -- convert ascii arg to numeric and scale as requested 113f08c3bdfSopenharmony_ci */ 114f08c3bdfSopenharmony_ci#define KILO_SHIFT 10 115f08c3bdfSopenharmony_cistatic size_t size_kmgp(char *arg) 116f08c3bdfSopenharmony_ci{ 117f08c3bdfSopenharmony_ci size_t argval; 118f08c3bdfSopenharmony_ci char *next; 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci argval = strtoul(arg, &next, 0); 121f08c3bdfSopenharmony_ci if (*next == '\0') 122f08c3bdfSopenharmony_ci return argval; 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci switch (tolower(*next)) { 125f08c3bdfSopenharmony_ci case 'p': /* pages */ 126f08c3bdfSopenharmony_ci argval *= glctx.pagesize; 127f08c3bdfSopenharmony_ci break; 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci case 'k': 130f08c3bdfSopenharmony_ci argval <<= KILO_SHIFT; 131f08c3bdfSopenharmony_ci break; 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci case 'm': 134f08c3bdfSopenharmony_ci argval <<= KILO_SHIFT * 2; 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci case 'g': 138f08c3bdfSopenharmony_ci argval <<= KILO_SHIFT * 3; 139f08c3bdfSopenharmony_ci break; 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci default: 142f08c3bdfSopenharmony_ci return BOGUS_SIZE; /* bogus chars after number */ 143f08c3bdfSopenharmony_ci } 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci return argval; 146f08c3bdfSopenharmony_ci} 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_cistatic size_t get_scaled_value(char *args, char *what) 149f08c3bdfSopenharmony_ci{ 150f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 151f08c3bdfSopenharmony_ci size_t size = size_kmgp(args); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci if (size == BOGUS_SIZE) { 154f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment %s must be numeric value" 155f08c3bdfSopenharmony_ci " followed by optional k, m, g or p [pages] scale factor.\n", 156f08c3bdfSopenharmony_ci gcp->program_name, what); 157f08c3bdfSopenharmony_ci } 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci return size; 160f08c3bdfSopenharmony_ci} 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_cistatic int get_range(char *args, range_t * range, char **nextarg) 163f08c3bdfSopenharmony_ci{ 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci if (isdigit(*args)) { 166f08c3bdfSopenharmony_ci char *nextarg; 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci args = strtok_r(args, whitespace, &nextarg); 169f08c3bdfSopenharmony_ci range->offset = get_scaled_value(args, "offset"); 170f08c3bdfSopenharmony_ci if (range->offset == BOGUS_SIZE) 171f08c3bdfSopenharmony_ci return CMD_ERROR; 172f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci /* 175f08c3bdfSopenharmony_ci * <length> ... only if offset specified 176f08c3bdfSopenharmony_ci */ 177f08c3bdfSopenharmony_ci if (*args != '\0') { 178f08c3bdfSopenharmony_ci args = strtok_r(args, whitespace, &nextarg); 179f08c3bdfSopenharmony_ci if (*args != '*') { 180f08c3bdfSopenharmony_ci range->length = 181f08c3bdfSopenharmony_ci get_scaled_value(args, "length"); 182f08c3bdfSopenharmony_ci if (range->length == BOGUS_SIZE) 183f08c3bdfSopenharmony_ci return CMD_ERROR; 184f08c3bdfSopenharmony_ci } else 185f08c3bdfSopenharmony_ci range->length = 0; /* map to end of file */ 186f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 187f08c3bdfSopenharmony_ci } 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci *nextarg = args; 191f08c3bdfSopenharmony_ci return CMD_SUCCESS; 192f08c3bdfSopenharmony_ci} 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_cistatic int get_shared(char *args) 195f08c3bdfSopenharmony_ci{ 196f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 197f08c3bdfSopenharmony_ci int segflag = MAP_PRIVATE; 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci if (!strcmp(args, "shared")) 200f08c3bdfSopenharmony_ci segflag = MAP_SHARED; 201f08c3bdfSopenharmony_ci else if (*args != '\0' && strcmp(args, "private")) { 202f08c3bdfSopenharmony_ci fprintf(stderr, "%s: anon seg access type must be one of: " 203f08c3bdfSopenharmony_ci "'private' or 'shared'\n", gcp->program_name); 204f08c3bdfSopenharmony_ci return -1; 205f08c3bdfSopenharmony_ci } 206f08c3bdfSopenharmony_ci return segflag; 207f08c3bdfSopenharmony_ci} 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci/* 210f08c3bdfSopenharmony_ci * get_access() - check args for 'read'\'write' 211f08c3bdfSopenharmony_ci * return: 212f08c3bdfSopenharmony_ci * 1 = read 213f08c3bdfSopenharmony_ci * 2 = write 214f08c3bdfSopenharmony_ci * 0 = neither [error] 215f08c3bdfSopenharmony_ci */ 216f08c3bdfSopenharmony_cistatic int get_access(char *args) 217f08c3bdfSopenharmony_ci{ 218f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 219f08c3bdfSopenharmony_ci int axcs = 1; 220f08c3bdfSopenharmony_ci int len = strlen(args); 221f08c3bdfSopenharmony_ci 222f08c3bdfSopenharmony_ci if (tolower(*args) == 'w') 223f08c3bdfSopenharmony_ci axcs = 2; 224f08c3bdfSopenharmony_ci else if (len != 0 && tolower(*args) != 'r') { 225f08c3bdfSopenharmony_ci fprintf(stderr, 226f08c3bdfSopenharmony_ci "%s: segment access must be 'r[ead]' or 'w[rite]'\n", 227f08c3bdfSopenharmony_ci gcp->program_name); 228f08c3bdfSopenharmony_ci return 0; 229f08c3bdfSopenharmony_ci } 230f08c3bdfSopenharmony_ci 231f08c3bdfSopenharmony_ci return axcs; 232f08c3bdfSopenharmony_ci} 233f08c3bdfSopenharmony_ci 234f08c3bdfSopenharmony_cistatic bool numa_supported(void) 235f08c3bdfSopenharmony_ci{ 236f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci if (gcp->numa_max_node <= 0) { 239f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no NUMA support on this platform\n", 240f08c3bdfSopenharmony_ci gcp->program_name); 241f08c3bdfSopenharmony_ci return false; 242f08c3bdfSopenharmony_ci } 243f08c3bdfSopenharmony_ci return true; 244f08c3bdfSopenharmony_ci} 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_cistatic struct policies { 247f08c3bdfSopenharmony_ci char *pol_name; 248f08c3bdfSopenharmony_ci int pol_flag; 249f08c3bdfSopenharmony_ci} policies[] = { 250f08c3bdfSopenharmony_ci { 251f08c3bdfSopenharmony_ci "default", MPOL_DEFAULT}, { 252f08c3bdfSopenharmony_ci "preferred", MPOL_PREFERRED}, { 253f08c3bdfSopenharmony_ci "bind", MPOL_BIND}, { 254f08c3bdfSopenharmony_ci "interleaved", MPOL_INTERLEAVE}, { 255f08c3bdfSopenharmony_ci NULL, -1} 256f08c3bdfSopenharmony_ci}; 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci/* 259f08c3bdfSopenharmony_ci * get_mbind_policy() - parse <policy> argument to mbind command 260f08c3bdfSopenharmony_ci * 261f08c3bdfSopenharmony_ci * format: <mpol>[+<flags>] 262f08c3bdfSopenharmony_ci * <mpol> is one of the policies[] above. 263f08c3bdfSopenharmony_ci * '+<flags>' = modifiers to mbind() call. parsed by get_mbind_flags() 264f08c3bdfSopenharmony_ci */ 265f08c3bdfSopenharmony_cistatic int get_mbind_policy(char *args, char **nextarg) 266f08c3bdfSopenharmony_ci{ 267f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 268f08c3bdfSopenharmony_ci struct policies *polp; 269f08c3bdfSopenharmony_ci char *pol; 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_ci pol = args; 272f08c3bdfSopenharmony_ci args += strcspn(args, " +"); 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci for (polp = policies; polp->pol_name != NULL; ++polp) { 275f08c3bdfSopenharmony_ci size_t plen = args - pol; 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci if (strncmp(pol, polp->pol_name, plen)) 278f08c3bdfSopenharmony_ci continue; 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci *nextarg = args; 281f08c3bdfSopenharmony_ci return polp->pol_flag; 282f08c3bdfSopenharmony_ci } 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci fprintf(stderr, "%s: unrecognized policy %s\n", 285f08c3bdfSopenharmony_ci gcp->program_name, pol); 286f08c3bdfSopenharmony_ci return CMD_ERROR; 287f08c3bdfSopenharmony_ci} 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci/* 290f08c3bdfSopenharmony_ci * get_mbind_flags() - parse mbind(2) modifier flags 291f08c3bdfSopenharmony_ci * 292f08c3bdfSopenharmony_ci * format: +move[+wait] 293f08c3bdfSopenharmony_ci * 'move' specifies that currently allocated pages should be migrated. 294f08c3bdfSopenharmony_ci * => MPOL_MF_MOVE 295f08c3bdfSopenharmony_ci * 'wait' [only if 'move' specified] specifies that mbind(2) should not 296f08c3bdfSopenharmony_ci * return until all pages that can be migrated have been. 297f08c3bdfSopenharmony_ci * => MPOL_MF_WAIT 298f08c3bdfSopenharmony_ci * 299f08c3bdfSopenharmony_ci * returns flags on success; -1 on error 300f08c3bdfSopenharmony_ci */ 301f08c3bdfSopenharmony_cistatic int get_mbind_flags(char *args, char **nextarg) 302f08c3bdfSopenharmony_ci{ 303f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 304f08c3bdfSopenharmony_ci char *arg; 305f08c3bdfSopenharmony_ci int flags = 0; 306f08c3bdfSopenharmony_ci 307f08c3bdfSopenharmony_ci arg = args; 308f08c3bdfSopenharmony_ci args += strcspn(args, " +"); 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci if (strncmp(arg, "move", args - arg)) 311f08c3bdfSopenharmony_ci goto flags_err; 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci flags = MPOL_MF_MOVE; 314f08c3bdfSopenharmony_ci 315f08c3bdfSopenharmony_ci if (*args == '+') { 316f08c3bdfSopenharmony_ci ++args; 317f08c3bdfSopenharmony_ci if (*args == '\0') { 318f08c3bdfSopenharmony_ci fprintf(stderr, "%s: expected 'wait' after '+'\n", 319f08c3bdfSopenharmony_ci gcp->program_name); 320f08c3bdfSopenharmony_ci return -1; 321f08c3bdfSopenharmony_ci } 322f08c3bdfSopenharmony_ci arg = strtok_r(args, " ", &args); 323f08c3bdfSopenharmony_ci if (strncmp(arg, "wait", strlen(arg))) 324f08c3bdfSopenharmony_ci goto flags_err; 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci flags |= MPOL_MF_WAIT; 327f08c3bdfSopenharmony_ci } 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_ci *nextarg = args; 330f08c3bdfSopenharmony_ci return flags; 331f08c3bdfSopenharmony_ci 332f08c3bdfSopenharmony_ciflags_err: 333f08c3bdfSopenharmony_ci fprintf(stderr, "%s: unrecognized mbind flag: %s\n", 334f08c3bdfSopenharmony_ci gcp->program_name, arg); 335f08c3bdfSopenharmony_ci return -1; 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci} 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci/* 340f08c3bdfSopenharmony_ci * get_nodemask() -- get nodemask from comma-separated list of node ids. 341f08c3bdfSopenharmony_ci * 342f08c3bdfSopenharmony_ci * N.B., caller must free returned nodemask 343f08c3bdfSopenharmony_ci */ 344f08c3bdfSopenharmony_cistatic nodemask_t *get_nodemask(char *args) 345f08c3bdfSopenharmony_ci{ 346f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 347f08c3bdfSopenharmony_ci nodemask_t *nmp = (nodemask_t *) calloc(1, sizeof(nodemask_t)); 348f08c3bdfSopenharmony_ci char *next; 349f08c3bdfSopenharmony_ci int node; 350f08c3bdfSopenharmony_ci while (*args != '\0') { 351f08c3bdfSopenharmony_ci if (!isdigit(*args)) { 352f08c3bdfSopenharmony_ci fprintf(stderr, "%s: expected digit for <node/list>\n", 353f08c3bdfSopenharmony_ci gcp->program_name); 354f08c3bdfSopenharmony_ci goto out_err; 355f08c3bdfSopenharmony_ci } 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ci node = strtoul(args, &next, 10); 358f08c3bdfSopenharmony_ci 359f08c3bdfSopenharmony_ci if (node > gcp->numa_max_node) { 360f08c3bdfSopenharmony_ci fprintf(stderr, "%s: node ids must be <= %d\n", 361f08c3bdfSopenharmony_ci gcp->program_name, gcp->numa_max_node); 362f08c3bdfSopenharmony_ci goto out_err; 363f08c3bdfSopenharmony_ci } 364f08c3bdfSopenharmony_ci 365f08c3bdfSopenharmony_ci nodemask_set(nmp, node); 366f08c3bdfSopenharmony_ci 367f08c3bdfSopenharmony_ci if (*next == '\0') 368f08c3bdfSopenharmony_ci return nmp; 369f08c3bdfSopenharmony_ci if (*next != ',') { 370f08c3bdfSopenharmony_ci break; 371f08c3bdfSopenharmony_ci } 372f08c3bdfSopenharmony_ci args = next + 1; 373f08c3bdfSopenharmony_ci } 374f08c3bdfSopenharmony_ci 375f08c3bdfSopenharmony_ciout_err: 376f08c3bdfSopenharmony_ci free(nmp); 377f08c3bdfSopenharmony_ci return NULL; 378f08c3bdfSopenharmony_ci} 379f08c3bdfSopenharmony_ci 380f08c3bdfSopenharmony_ci/* 381f08c3bdfSopenharmony_ci * get_arg_nodeid_list() -- get list [array] of node ids from comma-separated list. 382f08c3bdfSopenharmony_ci * 383f08c3bdfSopenharmony_ci * on success, returns count of id's in list; on error -1 384f08c3bdfSopenharmony_ci */ 385f08c3bdfSopenharmony_cistatic int get_arg_nodeid_list(char *args, unsigned int *list) 386f08c3bdfSopenharmony_ci{ 387f08c3bdfSopenharmony_ci glctx_t *gcp; 388f08c3bdfSopenharmony_ci char *next; 389f08c3bdfSopenharmony_ci nodemask_t my_allowed_nodes; 390f08c3bdfSopenharmony_ci int node, count = 0; 391f08c3bdfSopenharmony_ci 392f08c3bdfSopenharmony_ci gcp = &glctx; 393f08c3bdfSopenharmony_ci my_allowed_nodes = numa_get_membind_compat(); 394f08c3bdfSopenharmony_ci while (*args != '\0') { 395f08c3bdfSopenharmony_ci if (!isdigit(*args)) { 396f08c3bdfSopenharmony_ci fprintf(stderr, "%s: expected digit for <node/list>\n", 397f08c3bdfSopenharmony_ci gcp->program_name); 398f08c3bdfSopenharmony_ci return -1; 399f08c3bdfSopenharmony_ci } 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci node = strtoul(args, &next, 10); 402f08c3bdfSopenharmony_ci 403f08c3bdfSopenharmony_ci if (node > gcp->numa_max_node) { 404f08c3bdfSopenharmony_ci fprintf(stderr, "%s: node ids must be <= %d\n", 405f08c3bdfSopenharmony_ci gcp->program_name, gcp->numa_max_node); 406f08c3bdfSopenharmony_ci return -1; 407f08c3bdfSopenharmony_ci } 408f08c3bdfSopenharmony_ci 409f08c3bdfSopenharmony_ci if (!nodemask_isset(&my_allowed_nodes, node)) { 410f08c3bdfSopenharmony_ci fprintf(stderr, 411f08c3bdfSopenharmony_ci "%s: node %d is not in my allowed node mask\n", 412f08c3bdfSopenharmony_ci gcp->program_name, node); 413f08c3bdfSopenharmony_ci return -1; 414f08c3bdfSopenharmony_ci } 415f08c3bdfSopenharmony_ci 416f08c3bdfSopenharmony_ci *(list + count++) = node; 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci if (*next == '\0') 419f08c3bdfSopenharmony_ci return count; 420f08c3bdfSopenharmony_ci if (*next != ',') { 421f08c3bdfSopenharmony_ci break; 422f08c3bdfSopenharmony_ci } 423f08c3bdfSopenharmony_ci 424f08c3bdfSopenharmony_ci if (count >= gcp->numa_max_node) { 425f08c3bdfSopenharmony_ci fprintf(stderr, "%s: too many node ids in list\n", 426f08c3bdfSopenharmony_ci gcp->program_name); 427f08c3bdfSopenharmony_ci } 428f08c3bdfSopenharmony_ci args = next + 1; 429f08c3bdfSopenharmony_ci } 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci return -1; 432f08c3bdfSopenharmony_ci} 433f08c3bdfSopenharmony_ci 434f08c3bdfSopenharmony_ci/* 435f08c3bdfSopenharmony_ci * get_current_nodeid_list() - fill arg array with nodes from 436f08c3bdfSopenharmony_ci * current thread's allowed node mask. return # of nodes in 437f08c3bdfSopenharmony_ci * mask. 438f08c3bdfSopenharmony_ci */ 439f08c3bdfSopenharmony_cistatic int get_current_nodeid_list(unsigned int *fromids) 440f08c3bdfSopenharmony_ci{ 441f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 442f08c3bdfSopenharmony_ci nodemask_t my_allowed_nodes; 443f08c3bdfSopenharmony_ci int nr_nodes = 0, max_node = gcp->numa_max_node; 444f08c3bdfSopenharmony_ci int node; 445f08c3bdfSopenharmony_ci 446f08c3bdfSopenharmony_ci my_allowed_nodes = numa_get_membind_compat(); 447f08c3bdfSopenharmony_ci for (node = 0; node <= max_node; ++node) { 448f08c3bdfSopenharmony_ci if (nodemask_isset(&my_allowed_nodes, node)) 449f08c3bdfSopenharmony_ci *(fromids + nr_nodes++) = node; 450f08c3bdfSopenharmony_ci } 451f08c3bdfSopenharmony_ci 452f08c3bdfSopenharmony_ci /* 453f08c3bdfSopenharmony_ci * shouldn't happen, but let 'em know if it does 454f08c3bdfSopenharmony_ci */ 455f08c3bdfSopenharmony_ci if (nr_nodes == 0) 456f08c3bdfSopenharmony_ci fprintf(stderr, "%s: my allowed node mask is empty !!???\n", 457f08c3bdfSopenharmony_ci gcp->program_name); 458f08c3bdfSopenharmony_ci return nr_nodes; 459f08c3bdfSopenharmony_ci} 460f08c3bdfSopenharmony_ci 461f08c3bdfSopenharmony_ci/* 462f08c3bdfSopenharmony_ci * NOTE (garrcoop): Get rid of an -Wunused warning. This wasn't deleted because 463f08c3bdfSopenharmony_ci * I don't know what the original intent was for this code. 464f08c3bdfSopenharmony_ci */ 465f08c3bdfSopenharmony_ci#if 0 466f08c3bdfSopenharmony_cistatic void not_implemented() 467f08c3bdfSopenharmony_ci{ 468f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 469f08c3bdfSopenharmony_ci 470f08c3bdfSopenharmony_ci fprintf(stderr, "%s: %s not implemented yet\n", 471f08c3bdfSopenharmony_ci gcp->program_name, gcp->cmd_name); 472f08c3bdfSopenharmony_ci} 473f08c3bdfSopenharmony_ci#endif 474f08c3bdfSopenharmony_ci 475f08c3bdfSopenharmony_ci/* 476f08c3bdfSopenharmony_ci * ========================================================================= 477f08c3bdfSopenharmony_ci */ 478f08c3bdfSopenharmony_cistatic int quit(char *args) 479f08c3bdfSopenharmony_ci{ 480f08c3bdfSopenharmony_ci exit(0); /* let cleanup() do its thing */ 481f08c3bdfSopenharmony_ci} 482f08c3bdfSopenharmony_ci 483f08c3bdfSopenharmony_cistatic int show_pid(char *args) 484f08c3bdfSopenharmony_ci{ 485f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 486f08c3bdfSopenharmony_ci 487f08c3bdfSopenharmony_ci printf("%s: pid = %d\n", gcp->program_name, getpid()); 488f08c3bdfSopenharmony_ci 489f08c3bdfSopenharmony_ci return CMD_SUCCESS; 490f08c3bdfSopenharmony_ci} 491f08c3bdfSopenharmony_ci 492f08c3bdfSopenharmony_cistatic int pause_me(char *args) 493f08c3bdfSopenharmony_ci{ 494f08c3bdfSopenharmony_ci // glctx_t *gcp = &glctx; 495f08c3bdfSopenharmony_ci 496f08c3bdfSopenharmony_ci pause(); 497f08c3bdfSopenharmony_ci reset_signal(); 498f08c3bdfSopenharmony_ci 499f08c3bdfSopenharmony_ci return CMD_SUCCESS; 500f08c3bdfSopenharmony_ci} 501f08c3bdfSopenharmony_ci 502f08c3bdfSopenharmony_cistatic char *numa_header = " Node Total Mem[MB] Free Mem[MB]\n"; 503f08c3bdfSopenharmony_cistatic int numa_info(char *args) 504f08c3bdfSopenharmony_ci{ 505f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 506f08c3bdfSopenharmony_ci unsigned int *nodeids; 507f08c3bdfSopenharmony_ci int nr_nodes, i; 508f08c3bdfSopenharmony_ci bool do_header = true; 509f08c3bdfSopenharmony_ci 510f08c3bdfSopenharmony_ci if (!numa_supported()) 511f08c3bdfSopenharmony_ci return CMD_ERROR; 512f08c3bdfSopenharmony_ci 513f08c3bdfSopenharmony_ci nodeids = calloc(gcp->numa_max_node, sizeof(*nodeids)); 514f08c3bdfSopenharmony_ci nr_nodes = get_current_nodeid_list(nodeids); 515f08c3bdfSopenharmony_ci if (nr_nodes < 0) 516f08c3bdfSopenharmony_ci return CMD_ERROR; 517f08c3bdfSopenharmony_ci 518f08c3bdfSopenharmony_ci for (i = 0; i < nr_nodes; ++i) { 519f08c3bdfSopenharmony_ci int node = nodeids[i]; 520f08c3bdfSopenharmony_ci long node_size, node_free; 521f08c3bdfSopenharmony_ci 522f08c3bdfSopenharmony_ci node_size = numa_node_size(node, &node_free); 523f08c3bdfSopenharmony_ci if (node_size < 0) { 524f08c3bdfSopenharmony_ci fprintf(stderr, 525f08c3bdfSopenharmony_ci "%s: numa_node_size() failed for node %d\n", 526f08c3bdfSopenharmony_ci gcp->program_name, node); 527f08c3bdfSopenharmony_ci return CMD_ERROR; 528f08c3bdfSopenharmony_ci } 529f08c3bdfSopenharmony_ci 530f08c3bdfSopenharmony_ci if (do_header) { 531f08c3bdfSopenharmony_ci do_header = false; 532f08c3bdfSopenharmony_ci puts(numa_header); 533f08c3bdfSopenharmony_ci } 534f08c3bdfSopenharmony_ci printf(" %3d %9ld %8ld\n", node, 535f08c3bdfSopenharmony_ci node_size / (1024 * 1024), node_free / (1024 * 1024)); 536f08c3bdfSopenharmony_ci } 537f08c3bdfSopenharmony_ci 538f08c3bdfSopenharmony_ci return CMD_SUCCESS; 539f08c3bdfSopenharmony_ci} 540f08c3bdfSopenharmony_ci 541f08c3bdfSopenharmony_ci/* 542f08c3bdfSopenharmony_ci * migrate <to-node-id[s]> [<from-node-id[s]>] 543f08c3bdfSopenharmony_ci * 544f08c3bdfSopenharmony_ci * Node id[s] - single node id or comma-separated list 545f08c3bdfSopenharmony_ci * <to-node-id[s]> - 1-for-1 with <from-node-id[s]>, OR 546f08c3bdfSopenharmony_ci * if <from-node-id[s]> omitted, <to-node-id[s]> must be 547f08c3bdfSopenharmony_ci * a single node id. 548f08c3bdfSopenharmony_ci */ 549f08c3bdfSopenharmony_cistatic int migrate_process(char *args) 550f08c3bdfSopenharmony_ci{ 551f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 552f08c3bdfSopenharmony_ci unsigned int *fromids, *toids; 553f08c3bdfSopenharmony_ci char *idlist, *nextarg; 554f08c3bdfSopenharmony_ci struct timeval t_start, t_end; 555f08c3bdfSopenharmony_ci int nr_to, nr_from; 556f08c3bdfSopenharmony_ci int nr_migrated; 557f08c3bdfSopenharmony_ci int ret = CMD_ERROR; 558f08c3bdfSopenharmony_ci 559f08c3bdfSopenharmony_ci if (!numa_supported()) 560f08c3bdfSopenharmony_ci return CMD_ERROR; 561f08c3bdfSopenharmony_ci 562f08c3bdfSopenharmony_ci toids = calloc(gcp->numa_max_node, sizeof(*toids)); 563f08c3bdfSopenharmony_ci fromids = calloc(gcp->numa_max_node, sizeof(*fromids)); 564f08c3bdfSopenharmony_ci 565f08c3bdfSopenharmony_ci /* 566f08c3bdfSopenharmony_ci * <to-node-id[s]> 567f08c3bdfSopenharmony_ci */ 568f08c3bdfSopenharmony_ci if (!required_arg(args, "<to-node-id[s]>")) 569f08c3bdfSopenharmony_ci return CMD_ERROR; 570f08c3bdfSopenharmony_ci idlist = strtok_r(args, whitespace, &nextarg); 571f08c3bdfSopenharmony_ci nr_to = get_arg_nodeid_list(idlist, toids); 572f08c3bdfSopenharmony_ci if (nr_to <= 0) 573f08c3bdfSopenharmony_ci goto out_free; 574f08c3bdfSopenharmony_ci args = nextarg + strspn(nextarg, whitespace); 575f08c3bdfSopenharmony_ci 576f08c3bdfSopenharmony_ci if (*args != '\0') { 577f08c3bdfSopenharmony_ci /* 578f08c3bdfSopenharmony_ci * apparently, <from-node-id[s]> present 579f08c3bdfSopenharmony_ci */ 580f08c3bdfSopenharmony_ci idlist = strtok_r(args, whitespace, &nextarg); 581f08c3bdfSopenharmony_ci nr_from = get_arg_nodeid_list(idlist, fromids); 582f08c3bdfSopenharmony_ci if (nr_from <= 0) 583f08c3bdfSopenharmony_ci goto out_free; 584f08c3bdfSopenharmony_ci if (nr_from != nr_to) { 585f08c3bdfSopenharmony_ci fprintf(stderr, 586f08c3bdfSopenharmony_ci "%s: # of 'from' ids must = # of 'to' ids\n", 587f08c3bdfSopenharmony_ci gcp->program_name); 588f08c3bdfSopenharmony_ci goto out_free; 589f08c3bdfSopenharmony_ci } 590f08c3bdfSopenharmony_ci } else { 591f08c3bdfSopenharmony_ci int i; 592f08c3bdfSopenharmony_ci 593f08c3bdfSopenharmony_ci /* 594f08c3bdfSopenharmony_ci * no <from-node-id[s]>, nr_to must == 1, 595f08c3bdfSopenharmony_ci * get fromids from memory policy. 596f08c3bdfSopenharmony_ci */ 597f08c3bdfSopenharmony_ci if (nr_to > 1) { 598f08c3bdfSopenharmony_ci fprintf(stderr, "%s: # to ids must = 1" 599f08c3bdfSopenharmony_ci " when no 'from' ids specified\n", 600f08c3bdfSopenharmony_ci gcp->program_name); 601f08c3bdfSopenharmony_ci goto out_free; 602f08c3bdfSopenharmony_ci } 603f08c3bdfSopenharmony_ci nr_from = get_current_nodeid_list(fromids); 604f08c3bdfSopenharmony_ci if (nr_from <= 0) 605f08c3bdfSopenharmony_ci goto out_free; 606f08c3bdfSopenharmony_ci 607f08c3bdfSopenharmony_ci /* 608f08c3bdfSopenharmony_ci * remove 'to' node from 'from' list. to and from 609f08c3bdfSopenharmony_ci * lists can't intersect. 610f08c3bdfSopenharmony_ci */ 611f08c3bdfSopenharmony_ci for (i = nr_from - 1; i >= 0; --i) { 612f08c3bdfSopenharmony_ci if (*toids == *(fromids + i)) { 613f08c3bdfSopenharmony_ci while (i <= nr_from) { 614f08c3bdfSopenharmony_ci *(fromids + i) = *(fromids + i + 1); 615f08c3bdfSopenharmony_ci ++i; 616f08c3bdfSopenharmony_ci } 617f08c3bdfSopenharmony_ci --nr_from; 618f08c3bdfSopenharmony_ci break; 619f08c3bdfSopenharmony_ci } 620f08c3bdfSopenharmony_ci } 621f08c3bdfSopenharmony_ci 622f08c3bdfSopenharmony_ci /* 623f08c3bdfSopenharmony_ci * fill out nr_from toids with the single 'to' node 624f08c3bdfSopenharmony_ci */ 625f08c3bdfSopenharmony_ci for (; nr_to < nr_from; ++nr_to) 626f08c3bdfSopenharmony_ci *(toids + nr_to) = *toids; /* toids[0] */ 627f08c3bdfSopenharmony_ci } 628f08c3bdfSopenharmony_ci 629f08c3bdfSopenharmony_ci gettimeofday(&t_start, NULL); 630f08c3bdfSopenharmony_ci nr_migrated = 631f08c3bdfSopenharmony_ci syscall(__NR_migrate_pages, getpid(), nr_from, fromids, toids); 632f08c3bdfSopenharmony_ci if (nr_migrated < 0) { 633f08c3bdfSopenharmony_ci int err = errno; 634f08c3bdfSopenharmony_ci fprintf(stderr, "%s: migrate_pages failed - %s\n", 635f08c3bdfSopenharmony_ci gcp->program_name, strerror(err)); 636f08c3bdfSopenharmony_ci goto out_free; 637f08c3bdfSopenharmony_ci } 638f08c3bdfSopenharmony_ci gettimeofday(&t_end, NULL); 639f08c3bdfSopenharmony_ci printf("%s: migrated %d pages in %6.3fsecs\n", 640f08c3bdfSopenharmony_ci gcp->program_name, nr_migrated, 641f08c3bdfSopenharmony_ci (float)(tv_diff_usec(&t_start, &t_end)) / 1000000.0); 642f08c3bdfSopenharmony_ci ret = CMD_SUCCESS; 643f08c3bdfSopenharmony_ci 644f08c3bdfSopenharmony_ciout_free: 645f08c3bdfSopenharmony_ci free(toids); 646f08c3bdfSopenharmony_ci free(fromids); 647f08c3bdfSopenharmony_ci return ret; 648f08c3bdfSopenharmony_ci} 649f08c3bdfSopenharmony_ci 650f08c3bdfSopenharmony_cistatic int show_seg(char *args) 651f08c3bdfSopenharmony_ci{ 652f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 653f08c3bdfSopenharmony_ci 654f08c3bdfSopenharmony_ci char *segname = NULL, *nextarg; 655f08c3bdfSopenharmony_ci 656f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 657f08c3bdfSopenharmony_ci if (*args != '\0') 658f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 659f08c3bdfSopenharmony_ci 660f08c3bdfSopenharmony_ci if (!segment_show(segname)) 661f08c3bdfSopenharmony_ci return CMD_ERROR; 662f08c3bdfSopenharmony_ci 663f08c3bdfSopenharmony_ci return CMD_SUCCESS; 664f08c3bdfSopenharmony_ci} 665f08c3bdfSopenharmony_ci 666f08c3bdfSopenharmony_ci/* 667f08c3bdfSopenharmony_ci * anon_seg: <seg-name> <size>[kmgp] [private|shared] 668f08c3bdfSopenharmony_ci */ 669f08c3bdfSopenharmony_cistatic int anon_seg(char *args) 670f08c3bdfSopenharmony_ci{ 671f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 672f08c3bdfSopenharmony_ci 673f08c3bdfSopenharmony_ci char *segname, *nextarg; 674f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 675f08c3bdfSopenharmony_ci int segflag = 0; 676f08c3bdfSopenharmony_ci 677f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 678f08c3bdfSopenharmony_ci 679f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 680f08c3bdfSopenharmony_ci return CMD_ERROR; 681f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 682f08c3bdfSopenharmony_ci args = nextarg + strspn(nextarg, whitespace); 683f08c3bdfSopenharmony_ci 684f08c3bdfSopenharmony_ci if (!required_arg(args, "<size>")) 685f08c3bdfSopenharmony_ci return CMD_ERROR; 686f08c3bdfSopenharmony_ci args = strtok_r(args, whitespace, &nextarg); 687f08c3bdfSopenharmony_ci range.length = get_scaled_value(args, "size"); 688f08c3bdfSopenharmony_ci if (range.length == BOGUS_SIZE) 689f08c3bdfSopenharmony_ci return CMD_ERROR; 690f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 691f08c3bdfSopenharmony_ci 692f08c3bdfSopenharmony_ci if (*args != '\0') { 693f08c3bdfSopenharmony_ci segflag = get_shared(args); 694f08c3bdfSopenharmony_ci if (segflag == -1) 695f08c3bdfSopenharmony_ci return CMD_ERROR; 696f08c3bdfSopenharmony_ci } 697f08c3bdfSopenharmony_ci 698f08c3bdfSopenharmony_ci if (!segment_register(SEGT_ANON, segname, &range, segflag)) 699f08c3bdfSopenharmony_ci return CMD_ERROR; 700f08c3bdfSopenharmony_ci 701f08c3bdfSopenharmony_ci return CMD_SUCCESS; 702f08c3bdfSopenharmony_ci} 703f08c3bdfSopenharmony_ci 704f08c3bdfSopenharmony_ci/* 705f08c3bdfSopenharmony_ci * file_seg: <path-name> [<offset>[kmgp] <length>[kmgp] [private|shared]] 706f08c3bdfSopenharmony_ci */ 707f08c3bdfSopenharmony_cistatic int file_seg(char *args) 708f08c3bdfSopenharmony_ci{ 709f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 710f08c3bdfSopenharmony_ci 711f08c3bdfSopenharmony_ci char *pathname, *nextarg; 712f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 713f08c3bdfSopenharmony_ci int segflag = MAP_PRIVATE; 714f08c3bdfSopenharmony_ci 715f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 716f08c3bdfSopenharmony_ci 717f08c3bdfSopenharmony_ci if (!required_arg(args, "<path-name>")) 718f08c3bdfSopenharmony_ci return CMD_ERROR; 719f08c3bdfSopenharmony_ci pathname = strtok_r(args, whitespace, &nextarg); 720f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 721f08c3bdfSopenharmony_ci 722f08c3bdfSopenharmony_ci /* 723f08c3bdfSopenharmony_ci * offset, length are optional 724f08c3bdfSopenharmony_ci */ 725f08c3bdfSopenharmony_ci if (get_range(args, &range, &nextarg) == CMD_ERROR) 726f08c3bdfSopenharmony_ci return CMD_ERROR; 727f08c3bdfSopenharmony_ci args = nextarg; 728f08c3bdfSopenharmony_ci 729f08c3bdfSopenharmony_ci if (*args != '\0') { 730f08c3bdfSopenharmony_ci segflag = get_shared(args); 731f08c3bdfSopenharmony_ci if (segflag == -1) 732f08c3bdfSopenharmony_ci return CMD_ERROR; 733f08c3bdfSopenharmony_ci } 734f08c3bdfSopenharmony_ci 735f08c3bdfSopenharmony_ci if (!segment_register(SEGT_FILE, pathname, &range, segflag)) 736f08c3bdfSopenharmony_ci return CMD_ERROR; 737f08c3bdfSopenharmony_ci 738f08c3bdfSopenharmony_ci return CMD_SUCCESS; 739f08c3bdfSopenharmony_ci} 740f08c3bdfSopenharmony_ci 741f08c3bdfSopenharmony_ci/* 742f08c3bdfSopenharmony_ci * deletefile <file-name> 743f08c3bdfSopenharmony_ci */ 744f08c3bdfSopenharmony_cistatic int delete_file(char *args) 745f08c3bdfSopenharmony_ci{ 746f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 747f08c3bdfSopenharmony_ci char *filename, *nextarg; 748f08c3bdfSopenharmony_ci 749f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 750f08c3bdfSopenharmony_ci if (!required_arg(args, "<file-name>")) 751f08c3bdfSopenharmony_ci return CMD_ERROR; 752f08c3bdfSopenharmony_ci filename = strtok_r(args, whitespace, &nextarg); 753f08c3bdfSopenharmony_ci 754f08c3bdfSopenharmony_ci if (remove(filename)) { 755f08c3bdfSopenharmony_ci fprintf(stderr, "%s: deletefile failed - %s\n", 756f08c3bdfSopenharmony_ci gcp->program_name, strerror(errno)); 757f08c3bdfSopenharmony_ci return CMD_ERROR; 758f08c3bdfSopenharmony_ci } 759f08c3bdfSopenharmony_ci 760f08c3bdfSopenharmony_ci return CMD_SUCCESS; 761f08c3bdfSopenharmony_ci} 762f08c3bdfSopenharmony_ci 763f08c3bdfSopenharmony_ci/* 764f08c3bdfSopenharmony_ci * createfile <file-name> <size>[k|m|g|p]] 765f08c3bdfSopenharmony_ci */ 766f08c3bdfSopenharmony_cistatic int create_file(char *args) 767f08c3bdfSopenharmony_ci{ 768f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 769f08c3bdfSopenharmony_ci char *filename, *nextarg; 770f08c3bdfSopenharmony_ci size_t len; 771f08c3bdfSopenharmony_ci int fd; 772f08c3bdfSopenharmony_ci 773f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 774f08c3bdfSopenharmony_ci if (!required_arg(args, "<file-name>")) 775f08c3bdfSopenharmony_ci return CMD_ERROR; 776f08c3bdfSopenharmony_ci filename = strtok_r(args, whitespace, &nextarg); 777f08c3bdfSopenharmony_ci args = nextarg + strspn(nextarg, whitespace); 778f08c3bdfSopenharmony_ci 779f08c3bdfSopenharmony_ci if (!required_arg(args, "<size>")) 780f08c3bdfSopenharmony_ci return CMD_ERROR; 781f08c3bdfSopenharmony_ci args = strtok_r(args, whitespace, &nextarg); 782f08c3bdfSopenharmony_ci len = get_scaled_value(args, "size"); 783f08c3bdfSopenharmony_ci if (len == BOGUS_SIZE) 784f08c3bdfSopenharmony_ci return CMD_ERROR; 785f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 786f08c3bdfSopenharmony_ci 787f08c3bdfSopenharmony_ci fd = open(filename, O_RDWR | O_CREAT, 0600); 788f08c3bdfSopenharmony_ci if (fd < 0) { 789f08c3bdfSopenharmony_ci fprintf(stderr, "%s: createfile failed - %s\n", 790f08c3bdfSopenharmony_ci gcp->program_name, strerror(errno)); 791f08c3bdfSopenharmony_ci return CMD_ERROR; 792f08c3bdfSopenharmony_ci } 793f08c3bdfSopenharmony_ci 794f08c3bdfSopenharmony_ci if (posix_fallocate(fd, 0, len)) { 795f08c3bdfSopenharmony_ci fprintf(stderr, "%s: createfile failed - %s\n", 796f08c3bdfSopenharmony_ci gcp->program_name, strerror(errno)); 797f08c3bdfSopenharmony_ci return CMD_ERROR; 798f08c3bdfSopenharmony_ci } 799f08c3bdfSopenharmony_ci close(fd); 800f08c3bdfSopenharmony_ci return CMD_SUCCESS; 801f08c3bdfSopenharmony_ci} 802f08c3bdfSopenharmony_ci 803f08c3bdfSopenharmony_ci/* 804f08c3bdfSopenharmony_ci * remove_seg: <seg-name> [<seg-name> ...] 805f08c3bdfSopenharmony_ci */ 806f08c3bdfSopenharmony_cistatic int remove_seg(char *args) 807f08c3bdfSopenharmony_ci{ 808f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 809f08c3bdfSopenharmony_ci 810f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 811f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 812f08c3bdfSopenharmony_ci return CMD_ERROR; 813f08c3bdfSopenharmony_ci 814f08c3bdfSopenharmony_ci while (*args != '\0') { 815f08c3bdfSopenharmony_ci char *segname, *nextarg; 816f08c3bdfSopenharmony_ci 817f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 818f08c3bdfSopenharmony_ci args = nextarg + strspn(nextarg, whitespace); 819f08c3bdfSopenharmony_ci 820f08c3bdfSopenharmony_ci segment_remove(segname); 821f08c3bdfSopenharmony_ci } 822f08c3bdfSopenharmony_ci return 0; 823f08c3bdfSopenharmony_ci} 824f08c3bdfSopenharmony_ci 825f08c3bdfSopenharmony_ci/* 826f08c3bdfSopenharmony_ci * touch_seg: <seg-name> [<offset> <length>] [read|write] 827f08c3bdfSopenharmony_ci */ 828f08c3bdfSopenharmony_cistatic int touch_seg(char *args) 829f08c3bdfSopenharmony_ci{ 830f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 831f08c3bdfSopenharmony_ci 832f08c3bdfSopenharmony_ci char *segname, *nextarg; 833f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 834f08c3bdfSopenharmony_ci int axcs; 835f08c3bdfSopenharmony_ci 836f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 837f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 838f08c3bdfSopenharmony_ci return CMD_ERROR; 839f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 840f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 841f08c3bdfSopenharmony_ci 842f08c3bdfSopenharmony_ci /* 843f08c3bdfSopenharmony_ci * offset, length are optional 844f08c3bdfSopenharmony_ci */ 845f08c3bdfSopenharmony_ci if (get_range(args, &range, &nextarg) == CMD_ERROR) 846f08c3bdfSopenharmony_ci return CMD_ERROR; 847f08c3bdfSopenharmony_ci args = nextarg; 848f08c3bdfSopenharmony_ci 849f08c3bdfSopenharmony_ci axcs = get_access(args); 850f08c3bdfSopenharmony_ci if (axcs == 0) 851f08c3bdfSopenharmony_ci return CMD_ERROR; 852f08c3bdfSopenharmony_ci 853f08c3bdfSopenharmony_ci if (!segment_touch(segname, &range, axcs - 1)) 854f08c3bdfSopenharmony_ci return CMD_ERROR; 855f08c3bdfSopenharmony_ci 856f08c3bdfSopenharmony_ci return CMD_SUCCESS; 857f08c3bdfSopenharmony_ci} 858f08c3bdfSopenharmony_ci 859f08c3bdfSopenharmony_ci/* 860f08c3bdfSopenharmony_ci * unmap <seg-name> - unmap specified segment, but remember name/size/... 861f08c3bdfSopenharmony_ci */ 862f08c3bdfSopenharmony_cistatic int unmap_seg(char *args) 863f08c3bdfSopenharmony_ci{ 864f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 865f08c3bdfSopenharmony_ci char *segname, *nextarg; 866f08c3bdfSopenharmony_ci 867f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 868f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 869f08c3bdfSopenharmony_ci return CMD_ERROR; 870f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 871f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 872f08c3bdfSopenharmony_ci 873f08c3bdfSopenharmony_ci if (!segment_unmap(segname)) 874f08c3bdfSopenharmony_ci return CMD_ERROR; 875f08c3bdfSopenharmony_ci 876f08c3bdfSopenharmony_ci return CMD_SUCCESS; 877f08c3bdfSopenharmony_ci} 878f08c3bdfSopenharmony_ci 879f08c3bdfSopenharmony_ci/* 880f08c3bdfSopenharmony_ci * map <seg-name> [<offset>[k|m|g|p] <length>[k|m|g|p]] [<seg-share>] 881f08c3bdfSopenharmony_ci */ 882f08c3bdfSopenharmony_cistatic int map_seg(char *args) 883f08c3bdfSopenharmony_ci{ 884f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 885f08c3bdfSopenharmony_ci 886f08c3bdfSopenharmony_ci char *segname, *nextarg; 887f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 888f08c3bdfSopenharmony_ci range_t *rangep = NULL; 889f08c3bdfSopenharmony_ci int segflag = MAP_PRIVATE; 890f08c3bdfSopenharmony_ci 891f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 892f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 893f08c3bdfSopenharmony_ci return CMD_ERROR; 894f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 895f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 896f08c3bdfSopenharmony_ci 897f08c3bdfSopenharmony_ci /* 898f08c3bdfSopenharmony_ci * offset, length are optional 899f08c3bdfSopenharmony_ci */ 900f08c3bdfSopenharmony_ci if (get_range(args, &range, &nextarg) == CMD_ERROR) 901f08c3bdfSopenharmony_ci return CMD_ERROR; 902f08c3bdfSopenharmony_ci if (args != nextarg) { 903f08c3bdfSopenharmony_ci rangep = ⦥ /* override any registered range */ 904f08c3bdfSopenharmony_ci args = nextarg; 905f08c3bdfSopenharmony_ci } 906f08c3bdfSopenharmony_ci 907f08c3bdfSopenharmony_ci if (*args != '\0') { 908f08c3bdfSopenharmony_ci segflag = get_shared(args); 909f08c3bdfSopenharmony_ci if (segflag == -1) 910f08c3bdfSopenharmony_ci return CMD_ERROR; 911f08c3bdfSopenharmony_ci } 912f08c3bdfSopenharmony_ci 913f08c3bdfSopenharmony_ci if (!segment_map(segname, rangep, segflag)) 914f08c3bdfSopenharmony_ci return CMD_ERROR; 915f08c3bdfSopenharmony_ci 916f08c3bdfSopenharmony_ci return CMD_SUCCESS; 917f08c3bdfSopenharmony_ci} 918f08c3bdfSopenharmony_ci 919f08c3bdfSopenharmony_ci/* 920f08c3bdfSopenharmony_ci * mbind <seg-name> [<offset>[kmgp] <length>[kmgp]] <policy> <node-list> 921f08c3bdfSopenharmony_ci */ 922f08c3bdfSopenharmony_cistatic int mbind_seg(char *args) 923f08c3bdfSopenharmony_ci{ 924f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 925f08c3bdfSopenharmony_ci 926f08c3bdfSopenharmony_ci char *segname, *nextarg; 927f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 928f08c3bdfSopenharmony_ci nodemask_t *nodemask = NULL; 929f08c3bdfSopenharmony_ci int policy, flags = 0; 930f08c3bdfSopenharmony_ci int ret; 931f08c3bdfSopenharmony_ci 932f08c3bdfSopenharmony_ci if (!numa_supported()) 933f08c3bdfSopenharmony_ci return CMD_ERROR; 934f08c3bdfSopenharmony_ci 935f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 936f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 937f08c3bdfSopenharmony_ci return CMD_ERROR; 938f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 939f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 940f08c3bdfSopenharmony_ci 941f08c3bdfSopenharmony_ci /* 942f08c3bdfSopenharmony_ci * offset, length are optional 943f08c3bdfSopenharmony_ci */ 944f08c3bdfSopenharmony_ci if (get_range(args, &range, &nextarg) == CMD_ERROR) 945f08c3bdfSopenharmony_ci return CMD_ERROR; 946f08c3bdfSopenharmony_ci args = nextarg; 947f08c3bdfSopenharmony_ci 948f08c3bdfSopenharmony_ci if (!required_arg(args, "<policy>")) 949f08c3bdfSopenharmony_ci return CMD_ERROR; 950f08c3bdfSopenharmony_ci policy = get_mbind_policy(args, &nextarg); 951f08c3bdfSopenharmony_ci if (policy < 0) 952f08c3bdfSopenharmony_ci return CMD_ERROR; 953f08c3bdfSopenharmony_ci 954f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 955f08c3bdfSopenharmony_ci if (*args == '+') { 956f08c3bdfSopenharmony_ci flags = get_mbind_flags(++args, &nextarg); 957f08c3bdfSopenharmony_ci if (flags == -1) 958f08c3bdfSopenharmony_ci return CMD_ERROR; 959f08c3bdfSopenharmony_ci } 960f08c3bdfSopenharmony_ci args = nextarg + strspn(nextarg, whitespace); 961f08c3bdfSopenharmony_ci 962f08c3bdfSopenharmony_ci if (policy != MPOL_DEFAULT) { 963f08c3bdfSopenharmony_ci if (!required_arg(args, "<node/list>")) 964f08c3bdfSopenharmony_ci return CMD_ERROR; 965f08c3bdfSopenharmony_ci nodemask = get_nodemask(args); 966f08c3bdfSopenharmony_ci if (nodemask == NULL) 967f08c3bdfSopenharmony_ci return CMD_ERROR; 968f08c3bdfSopenharmony_ci } 969f08c3bdfSopenharmony_ci 970f08c3bdfSopenharmony_ci ret = CMD_SUCCESS; 971f08c3bdfSopenharmony_ci#if 1 // for testing 972f08c3bdfSopenharmony_ci if (!segment_mbind(segname, &range, policy, nodemask, flags)) 973f08c3bdfSopenharmony_ci ret = CMD_ERROR; 974f08c3bdfSopenharmony_ci#endif 975f08c3bdfSopenharmony_ci 976f08c3bdfSopenharmony_ci if (nodemask != NULL) 977f08c3bdfSopenharmony_ci free(nodemask); 978f08c3bdfSopenharmony_ci return ret; 979f08c3bdfSopenharmony_ci} 980f08c3bdfSopenharmony_ci 981f08c3bdfSopenharmony_ci/* 982f08c3bdfSopenharmony_ci * shmem_seg - create [shmget] and register a SysV shared memory segment 983f08c3bdfSopenharmony_ci * of specified size 984f08c3bdfSopenharmony_ci */ 985f08c3bdfSopenharmony_cistatic int shmem_seg(char *args) 986f08c3bdfSopenharmony_ci{ 987f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 988f08c3bdfSopenharmony_ci 989f08c3bdfSopenharmony_ci char *segname, *nextarg; 990f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 991f08c3bdfSopenharmony_ci 992f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 993f08c3bdfSopenharmony_ci 994f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 995f08c3bdfSopenharmony_ci return CMD_ERROR; 996f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 997f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 998f08c3bdfSopenharmony_ci 999f08c3bdfSopenharmony_ci if (!required_arg(args, "<size>")) 1000f08c3bdfSopenharmony_ci return CMD_ERROR; 1001f08c3bdfSopenharmony_ci args = strtok_r(args, whitespace, &nextarg); 1002f08c3bdfSopenharmony_ci range.length = get_scaled_value(args, "size"); 1003f08c3bdfSopenharmony_ci if (range.length == BOGUS_SIZE) 1004f08c3bdfSopenharmony_ci return CMD_ERROR; 1005f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 1006f08c3bdfSopenharmony_ci 1007f08c3bdfSopenharmony_ci if (!segment_register(SEGT_SHM, segname, &range, MAP_SHARED)) 1008f08c3bdfSopenharmony_ci return CMD_ERROR; 1009f08c3bdfSopenharmony_ci 1010f08c3bdfSopenharmony_ci return CMD_SUCCESS; 1011f08c3bdfSopenharmony_ci} 1012f08c3bdfSopenharmony_ci 1013f08c3bdfSopenharmony_ci/* 1014f08c3bdfSopenharmony_ci * where <seg-name> [<offset>[kmgp] <length>[kmgp]] - show node location 1015f08c3bdfSopenharmony_ci * of specified range of segment. 1016f08c3bdfSopenharmony_ci * 1017f08c3bdfSopenharmony_ci * NOTE: if neither <offset> nor <length> specified, <offset> defaults 1018f08c3bdfSopenharmony_ci * to 0 [start of segment], as usual, and length defaults to 64 pages 1019f08c3bdfSopenharmony_ci * rather than the entire segment. Suitable for a "quick look" at where 1020f08c3bdfSopenharmony_ci * segment resides. 1021f08c3bdfSopenharmony_ci */ 1022f08c3bdfSopenharmony_cistatic int where_seg(char *args) 1023f08c3bdfSopenharmony_ci{ 1024f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 1025f08c3bdfSopenharmony_ci 1026f08c3bdfSopenharmony_ci char *segname, *nextarg; 1027f08c3bdfSopenharmony_ci range_t range = { 0L, 0L }; 1028f08c3bdfSopenharmony_ci int ret; 1029f08c3bdfSopenharmony_ci 1030f08c3bdfSopenharmony_ci if (!numa_supported()) 1031f08c3bdfSopenharmony_ci return CMD_ERROR; 1032f08c3bdfSopenharmony_ci 1033f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 1034f08c3bdfSopenharmony_ci if (!required_arg(args, "<seg-name>")) 1035f08c3bdfSopenharmony_ci return CMD_ERROR; 1036f08c3bdfSopenharmony_ci segname = strtok_r(args, whitespace, &nextarg); 1037f08c3bdfSopenharmony_ci args = get_next_arg(args, nextarg); 1038f08c3bdfSopenharmony_ci 1039f08c3bdfSopenharmony_ci /* 1040f08c3bdfSopenharmony_ci * offset, length are optional 1041f08c3bdfSopenharmony_ci */ 1042f08c3bdfSopenharmony_ci if (get_range(args, &range, &nextarg) == CMD_ERROR) 1043f08c3bdfSopenharmony_ci return CMD_ERROR; 1044f08c3bdfSopenharmony_ci if (args == nextarg) 1045f08c3bdfSopenharmony_ci range.length = 64 * gcp->pagesize; /* default length */ 1046f08c3bdfSopenharmony_ci 1047f08c3bdfSopenharmony_ci if (!segment_location(segname, &range)) 1048f08c3bdfSopenharmony_ci return CMD_ERROR; 1049f08c3bdfSopenharmony_ci 1050f08c3bdfSopenharmony_ci return CMD_SUCCESS; 1051f08c3bdfSopenharmony_ci} 1052f08c3bdfSopenharmony_ci 1053f08c3bdfSopenharmony_ci#if 0 1054f08c3bdfSopenharmony_cistatic int command(char *args) 1055f08c3bdfSopenharmony_ci{ 1056f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 1057f08c3bdfSopenharmony_ci 1058f08c3bdfSopenharmony_ci return CMD_SUCCESS; 1059f08c3bdfSopenharmony_ci} 1060f08c3bdfSopenharmony_ci 1061f08c3bdfSopenharmony_ci#endif 1062f08c3bdfSopenharmony_ci/* 1063f08c3bdfSopenharmony_ci * ========================================================================= 1064f08c3bdfSopenharmony_ci */ 1065f08c3bdfSopenharmony_citypedef int (*cmd_func_t) (char *); 1066f08c3bdfSopenharmony_ci 1067f08c3bdfSopenharmony_cistruct command { 1068f08c3bdfSopenharmony_ci char *cmd_name; 1069f08c3bdfSopenharmony_ci cmd_func_t cmd_func; /* */ 1070f08c3bdfSopenharmony_ci char *cmd_help; 1071f08c3bdfSopenharmony_ci 1072f08c3bdfSopenharmony_ci} cmd_table[] = { 1073f08c3bdfSopenharmony_ci { 1074f08c3bdfSopenharmony_ci .cmd_name = "quit",.cmd_func = quit,.cmd_help = 1075f08c3bdfSopenharmony_ci "quit - just what you think\n" 1076f08c3bdfSopenharmony_ci "\tEOF on stdin has the same effect\n"}, { 1077f08c3bdfSopenharmony_ci .cmd_name = "help",.cmd_func = help_me,.cmd_help = 1078f08c3bdfSopenharmony_ci "help - show this help\n" 1079f08c3bdfSopenharmony_ci "help <command> - display help for just <command>\n"}, { 1080f08c3bdfSopenharmony_ci .cmd_name = "pid",.cmd_func = show_pid,.cmd_help = 1081f08c3bdfSopenharmony_ci "pid - show process id of this session\n"}, { 1082f08c3bdfSopenharmony_ci .cmd_name = "pause",.cmd_func = pause_me,.cmd_help = 1083f08c3bdfSopenharmony_ci "pause - pause program until signal" 1084f08c3bdfSopenharmony_ci " -- e.g., INT, USR1\n"}, { 1085f08c3bdfSopenharmony_ci .cmd_name = "numa",.cmd_func = numa_info,.cmd_help = 1086f08c3bdfSopenharmony_ci "numa - display numa info as seen by this program.\n" 1087f08c3bdfSopenharmony_ci "\tshows nodes from which program may allocate memory\n" 1088f08c3bdfSopenharmony_ci "\twith total and free memory.\n"}, { 1089f08c3bdfSopenharmony_ci .cmd_name = "migrate",.cmd_func = migrate_process,.cmd_help = 1090f08c3bdfSopenharmony_ci "migrate <to-node-id[s]> [<from-node-id[s]>] - \n" 1091f08c3bdfSopenharmony_ci "\tmigrate this process' memory from <from-node-id[s]>\n" 1092f08c3bdfSopenharmony_ci "\tto <to-node-id[s]>. Specify multiple node ids as a\n" 1093f08c3bdfSopenharmony_ci "\tcomma-separated list. TODO - more info\n"}, { 1094f08c3bdfSopenharmony_ci .cmd_name = "show",.cmd_func = show_seg,.cmd_help = 1095f08c3bdfSopenharmony_ci "show [<name>] - show info for segment[s]; default all\n"}, 1096f08c3bdfSopenharmony_ci { 1097f08c3bdfSopenharmony_ci .cmd_name = "anon",.cmd_func = anon_seg,.cmd_help = 1098f08c3bdfSopenharmony_ci "anon <seg-name> <seg-size>[k|m|g|p] [<seg-share>] -\n" 1099f08c3bdfSopenharmony_ci "\tdefine a MAP_ANONYMOUS segment of specified size\n" 1100f08c3bdfSopenharmony_ci "\t<seg-share> := private|shared - default = private\n"}, { 1101f08c3bdfSopenharmony_ci .cmd_name = "file",.cmd_func = file_seg,.cmd_help = 1102f08c3bdfSopenharmony_ci "file <pathname> [<offset>[k|m|g|p] <length>[k|m|g|p]] [<seg-share>] -\n" 1103f08c3bdfSopenharmony_ci "\tdefine a mapped file segment of specified length starting at the\n" 1104f08c3bdfSopenharmony_ci "\tspecified offset into the file. <offset> and <length> may be\n" 1105f08c3bdfSopenharmony_ci "\tomitted and specified on the map command.\n" 1106f08c3bdfSopenharmony_ci "\t<seg-share> := private|shared - default = private\n"}, { 1107f08c3bdfSopenharmony_ci .cmd_name = "createfile", .cmd_func = create_file, .cmd_help = 1108f08c3bdfSopenharmony_ci "createfile <file-name> <size>[k|m|g|p]]",}, { 1109f08c3bdfSopenharmony_ci .cmd_name = "deletefile", .cmd_func = delete_file, .cmd_help = 1110f08c3bdfSopenharmony_ci "deletefile <file-name>"}, { 1111f08c3bdfSopenharmony_ci .cmd_name = "shm",.cmd_func = shmem_seg,.cmd_help = 1112f08c3bdfSopenharmony_ci "shm <seg-name> <seg-size>[k|m|g|p] - \n" 1113f08c3bdfSopenharmony_ci "\tdefine a shared memory segment of specified size.\n" 1114f08c3bdfSopenharmony_ci "\tYou may need to increase limits [/proc/sys/kernel/shmmax].\n" 1115f08c3bdfSopenharmony_ci "\tUse map/unmap to attach/detach\n"}, { 1116f08c3bdfSopenharmony_ci .cmd_name = "remove",.cmd_func = remove_seg,.cmd_help = 1117f08c3bdfSopenharmony_ci "remove <seg-name> [<seg-name> ...] - remove the named segment[s]\n"}, 1118f08c3bdfSopenharmony_ci { 1119f08c3bdfSopenharmony_ci .cmd_name = "map",.cmd_func = map_seg,.cmd_help = 1120f08c3bdfSopenharmony_ci "map <seg-name> [<offset>[k|m|g|p] <length>[k|m|g|p]] [<seg-share>] - \n" 1121f08c3bdfSopenharmony_ci "\tmmap()/shmat() a previously defined, currently unmapped() segment.\n" 1122f08c3bdfSopenharmony_ci "\t<offset> and <length> apply only to mapped files.\n" 1123f08c3bdfSopenharmony_ci "\tUse <length> of '*' or '0' to map to the end of the file.\n"}, 1124f08c3bdfSopenharmony_ci { 1125f08c3bdfSopenharmony_ci .cmd_name = "unmap",.cmd_func = unmap_seg,.cmd_help = 1126f08c3bdfSopenharmony_ci "unmap <seg-name> - unmap specified segment, but remember name/size/...\n"}, 1127f08c3bdfSopenharmony_ci { 1128f08c3bdfSopenharmony_ci .cmd_name = "touch",.cmd_func = touch_seg,.cmd_help = 1129f08c3bdfSopenharmony_ci "touch <seg-name> [<offset>[k|m|g|p] <length>[k|m|g|p]] [read|write] - \n" 1130f08c3bdfSopenharmony_ci "\tread [default] or write the named segment from <offset> through\n" 1131f08c3bdfSopenharmony_ci "\t<offset>+<length>. If <offset> and <length> omitted, touches all\n" 1132f08c3bdfSopenharmony_ci "\t of mapped segment.\n"}, { 1133f08c3bdfSopenharmony_ci .cmd_name = "mbind",.cmd_func = mbind_seg,.cmd_help = 1134f08c3bdfSopenharmony_ci "mbind <seg-name> [<offset>[k|m|g|p] <length>[k|m|g|p]]\n" 1135f08c3bdfSopenharmony_ci " <policy>[+move[+wait]] [<node/list>] - \n" 1136f08c3bdfSopenharmony_ci "\tset the numa policy for the specified range of the name segment\n" 1137f08c3bdfSopenharmony_ci "\tto policy -- one of {default, bind, preferred, interleaved}.\n" 1138f08c3bdfSopenharmony_ci "\t<node/list> specifies a node id or a comma separated list of\n" 1139f08c3bdfSopenharmony_ci "\tnode ids. <node> is ignored for 'default' policy, and only\n" 1140f08c3bdfSopenharmony_ci "\tthe first node is used for 'preferred' policy.\n" 1141f08c3bdfSopenharmony_ci "\t'+move' specifies that currently allocated pages be prepared\n" 1142f08c3bdfSopenharmony_ci "\t for migration on next touch\n" 1143f08c3bdfSopenharmony_ci "\t'+wait' [valid only with +move] specifies that pages mbind()\n" 1144f08c3bdfSopenharmony_ci " touch the pages and wait for migration before returning.\n"}, 1145f08c3bdfSopenharmony_ci { 1146f08c3bdfSopenharmony_ci .cmd_name = "where",.cmd_func = where_seg,.cmd_help = 1147f08c3bdfSopenharmony_ci "where <seg-name> [<offset>[k|m|g|p] <length>[k|m|g|p]] - \n" 1148f08c3bdfSopenharmony_ci "\tshow the node location of pages in the specified range\n" 1149f08c3bdfSopenharmony_ci "\tof the specified segment. <offset> defaults to start of\n" 1150f08c3bdfSopenharmony_ci "\tsegment; <length> defaults to 64 pages.\n"}, 1151f08c3bdfSopenharmony_ci#if 0 /* template for new commands */ 1152f08c3bdfSopenharmony_ci { 1153f08c3bdfSopenharmony_ci .cmd_name = "",.cmd_func =,.cmd_help =}, 1154f08c3bdfSopenharmony_ci#endif 1155f08c3bdfSopenharmony_ci { 1156f08c3bdfSopenharmony_ci .cmd_name = NULL} 1157f08c3bdfSopenharmony_ci}; 1158f08c3bdfSopenharmony_ci 1159f08c3bdfSopenharmony_cistatic int help_me(char *args) 1160f08c3bdfSopenharmony_ci{ 1161f08c3bdfSopenharmony_ci struct command *cmdp = cmd_table; 1162f08c3bdfSopenharmony_ci char *cmd, *nextarg; 1163f08c3bdfSopenharmony_ci int cmdlen; 1164f08c3bdfSopenharmony_ci bool match = false; 1165f08c3bdfSopenharmony_ci 1166f08c3bdfSopenharmony_ci args += strspn(args, whitespace); 1167f08c3bdfSopenharmony_ci if (*args != '\0') { 1168f08c3bdfSopenharmony_ci cmd = strtok_r(args, whitespace, &nextarg); 1169f08c3bdfSopenharmony_ci cmdlen = strlen(cmd); 1170f08c3bdfSopenharmony_ci } else { 1171f08c3bdfSopenharmony_ci cmd = NULL; 1172f08c3bdfSopenharmony_ci cmdlen = 0; 1173f08c3bdfSopenharmony_ci } 1174f08c3bdfSopenharmony_ci 1175f08c3bdfSopenharmony_ci for (cmdp = cmd_table; cmdp->cmd_name != NULL; ++cmdp) { 1176f08c3bdfSopenharmony_ci if (cmd == NULL || !strncmp(cmd, cmdp->cmd_name, cmdlen)) { 1177f08c3bdfSopenharmony_ci printf("%s\n", cmdp->cmd_help); 1178f08c3bdfSopenharmony_ci match = true; 1179f08c3bdfSopenharmony_ci } 1180f08c3bdfSopenharmony_ci } 1181f08c3bdfSopenharmony_ci 1182f08c3bdfSopenharmony_ci if (!match) { 1183f08c3bdfSopenharmony_ci printf("unrecognized command: %s\n", cmd); 1184f08c3bdfSopenharmony_ci printf("\tuse 'help' for a complete list of commands\n"); 1185f08c3bdfSopenharmony_ci return CMD_ERROR; 1186f08c3bdfSopenharmony_ci } 1187f08c3bdfSopenharmony_ci 1188f08c3bdfSopenharmony_ci return CMD_SUCCESS; 1189f08c3bdfSopenharmony_ci} 1190f08c3bdfSopenharmony_ci 1191f08c3bdfSopenharmony_ci/* 1192f08c3bdfSopenharmony_ci * ========================================================================= 1193f08c3bdfSopenharmony_ci */ 1194f08c3bdfSopenharmony_ci 1195f08c3bdfSopenharmony_cistatic bool unique_abbrev(char *cmd, size_t clen, struct command *cmdp) 1196f08c3bdfSopenharmony_ci{ 1197f08c3bdfSopenharmony_ci for (; cmdp->cmd_name != NULL; ++cmdp) { 1198f08c3bdfSopenharmony_ci if (!strncmp(cmd, cmdp->cmd_name, clen)) 1199f08c3bdfSopenharmony_ci return false; /* match: not unique */ 1200f08c3bdfSopenharmony_ci } 1201f08c3bdfSopenharmony_ci return true; 1202f08c3bdfSopenharmony_ci} 1203f08c3bdfSopenharmony_ci 1204f08c3bdfSopenharmony_cistatic int parse_command(char *cmdline) 1205f08c3bdfSopenharmony_ci{ 1206f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 1207f08c3bdfSopenharmony_ci char *cmd, *args; 1208f08c3bdfSopenharmony_ci struct command *cmdp; 1209f08c3bdfSopenharmony_ci 1210f08c3bdfSopenharmony_ci cmdline += strspn(cmdline, whitespace); /* possibly redundant */ 1211f08c3bdfSopenharmony_ci 1212f08c3bdfSopenharmony_ci cmd = strtok_r(cmdline, whitespace, &args); 1213f08c3bdfSopenharmony_ci 1214f08c3bdfSopenharmony_ci for (cmdp = cmd_table; cmdp->cmd_name != NULL; ++cmdp) { 1215f08c3bdfSopenharmony_ci size_t clen = strlen(cmd); 1216f08c3bdfSopenharmony_ci int ret; 1217f08c3bdfSopenharmony_ci 1218f08c3bdfSopenharmony_ci if (strncmp(cmd, cmdp->cmd_name, clen)) 1219f08c3bdfSopenharmony_ci continue; 1220f08c3bdfSopenharmony_ci if (!unique_abbrev(cmd, clen, cmdp + 1)) { 1221f08c3bdfSopenharmony_ci fprintf(stderr, "%s: ambiguous command: %s\n", 1222f08c3bdfSopenharmony_ci gcp->program_name, cmd); 1223f08c3bdfSopenharmony_ci return CMD_ERROR; 1224f08c3bdfSopenharmony_ci } 1225f08c3bdfSopenharmony_ci gcp->cmd_name = cmdp->cmd_name; 1226f08c3bdfSopenharmony_ci ret = cmdp->cmd_func(args); 1227f08c3bdfSopenharmony_ci gcp->cmd_name = NULL; 1228f08c3bdfSopenharmony_ci return ret; 1229f08c3bdfSopenharmony_ci } 1230f08c3bdfSopenharmony_ci 1231f08c3bdfSopenharmony_ci fprintf(stderr, "%s: unrecognized command %s\n", __FUNCTION__, cmd); 1232f08c3bdfSopenharmony_ci return CMD_ERROR; 1233f08c3bdfSopenharmony_ci} 1234f08c3bdfSopenharmony_ci 1235f08c3bdfSopenharmony_civoid process_commands() 1236f08c3bdfSopenharmony_ci{ 1237f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 1238f08c3bdfSopenharmony_ci 1239f08c3bdfSopenharmony_ci char cmdbuf[CMDBUFSZ]; 1240f08c3bdfSopenharmony_ci 1241f08c3bdfSopenharmony_ci do { 1242f08c3bdfSopenharmony_ci char *cmdline; 1243f08c3bdfSopenharmony_ci size_t cmdlen; 1244f08c3bdfSopenharmony_ci 1245f08c3bdfSopenharmony_ci if (is_option(INTERACTIVE)) 1246f08c3bdfSopenharmony_ci printf("%s>", gcp->program_name); 1247f08c3bdfSopenharmony_ci 1248f08c3bdfSopenharmony_ci cmdline = fgets(cmdbuf, CMDBUFSZ, stdin); 1249f08c3bdfSopenharmony_ci if (cmdline == NULL) { 1250f08c3bdfSopenharmony_ci printf("%s\n", 1251f08c3bdfSopenharmony_ci is_option(INTERACTIVE) ? "" : "EOF on stdin"); 1252f08c3bdfSopenharmony_ci exit(0); /* EOF */ 1253f08c3bdfSopenharmony_ci } 1254f08c3bdfSopenharmony_ci if (cmdline[0] == '\n') 1255f08c3bdfSopenharmony_ci continue; 1256f08c3bdfSopenharmony_ci 1257f08c3bdfSopenharmony_ci /* 1258f08c3bdfSopenharmony_ci * trim trailing newline, if any 1259f08c3bdfSopenharmony_ci */ 1260f08c3bdfSopenharmony_ci cmdlen = strlen(cmdline); 1261f08c3bdfSopenharmony_ci if (cmdline[cmdlen - 1] == '\n') 1262f08c3bdfSopenharmony_ci cmdline[--cmdlen] = '\0'; 1263f08c3bdfSopenharmony_ci 1264f08c3bdfSopenharmony_ci cmdline += strspn(cmdline, whitespace); 1265f08c3bdfSopenharmony_ci cmdlen -= (cmdline - cmdbuf); 1266f08c3bdfSopenharmony_ci 1267f08c3bdfSopenharmony_ci if (cmdlen == 0) { 1268f08c3bdfSopenharmony_ci //TODO: interactive help? 1269f08c3bdfSopenharmony_ci continue; /* ignore blank lines */ 1270f08c3bdfSopenharmony_ci } 1271f08c3bdfSopenharmony_ci 1272f08c3bdfSopenharmony_ci if (*cmdline == '#') 1273f08c3bdfSopenharmony_ci continue; /* comments */ 1274f08c3bdfSopenharmony_ci 1275f08c3bdfSopenharmony_ci /* 1276f08c3bdfSopenharmony_ci * trim trailing whitespace for ease of parsing 1277f08c3bdfSopenharmony_ci */ 1278f08c3bdfSopenharmony_ci while (strchr(whitespace, cmdline[cmdlen - 1])) 1279f08c3bdfSopenharmony_ci cmdline[--cmdlen] = '\0'; 1280f08c3bdfSopenharmony_ci 1281f08c3bdfSopenharmony_ci if (cmdlen == 0) 1282f08c3bdfSopenharmony_ci continue; 1283f08c3bdfSopenharmony_ci 1284f08c3bdfSopenharmony_ci /* 1285f08c3bdfSopenharmony_ci * reset signals just before parsing a command. 1286f08c3bdfSopenharmony_ci * non-interactive: exit on SIGQUIT 1287f08c3bdfSopenharmony_ci */ 1288f08c3bdfSopenharmony_ci if (signalled(gcp)) { 1289f08c3bdfSopenharmony_ci if (!is_option(INTERACTIVE) && 1290f08c3bdfSopenharmony_ci gcp->siginfo->si_signo == SIGQUIT) 1291f08c3bdfSopenharmony_ci exit(0); 1292f08c3bdfSopenharmony_ci reset_signal(); 1293f08c3bdfSopenharmony_ci } 1294f08c3bdfSopenharmony_ci 1295f08c3bdfSopenharmony_ci /* 1296f08c3bdfSopenharmony_ci * non-interactive: errors are fatal 1297f08c3bdfSopenharmony_ci */ 1298f08c3bdfSopenharmony_ci if (!is_option(INTERACTIVE)) { 1299f08c3bdfSopenharmony_ci vprint("%s>%s\n", gcp->program_name, cmdline); 1300f08c3bdfSopenharmony_ci if (parse_command(cmdline) == CMD_ERROR) { 1301f08c3bdfSopenharmony_ci fprintf(stderr, "%s: command error\n", 1302f08c3bdfSopenharmony_ci gcp->program_name); 1303f08c3bdfSopenharmony_ci exit(4); 1304f08c3bdfSopenharmony_ci } 1305f08c3bdfSopenharmony_ci } else 1306f08c3bdfSopenharmony_ci parse_command(cmdline); 1307f08c3bdfSopenharmony_ci 1308f08c3bdfSopenharmony_ci } while (1); 1309f08c3bdfSopenharmony_ci} 1310f08c3bdfSopenharmony_ci#endif 1311