1/*****************************************************************************/
2/*                                                                           */
3/*  Copyright (c) 2010 Mohamed Naufal Basheer                                */
4/*                                                                           */
5/*  This program is free software;  you can redistribute it and/or modify    */
6/*  it under the terms of the GNU General Public License as published by     */
7/*  the Free Software Foundation; either version 2 of the License, or        */
8/*  (at your option) any later version.                                      */
9/*                                                                           */
10/*  This program is distributed in the hope that it will be useful,          */
11/*  but WITHOUT ANY WARRANTY;  without even the implied warranty of          */
12/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                */
13/*  the GNU General Public License for more details.                         */
14/*                                                                           */
15/*  You should have received a copy of the GNU General Public License        */
16/*  along with this program;  if not, write to the Free Software             */
17/*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  */
18/*                                                                           */
19/*  File:    mem_process.c                                                   */
20/*                                                                           */
21/*  Purpose: act as a memory hog for the memcg_control tests                 */
22/*                                                                           */
23/*  Author:  Mohamed Naufal Basheer <naufal11@gmail.com >                    */
24/*                                                                           */
25/*****************************************************************************/
26
27#include <sys/types.h>
28#include <sys/mman.h>
29#include <sys/stat.h>
30#include <err.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <unistd.h>
36
37/*
38 * Named pipe to act as a communication channel between
39 * shell script & this process
40 */
41#define STATUS_PIPE "status_pipe"
42
43int flag_exit;
44int flag_allocated;
45unsigned long memsize;
46
47/*
48 * process_options: process user specified options
49 */
50void process_options(int argc, char **argv)
51{
52	int c;
53	char *end;
54
55	opterr = 0;
56	while ((c = getopt(argc, argv, "pm:")) != -1) {
57		switch (c) {
58		case 'm':
59			memsize = strtoul(optarg, &end, 10);
60			if (*end != '\0')
61				errx(2, "invalid -m usage");
62			break;
63		case 'p':
64			printf("%d\n", getpagesize());
65			exit(0);
66		default:
67			errx(2, "invalid option specifed");
68		}
69	}
70
71	if (memsize <= 0)
72		errx(3, "invalid usage");
73}
74
75/*
76 * touch_memory: force physical memory allocation
77 */
78void touch_memory(char *p)
79{
80	int i;
81	int pagesize = getpagesize();
82
83	for (i = 0; i < memsize; i += pagesize)
84		p[i] = 0xef;
85}
86
87void mem_map()
88{
89	static char *p;
90
91	if (flag_allocated) {
92		if (munmap(p, memsize) == -1)
93			err(5, "munmap failed");
94	} else {
95		p = mmap(NULL, memsize, PROT_READ | PROT_WRITE,
96			 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
97		if (p == MAP_FAILED)
98			err(4, "mmap failed");
99		touch_memory(p);
100	}
101	flag_allocated = !flag_allocated;
102}
103
104/*
105 * done: retrieve instructions from the named pipe
106 */
107char action()
108{
109	char ch;
110	int fd;
111
112	if ((fd = open(STATUS_PIPE, O_RDONLY)) == -1)
113		err(6, "Error opening named pipe");
114
115	if (read(fd, &ch, 1) == -1)
116		err(7, "Error reading named pipe");
117
118	close(fd);
119
120	return ch;
121}
122
123int main(int argc, char **argv)
124{
125	int ret;
126	char ch;
127
128	process_options(argc, argv);
129
130	ret = mkfifo(STATUS_PIPE, 0666);
131
132	if (ret == -1 && errno != EEXIST)
133		errx(1, "Error creating named pipe");
134
135	do {
136		ch = action();
137
138		if (ch == 'm')
139			mem_map();
140	} while (ch != 'x');
141
142	remove(STATUS_PIPE);
143
144	return 0;
145}
146