1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * memtoy.c -- toy/tool for investigating Linux [Numa] VM behavior 3f08c3bdfSopenharmony_ci */ 4f08c3bdfSopenharmony_ci/* 5f08c3bdfSopenharmony_ci * Copyright (c) 2005 Hewlett-Packard, Inc 6f08c3bdfSopenharmony_ci * All rights reserved. 7f08c3bdfSopenharmony_ci */ 8f08c3bdfSopenharmony_ci 9f08c3bdfSopenharmony_ci/* 10f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 11f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 12f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 13f08c3bdfSopenharmony_ci * (at your option) any later version. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 16f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 17f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18f08c3bdfSopenharmony_ci * GNU General Public License for more details. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 21f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 22f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include <stdio.h> 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#include "config.h" 28f08c3bdfSopenharmony_ci#include "tst_res_flags.h" 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include <sys/types.h> 33f08c3bdfSopenharmony_ci#include <sys/time.h> 34f08c3bdfSopenharmony_ci#include <sys/mman.h> 35f08c3bdfSopenharmony_ci#include <libgen.h> 36f08c3bdfSopenharmony_ci#include <errno.h> 37f08c3bdfSopenharmony_ci#include <numa.h> 38f08c3bdfSopenharmony_ci#include <signal.h> 39f08c3bdfSopenharmony_ci#include <stdarg.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <string.h> 42f08c3bdfSopenharmony_ci#include <unistd.h> 43f08c3bdfSopenharmony_ci#include "memtoy.h" 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci/* 46f08c3bdfSopenharmony_ci * global context 47f08c3bdfSopenharmony_ci */ 48f08c3bdfSopenharmony_ciglctx_t glctx; /* global context */ 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci/* 51f08c3bdfSopenharmony_ci * command line options: 52f08c3bdfSopenharmony_ci * 53f08c3bdfSopenharmony_ci * -v = verbose 54f08c3bdfSopenharmony_ci * -V = display version 55f08c3bdfSopenharmony_ci * -h|x = display help. 56f08c3bdfSopenharmony_ci */ 57f08c3bdfSopenharmony_ci#define OPTIONS "Vhvx" 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci/* 60f08c3bdfSopenharmony_ci * usage/help message 61f08c3bdfSopenharmony_ci */ 62f08c3bdfSopenharmony_cichar *USAGE = "\nUsage: %s [-v] [-V] [-{h|x}]\n\n\ 63f08c3bdfSopenharmony_ciWhere:\n\ 64f08c3bdfSopenharmony_ci\t-v enable verbosity\n\ 65f08c3bdfSopenharmony_ci\t-V display version info\n\ 66f08c3bdfSopenharmony_ci\t-h|x show this usage/help message\n\ 67f08c3bdfSopenharmony_ci\n\ 68f08c3bdfSopenharmony_ciMore info - TODO\n\ 69f08c3bdfSopenharmony_ci"; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci/* 72f08c3bdfSopenharmony_ci * die() - emit error message and exit w/ specified return code. 73f08c3bdfSopenharmony_ci * if exit_code < 0, save current errno, and fetch associated 74f08c3bdfSopenharmony_ci * error string. Print error string after app error message. 75f08c3bdfSopenharmony_ci * Then exit with abs(exit_code). 76f08c3bdfSopenharmony_ci */ 77f08c3bdfSopenharmony_civoid die(int exit_code, char *format, ...) 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci va_list ap; 80f08c3bdfSopenharmony_ci char *errstr; 81f08c3bdfSopenharmony_ci int saverrno; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci va_start(ap, format); 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (exit_code < 0) { 86f08c3bdfSopenharmony_ci saverrno = errno; 87f08c3bdfSopenharmony_ci errstr = strerror(errno); 88f08c3bdfSopenharmony_ci } 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci (void)vfprintf(stderr, format, ap); 91f08c3bdfSopenharmony_ci va_end(ap); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (exit_code < 0) 94f08c3bdfSopenharmony_ci fprintf(stderr, "Error = (%d) %s\n", saverrno, errstr); 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci exit(abs(exit_code)); 97f08c3bdfSopenharmony_ci} 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_civoid usage(char *mesg) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci if (mesg != NULL) { 102f08c3bdfSopenharmony_ci fprintf(stderr, "%s\n", mesg); 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci fprintf(stderr, USAGE, glctx.program_name); 105f08c3bdfSopenharmony_ci exit(1); 106f08c3bdfSopenharmony_ci} 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci#ifdef _DEBUG 109f08c3bdfSopenharmony_ci/* 110f08c3bdfSopenharmony_ci * This function is a wrapper around "fprintf(stderr, ...)" so that we 111f08c3bdfSopenharmony_ci * can use the DPRINTF(<flag>, (<[f]printf arguments>)) macro for debug 112f08c3bdfSopenharmony_ci * prints. See the definition of DPRINTF in XXX.h 113f08c3bdfSopenharmony_ci */ 114f08c3bdfSopenharmony_ciint _dvprintf(char *format, ...) 115f08c3bdfSopenharmony_ci{ 116f08c3bdfSopenharmony_ci va_list ap; 117f08c3bdfSopenharmony_ci int retval; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci va_start(ap, format); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci retval = vfprintf(stderr, format, ap); 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci va_end(ap); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci fflush(stderr); 126f08c3bdfSopenharmony_ci return (retval); 127f08c3bdfSopenharmony_ci} 128f08c3bdfSopenharmony_ci#endif 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_civoid vprint(char *format, ...) 131f08c3bdfSopenharmony_ci{ 132f08c3bdfSopenharmony_ci va_list ap; 133f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci va_start(ap, format); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (!is_option(VERBOSE)) 138f08c3bdfSopenharmony_ci goto out; 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci (void)vfprintf(stderr, format, ap); 141f08c3bdfSopenharmony_ci fflush(stderr); 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ciout: 144f08c3bdfSopenharmony_ci va_end(ap); 145f08c3bdfSopenharmony_ci return; 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci/* 150f08c3bdfSopenharmony_ci * ========================================================================= 151f08c3bdfSopenharmony_ci */ 152f08c3bdfSopenharmony_cistatic int signals_to_handle[] = { 153f08c3bdfSopenharmony_ci SIGINT, SIGQUIT, SIGSEGV, SIGBUS, 154f08c3bdfSopenharmony_ci SIGUSR1, SIGUSR2, 0 155f08c3bdfSopenharmony_ci}; 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_cistatic char *sig_names[] = { 158f08c3bdfSopenharmony_ci "SIGINT", "SIGQUIT", "SIGSEGV", "SIGBUS", 159f08c3bdfSopenharmony_ci "SIGUSR1", "SIGUSR2", "unknown", 0 160f08c3bdfSopenharmony_ci}; 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci/* 163f08c3bdfSopenharmony_ci * signal_handler() 164f08c3bdfSopenharmony_ci * 165f08c3bdfSopenharmony_ci * save siginfo and name in global context 166f08c3bdfSopenharmony_ci */ 167f08c3bdfSopenharmony_civoid signal_handler(int sig, siginfo_t * info, void *vcontext) 168f08c3bdfSopenharmony_ci{ 169f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 170f08c3bdfSopenharmony_ci int isig = 0, *sigp = signals_to_handle; 171f08c3bdfSopenharmony_ci static siginfo_t infocopy; 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci /* 174f08c3bdfSopenharmony_ci * static copy of signal info. 175f08c3bdfSopenharmony_ci * Note, additional signals, before use, can overwrite 176f08c3bdfSopenharmony_ci */ 177f08c3bdfSopenharmony_ci infocopy = *info; 178f08c3bdfSopenharmony_ci gcp->siginfo = &infocopy; 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci while (*sigp) { 181f08c3bdfSopenharmony_ci if (*sigp == sig) 182f08c3bdfSopenharmony_ci break; 183f08c3bdfSopenharmony_ci ++isig; 184f08c3bdfSopenharmony_ci ++sigp; 185f08c3bdfSopenharmony_ci } 186f08c3bdfSopenharmony_ci gcp->signame = sig_names[isig]; 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci vprint("signal hander entered for sig %s\n", gcp->signame); 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci switch (sig) { 191f08c3bdfSopenharmony_ci case SIGSEGV: 192f08c3bdfSopenharmony_ci case SIGBUS: 193f08c3bdfSopenharmony_ci if (gcp->sigjmp) { 194f08c3bdfSopenharmony_ci gcp->sigjmp = false; 195f08c3bdfSopenharmony_ci siglongjmp(gcp->sigjmp_env, 1); 196f08c3bdfSopenharmony_ci } 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci die(8, "\n%s: signal %s, but siglongjmp not armed\n", 199f08c3bdfSopenharmony_ci gcp->program_name, gcp->signame); 200f08c3bdfSopenharmony_ci break; 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ci case SIGINT: 203f08c3bdfSopenharmony_ci case SIGQUIT: 204f08c3bdfSopenharmony_ci break; 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci default: 207f08c3bdfSopenharmony_ci die(8, "\n%s: Unexpected signal: %d\n", 208f08c3bdfSopenharmony_ci gcp->program_name, sig); 209f08c3bdfSopenharmony_ci break; 210f08c3bdfSopenharmony_ci } 211f08c3bdfSopenharmony_ci} 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_ci/* 214f08c3bdfSopenharmony_ci * set_signals() 215f08c3bdfSopenharmony_ci * 216f08c3bdfSopenharmony_ci * Setup signal dispositions to catch selected signals 217f08c3bdfSopenharmony_ci */ 218f08c3bdfSopenharmony_civoid set_signals() 219f08c3bdfSopenharmony_ci{ 220f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 221f08c3bdfSopenharmony_ci int *sigp = signals_to_handle; 222f08c3bdfSopenharmony_ci char **namep = sig_names; 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci struct sigaction act = { 225f08c3bdfSopenharmony_ci .sa_sigaction = signal_handler, 226f08c3bdfSopenharmony_ci .sa_flags = SA_SIGINFO 227f08c3bdfSopenharmony_ci }; 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci (void)sigfillset(&(act.sa_mask)); 230f08c3bdfSopenharmony_ci 231f08c3bdfSopenharmony_ci while (*sigp) { 232f08c3bdfSopenharmony_ci char *sig_name = *(namep++); 233f08c3bdfSopenharmony_ci int sig = *(sigp++); 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ci if (0 != sigaction(sig, &act, NULL)) { 236f08c3bdfSopenharmony_ci die(-1, "%s: Failed to set sigaction for %s\n", 237f08c3bdfSopenharmony_ci gcp->program_name, sig_name); 238f08c3bdfSopenharmony_ci } else 239f08c3bdfSopenharmony_ci#if 0 240f08c3bdfSopenharmony_ci vprint("%s: established handler for %s\n", 241f08c3bdfSopenharmony_ci gcp->program_name, sig_name) 242f08c3bdfSopenharmony_ci#endif 243f08c3bdfSopenharmony_ci ; 244f08c3bdfSopenharmony_ci } 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci return; 247f08c3bdfSopenharmony_ci} 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_civoid reset_signal(void) 250f08c3bdfSopenharmony_ci{ 251f08c3bdfSopenharmony_ci//TODO: free siginfo if/when malloc'd 252f08c3bdfSopenharmony_ci glctx.siginfo = NULL; 253f08c3bdfSopenharmony_ci glctx.sigjmp = false; 254f08c3bdfSopenharmony_ci} 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_civoid wait_for_signal(const char *mesg) 257f08c3bdfSopenharmony_ci{ 258f08c3bdfSopenharmony_ci printf("%s ... ", mesg); 259f08c3bdfSopenharmony_ci fflush(stdout); 260f08c3bdfSopenharmony_ci pause(); 261f08c3bdfSopenharmony_ci vprint("%s: wakened by signal %s\n", __FUNCTION__, glctx.signame); 262f08c3bdfSopenharmony_ci reset_signal(); 263f08c3bdfSopenharmony_ci printf("\n"); 264f08c3bdfSopenharmony_ci fflush(stdout); 265f08c3bdfSopenharmony_ci} 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_civoid show_siginfo() 268f08c3bdfSopenharmony_ci{ 269f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 270f08c3bdfSopenharmony_ci siginfo_t *info = gcp->siginfo; 271f08c3bdfSopenharmony_ci void *badaddr = info->si_addr; 272f08c3bdfSopenharmony_ci char *sigcode; 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci switch (info->si_signo) { 275f08c3bdfSopenharmony_ci case SIGSEGV: 276f08c3bdfSopenharmony_ci switch (info->si_code) { 277f08c3bdfSopenharmony_ci case SEGV_MAPERR: 278f08c3bdfSopenharmony_ci sigcode = "address not mapped"; 279f08c3bdfSopenharmony_ci break; 280f08c3bdfSopenharmony_ci 281f08c3bdfSopenharmony_ci case SEGV_ACCERR: 282f08c3bdfSopenharmony_ci sigcode = "invalid access error"; 283f08c3bdfSopenharmony_ci break; 284f08c3bdfSopenharmony_ci 285f08c3bdfSopenharmony_ci default: 286f08c3bdfSopenharmony_ci sigcode = "unknown"; 287f08c3bdfSopenharmony_ci break; 288f08c3bdfSopenharmony_ci } 289f08c3bdfSopenharmony_ci break; 290f08c3bdfSopenharmony_ci 291f08c3bdfSopenharmony_ci case SIGBUS: 292f08c3bdfSopenharmony_ci switch (info->si_code) { 293f08c3bdfSopenharmony_ci case BUS_ADRALN: 294f08c3bdfSopenharmony_ci sigcode = "invalid address alignment"; 295f08c3bdfSopenharmony_ci break; 296f08c3bdfSopenharmony_ci 297f08c3bdfSopenharmony_ci case BUS_ADRERR: 298f08c3bdfSopenharmony_ci sigcode = "non-existent physical address"; 299f08c3bdfSopenharmony_ci break; 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_ci default: 302f08c3bdfSopenharmony_ci sigcode = "unknown"; 303f08c3bdfSopenharmony_ci break; 304f08c3bdfSopenharmony_ci } 305f08c3bdfSopenharmony_ci break; 306f08c3bdfSopenharmony_ci 307f08c3bdfSopenharmony_ci default: 308f08c3bdfSopenharmony_ci /* 309f08c3bdfSopenharmony_ci * ignore SIGINT/SIGQUIT 310f08c3bdfSopenharmony_ci */ 311f08c3bdfSopenharmony_ci return; 312f08c3bdfSopenharmony_ci } 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci printf("Signal %s @ 0x%lx - %s\n", gcp->signame, badaddr, sigcode); 315f08c3bdfSopenharmony_ci 316f08c3bdfSopenharmony_ci} 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_ci/* 319f08c3bdfSopenharmony_ci * ========================================================================= 320f08c3bdfSopenharmony_ci */ 321f08c3bdfSopenharmony_ci 322f08c3bdfSopenharmony_civoid touch_memory(bool rw, unsigned long *memp, size_t memlen) 323f08c3bdfSopenharmony_ci{ 324f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci unsigned long *memend, *pp, sink; 327f08c3bdfSopenharmony_ci unsigned long longs_in_page = gcp->pagesize / sizeof(unsigned long); 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_ci memend = memp + memlen / sizeof(unsigned long); 330f08c3bdfSopenharmony_ci vprint("!!!%s from 0x%lx thru 0x%lx\n", 331f08c3bdfSopenharmony_ci rw ? "Writing" : "Reading", memp, memend); 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_ci for (pp = memp; pp < memend; pp += longs_in_page) { 334f08c3bdfSopenharmony_ci // vprint("%s: touching 0x%lx\n", __FUNCTION__, pp); 335f08c3bdfSopenharmony_ci if (!sigsetjmp(gcp->sigjmp_env, true)) { 336f08c3bdfSopenharmony_ci gcp->sigjmp = true; 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_ci /* 339f08c3bdfSopenharmony_ci * Mah-ahm! He's touching me! 340f08c3bdfSopenharmony_ci */ 341f08c3bdfSopenharmony_ci if (rw) 342f08c3bdfSopenharmony_ci *pp = (unsigned long)pp; 343f08c3bdfSopenharmony_ci else 344f08c3bdfSopenharmony_ci sink = *pp; 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_ci gcp->sigjmp = false; 347f08c3bdfSopenharmony_ci } else { 348f08c3bdfSopenharmony_ci show_siginfo(); 349f08c3bdfSopenharmony_ci reset_signal(); 350f08c3bdfSopenharmony_ci break; 351f08c3bdfSopenharmony_ci } 352f08c3bdfSopenharmony_ci 353f08c3bdfSopenharmony_ci /* 354f08c3bdfSopenharmony_ci * Any [handled] signal breaks the loop 355f08c3bdfSopenharmony_ci */ 356f08c3bdfSopenharmony_ci if (gcp->siginfo != NULL) { 357f08c3bdfSopenharmony_ci reset_signal(); 358f08c3bdfSopenharmony_ci break; 359f08c3bdfSopenharmony_ci } 360f08c3bdfSopenharmony_ci } 361f08c3bdfSopenharmony_ci} 362f08c3bdfSopenharmony_ci 363f08c3bdfSopenharmony_ci/* 364f08c3bdfSopenharmony_ci * ========================================================================= 365f08c3bdfSopenharmony_ci */ 366f08c3bdfSopenharmony_ci 367f08c3bdfSopenharmony_civoid init_glctx(glctx_t * gcp) 368f08c3bdfSopenharmony_ci{ 369f08c3bdfSopenharmony_ci 370f08c3bdfSopenharmony_ci memset(gcp, 0, sizeof(glctx_t)); 371f08c3bdfSopenharmony_ci 372f08c3bdfSopenharmony_ci gcp->pagesize = (size_t) sysconf(_SC_PAGESIZE); 373f08c3bdfSopenharmony_ci 374f08c3bdfSopenharmony_ci if (numa_available() >= 0) { 375f08c3bdfSopenharmony_ci gcp->numa_max_node = numa_max_node(); 376f08c3bdfSopenharmony_ci } else 377f08c3bdfSopenharmony_ci gcp->numa_max_node = -1; 378f08c3bdfSopenharmony_ci 379f08c3bdfSopenharmony_ci segment_init(gcp); 380f08c3bdfSopenharmony_ci 381f08c3bdfSopenharmony_ci if (isatty(fileno(stdin))) 382f08c3bdfSopenharmony_ci set_option(INTERACTIVE); 383f08c3bdfSopenharmony_ci 384f08c3bdfSopenharmony_ci} 385f08c3bdfSopenharmony_ci 386f08c3bdfSopenharmony_ci/* 387f08c3bdfSopenharmony_ci * cleanup() - at exit cleanup routine 388f08c3bdfSopenharmony_ci */ 389f08c3bdfSopenharmony_cistatic void cleanup() 390f08c3bdfSopenharmony_ci{ 391f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 392f08c3bdfSopenharmony_ci 393f08c3bdfSopenharmony_ci segment_cleanup(gcp); 394f08c3bdfSopenharmony_ci} /* cleanup() */ 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ciint parse_command_line_args(int argc, char *argv[]) 397f08c3bdfSopenharmony_ci{ 398f08c3bdfSopenharmony_ci extern int optind; 399f08c3bdfSopenharmony_ci extern char *optarg; 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 402f08c3bdfSopenharmony_ci int argval; 403f08c3bdfSopenharmony_ci int error = 0; 404f08c3bdfSopenharmony_ci 405f08c3bdfSopenharmony_ci char c; 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci gcp->program_name = basename(argv[0]); 408f08c3bdfSopenharmony_ci 409f08c3bdfSopenharmony_ci /* 410f08c3bdfSopenharmony_ci * process command line options. 411f08c3bdfSopenharmony_ci */ 412f08c3bdfSopenharmony_ci while ((c = getopt(argc, argv, OPTIONS)) != (char)EOF) { 413f08c3bdfSopenharmony_ci char *next; 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci switch (c) { 416f08c3bdfSopenharmony_ci 417f08c3bdfSopenharmony_ci case 'v': 418f08c3bdfSopenharmony_ci set_option(VERBOSE); 419f08c3bdfSopenharmony_ci break; 420f08c3bdfSopenharmony_ci 421f08c3bdfSopenharmony_ci case 'h': 422f08c3bdfSopenharmony_ci case 'x': 423f08c3bdfSopenharmony_ci usage(NULL); 424f08c3bdfSopenharmony_ci 425f08c3bdfSopenharmony_ci break; 426f08c3bdfSopenharmony_ci 427f08c3bdfSopenharmony_ci case 'V': 428f08c3bdfSopenharmony_ci printf("memtoy " MEMTOY_VERSION " built " 429f08c3bdfSopenharmony_ci __DATE__ " @ " __TIME__ "\n"); 430f08c3bdfSopenharmony_ci exit(0); 431f08c3bdfSopenharmony_ci break; 432f08c3bdfSopenharmony_ci 433f08c3bdfSopenharmony_ci#ifdef _DEBUG 434f08c3bdfSopenharmony_ci case '0': 435f08c3bdfSopenharmony_ci argval = strtoul(optarg, &next, 0); 436f08c3bdfSopenharmony_ci if (*next != '\0') { 437f08c3bdfSopenharmony_ci fprintf(stderr, 438f08c3bdfSopenharmony_ci "-D <debug-mask> must be unsigned hex/decimal integer\n"); 439f08c3bdfSopenharmony_ci ++error; 440f08c3bdfSopenharmony_ci } else 441f08c3bdfSopenharmony_ci gcp->debug = argval; 442f08c3bdfSopenharmony_ci break; 443f08c3bdfSopenharmony_ci#endif 444f08c3bdfSopenharmony_ci 445f08c3bdfSopenharmony_ci default: 446f08c3bdfSopenharmony_ci error = 1; 447f08c3bdfSopenharmony_ci break; 448f08c3bdfSopenharmony_ci } 449f08c3bdfSopenharmony_ci } 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ci return (error); 452f08c3bdfSopenharmony_ci} 453f08c3bdfSopenharmony_ci 454f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 455f08c3bdfSopenharmony_ci{ 456f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 457f08c3bdfSopenharmony_ci bool user_is_super; 458f08c3bdfSopenharmony_ci int error; 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci init_glctx(gcp); 461f08c3bdfSopenharmony_ci if (!is_option(INTERACTIVE)) 462f08c3bdfSopenharmony_ci setbuf(stdout, NULL); 463f08c3bdfSopenharmony_ci 464f08c3bdfSopenharmony_ci /* 465f08c3bdfSopenharmony_ci * Register cleanup handler 466f08c3bdfSopenharmony_ci */ 467f08c3bdfSopenharmony_ci if (atexit(cleanup) != 0) { 468f08c3bdfSopenharmony_ci die(-1, "%s: atexit(cleanup) registration failed\n", argv[0]); 469f08c3bdfSopenharmony_ci } 470f08c3bdfSopenharmony_ci 471f08c3bdfSopenharmony_ci user_is_super = (geteuid() == 0); 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci error = parse_command_line_args(argc, argv); 474f08c3bdfSopenharmony_ci 475f08c3bdfSopenharmony_ci if (error /* || argc==1 */ ) { 476f08c3bdfSopenharmony_ci usage(NULL); 477f08c3bdfSopenharmony_ci 478f08c3bdfSopenharmony_ci } 479f08c3bdfSopenharmony_ci 480f08c3bdfSopenharmony_ci /* 481f08c3bdfSopenharmony_ci * actual program logic starts here 482f08c3bdfSopenharmony_ci */ 483f08c3bdfSopenharmony_ci printf("memtoy pid: %d\n", getpid()); 484f08c3bdfSopenharmony_ci vprint("%s: pagesize = %d\n", gcp->program_name, gcp->pagesize); 485f08c3bdfSopenharmony_ci if (gcp->numa_max_node >= 0) 486f08c3bdfSopenharmony_ci vprint("%s: NUMA available - max node: %d\n", 487f08c3bdfSopenharmony_ci gcp->program_name, gcp->numa_max_node); 488f08c3bdfSopenharmony_ci 489f08c3bdfSopenharmony_ci set_signals(); 490f08c3bdfSopenharmony_ci 491f08c3bdfSopenharmony_ci process_commands(); 492f08c3bdfSopenharmony_ci 493f08c3bdfSopenharmony_ci return 0; 494f08c3bdfSopenharmony_ci 495f08c3bdfSopenharmony_ci} 496f08c3bdfSopenharmony_ci#else 497f08c3bdfSopenharmony_ciint main(void) 498f08c3bdfSopenharmony_ci{ 499f08c3bdfSopenharmony_ci fprintf(stderr, NUMA_ERROR_MSG "\n"); 500f08c3bdfSopenharmony_ci return TCONF; 501f08c3bdfSopenharmony_ci} 502f08c3bdfSopenharmony_ci#endif 503