1/******************************************************************************/
2/*                                                                            */
3/* Copyright (c) International Business Machines  Corp., 2007                 */
4/* Copyright (c) Linux Test Project, 2016                                     */
5/*                                                                            */
6/* This program is free software: you can redistribute it and/or modify       */
7/* it under the terms of the GNU General Public License as published by       */
8/* the Free Software Foundation, either version 3 of the License, or          */
9/* (at your option) any later version.                                        */
10/*                                                                            */
11/* This program is distributed in the hope that it will be useful,            */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              */
14/* GNU General Public License for more details.                               */
15/*                                                                            */
16/* You should have received a copy of the GNU General Public License          */
17/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
18/*                                                                            */
19/******************************************************************************/
20
21/******************************************************************************/
22/*                                                                            */
23/* File:        support_numa.c                                                */
24/*                                                                            */
25/* Description: Allocates memory and touches it to verify numa                */
26/*                                                                            */
27/* Author:      Sivakumar Chinnaiah  Sivakumar.C@in.ibm.com                   */
28/*                                                                            */
29/******************************************************************************/
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <errno.h>
34#include <unistd.h>
35#include <signal.h>
36#include <limits.h>
37#include <string.h>
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <sys/mman.h>
41#include <fcntl.h>
42#include "lapi/mmap.h"
43
44/* Global Variables */
45#define MB (1<<20)
46#define PAGE_SIZE getpagesize()
47#define barrier() __asm__ __volatile__("": : :"memory")
48#define TEST_SFILE "ltp_numa_testfile"
49#define STR "abcdefghijklmnopqrstuvwxyz12345\n"
50
51static void help(void)
52{
53	printf("Input:	Describe input arguments to this program\n");
54	printf("	argv[1] == \"alloc_1MB\" then allocate 1MB of memory\n");
55	printf("	argv[1] == \"alloc_1MB_shared\" then allocate 1MB of share memory\n");
56	printf("	argv[1] == \"alloc_2HPSZ_THP\" then allocate 2HUGE PAGE SIZE of THP memory\n");
57	printf("        argv[1] == \"alloc_1huge_page\" then allocate 1HUGE PAGE SIZE of memory\n");
58	printf("        argv[1] == \"pause\" then pause the program to catch sigint\n");
59	printf("Exit:	On failure - Exits with non-zero value\n");
60	printf("	On success - exits with 0 exit value\n");
61
62	exit(1);
63}
64
65static int read_hugepagesize(void)
66{
67	FILE *fp;
68	char line[BUFSIZ], buf[BUFSIZ];
69	int val;
70
71	fp = fopen("/proc/meminfo", "r");
72	if (fp == NULL) {
73		fprintf(stderr, "Failed to open /proc/meminfo");
74		return 0;
75	}
76
77	while (fgets(line, BUFSIZ, fp) != NULL) {
78		if (sscanf(line, "%64s %d", buf, &val) == 2)
79			if (strcmp(buf, "Hugepagesize:") == 0) {
80				fclose(fp);
81				return 1024 * val;
82			}
83	}
84
85	fclose(fp);
86	fprintf(stderr, "can't find \"%s\" in %s", "Hugepagesize:", "/proc/meminfo");
87
88	return 0;
89}
90
91int main(int argc, char *argv[])
92{
93	int i, fd, rc, hpsz;
94	char *buf = NULL;
95	struct stat sb;
96
97	if (argc != 2) {
98		fprintf(stderr, "Here expect only one number(i.e. 2) as the parameter\n");
99		exit(1);
100	}
101
102	if (!strcmp(argv[1], "alloc_1MB")) {
103		buf = malloc(MB);
104		if (!buf) {
105			fprintf(stderr, "Memory is not available\n");
106			exit(1);
107		}
108		for (i = 0; i < MB; i += PAGE_SIZE) {
109			buf[i] = 'a';
110			barrier();
111		}
112
113		raise(SIGSTOP);
114
115		free(buf);
116	} else if (!strcmp(argv[1], "alloc_1MB_shared")) {
117		fd = open(TEST_SFILE, O_RDWR | O_CREAT, 0666);
118		/* Writing 1MB of random data into this file [32 * 32768 = 1024 * 1024] */
119		for (i = 0; i < 32768; i++){
120			rc = write(fd, STR, strlen(STR));
121			if (rc == -1 || ((size_t)rc != strlen(STR)))
122				fprintf(stderr, "write failed\n");
123		}
124
125		if ((fstat(fd, &sb)) == -1)
126			fprintf(stderr, "fstat failed\n");
127
128		buf = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
129		if (buf == MAP_FAILED){
130			fprintf(stderr, "mmap failed\n");
131			close(fd);
132			exit(1);
133		}
134
135		memset(buf, 'a', sb.st_size);
136
137		raise(SIGSTOP);
138
139		munmap(buf, sb.st_size);
140		close(fd);
141		remove(TEST_SFILE);
142	} else if (!strcmp(argv[1], "alloc_2HPSZ_THP")) {
143		ssize_t size = 2 * read_hugepagesize();
144		if (size == 0)
145			exit(1);
146
147		buf = mmap(NULL, size, PROT_READ | PROT_WRITE,
148				MAP_PRIVATE | MAP_ANONYMOUS,
149				-1, 0);
150		if (buf == MAP_FAILED) {
151			perror("mmap failed");
152			exit(1);
153		}
154
155		memset(buf, 'a', size);
156
157		raise(SIGSTOP);
158
159		munmap(buf, size);
160	} else if (!strcmp(argv[1], "alloc_1huge_page")) {
161		hpsz = read_hugepagesize();
162		if (hpsz == 0)
163			exit(1);
164
165		buf = mmap(NULL, hpsz, PROT_READ | PROT_WRITE,
166				MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
167				-1, 0);
168
169		if (buf == MAP_FAILED) {
170			perror("mmap failed");
171			exit(1);
172		}
173
174		memset(buf, 'a', hpsz);
175
176		raise(SIGSTOP);
177
178		munmap(buf, hpsz);
179	} else if (!strcmp(argv[1], "pause")) {
180		raise(SIGSTOP);
181	} else {
182		help();
183	}
184
185	return 0;
186}
187