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