blob: b5458944797512e870b552654ab8e43a505c5003 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/******************************************************************************/
2/* */
3/* Copyright (c) International Business Machines Corp., 2001 */
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 */
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
plars865695b2001-08-27 22:15:12 +000018/* */
19/******************************************************************************/
20
plars865695b2001-08-27 22:15:12 +000021/******************************************************************************/
22/* */
23/* History: July - 16 - 2001 Created by Manoj Iyer, IBM Austin TX. */
24/* email:manjo@austin.ibm.com */
25/* */
26/* July - 24 - 2001 Modified. Added loop and pass arguments to */
27/* the thread function. Fixed usage function. */
28/* added option to MAP_PRIVATE or MAP_SHARED. */
29/* */
30/* Aug - 01 - 2001 Modified. Added include file signal.h */
31/* has defines required by signal handler. */
32/* */
iyermanoj26a01832001-10-25 20:13:52 +000033/* Oct - 25 - 2001 Modified. Fixed bug in main(). Pthread_join */
34/* sets the return value of the thread in thread*/
35/* return_status parameter. */
iyermanojc839ac42001-11-09 23:24:13 +000036/* Nov - 09 - 2001 Modified. Removed compile errors */
37/* - incomplete comment in line 301 */
38/* - missing argument to printf in pthread_join */
robbiew173b0452003-04-16 19:46:42 +000039/* */
40/* Apr - 16 - 2003 Modified - replaced tempnam() use with */
41/* mkstemp(). -Robbie Williamson */
42/* email:robbiew@us.ibm.com */
plars52601372003-05-12 22:04:16 +000043/* */
44/* May - 12 - 2003 Modified - remove the really large files */
45/* when we are done with the test - Paul Larson */
46/* email:plars@linuxtestproject.org */
plars865695b2001-08-27 22:15:12 +000047/* File: mmap3.c */
48/* */
49/* Description: Test the LINUX memory manager. The program is aimed at */
50/* stressing the memory manager by repeaded map/write/unmap */
51/* of file/memory of random size (maximum 1GB) this is done by */
52/* multiple processes. */
53/* */
54/* Create a file of random size upto 1000 times 4096, map it, */
55/* change the contents of the file and unmap it. This is repeated*/
56/* several times for the specified number of hours by a certain. */
57/* number of processes. */
58/* */
59/******************************************************************************/
60
plars865695b2001-08-27 22:15:12 +000061/* Include Files */
62#include <stdio.h>
63#include <sys/types.h>
64#include <sys/stat.h>
65#include <fcntl.h>
66#include <unistd.h>
67#include <errno.h>
68#include <sys/mman.h>
69#include <sched.h>
70#include <stdlib.h>
71#include <signal.h>
72#include <sys/time.h>
73#include <sys/wait.h>
74#include <pthread.h>
75#include <signal.h>
robbiew88e7b182003-03-13 19:00:13 +000076#include <string.h>
robbiew173b0452003-04-16 19:46:42 +000077#include "test.h"
plars865695b2001-08-27 22:15:12 +000078
79/* Defines */
80#ifndef TRUE
81#define TRUE 1
82#endif
83#ifndef FALSE
84#define FALSE 0
85#endif
86#define prtln() printf(" I AM HERE ==> %s %d\n", __FILE__, __LINE__);
87
88/******************************************************************************/
89/* */
90/* Function: mkfile */
91/* */
92/* Description: Create a temparory file of ramdom size. */
93/* */
94/* Input: NONE */
95/* */
robbiew173b0452003-04-16 19:46:42 +000096/* Output: size - size of the temp file created */
plars865695b2001-08-27 22:15:12 +000097/* */
98/* Return: int fd - file descriptor if the file was created. */
99/* -1 - if it failed to create. */
100/* */
101/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102static int mkfile(int *size)
103{ /* size of the file to be generated in GB */
104 int fd; /* file descriptior of tmpfile */
105 int index = 0; /* index into the file, fill it with a's */
106 char buff[4096]; /* buffer that will be written to the file. */
107 char template[PATH_MAX]; /* template for temp file name */
plars865695b2001-08-27 22:15:12 +0000108
Wanlong Gao354ebb42012-12-07 10:10:04 +0800109 /* fill the buffer with a's and open a temp file */
110 memset(buff, 'a', 4096);
111 snprintf(template, PATH_MAX, "ashfileXXXXXX");
112 if ((fd = mkstemp(template)) == -1) {
113 perror("mkfile(): mkstemp()");
114 return -1;
plars865695b2001-08-27 22:15:12 +0000115 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800116 unlink(template);
Garrett Cooper2c282152010-12-16 00:55:50 -0800117
Wanlong Gao354ebb42012-12-07 10:10:04 +0800118 srand(time(NULL) % 100);
119 *size = (1 + (int)(1000.0 * rand() / (RAND_MAX + 1.0))) * 4096;
120
121 /* fill the file with the character a */
122 while (index < *size) {
123 index += 4096;
124 if (write(fd, buff, 4096) == -1) {
125 perror("mkfile(): write()");
126 return -1;
127 }
128 }
129
130 /* make sure a's are written to the file. */
131 if (fsync(fd) == -1) {
132 perror("mkfile(): fsync()");
133 return -1;
134 }
135 return fd;
plars865695b2001-08-27 22:15:12 +0000136}
137
138/******************************************************************************/
139/* */
140/* Function: sig_handler */
141/* */
142/* Description: handle SIGALRM raised by set_timer(), SIGALRM is raised when */
143/* the timer expires. If any other signal is recived exit the */
144/* test. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145 /* *//* Input: signal - signal number, intrested in SIGALRM! */
plars865695b2001-08-27 22:15:12 +0000146/* */
147/* Return: exit 1 if unexpected signal is recived */
148/* exit 0 if SIGALRM is recieved */
149/* */
150/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151static void sig_handler(int signal)
152{ /* signal number, set to handle SIGALRM */
153 if (signal != SIGALRM) {
154 fprintf(stderr,
155 "sig_handlder(): unexpected signal caught [%d]\n",
156 signal);
157 exit(-1);
158 } else
159 fprintf(stdout, "Test ended, success\n");
160 exit(0);
plars865695b2001-08-27 22:15:12 +0000161}
162
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163 /******************************************************************************//* */
plars865695b2001-08-27 22:15:12 +0000164/* Function: usage */
165/* */
166/* Description: Print the usage message. */
167/* */
168/* Return: exits with -1 */
169/* */
170/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171static void usage(char *progname)
172{ /* name of this program */
173 fprintf(stderr,
174 "Usage: %s -h -l -n -p -x\n"
175 "\t -h help, usage message.\n"
176 "\t -l number of map - write - unmap. default: 1000\n"
177 "\t -n number of LWP's to create. default: 20\n"
178 "\t -p set mapping to MAP_PRIVATE. default: MAP_SHARED\n"
179 "\t -x time for which test is to be run. default: 24 Hrs\n",
180 progname);
181 exit(-1);
plars865695b2001-08-27 22:15:12 +0000182}
183
plars865695b2001-08-27 22:15:12 +0000184/******************************************************************************/
185/* */
186/* Function: map_write_unmap */
187/* */
188/* Description: map a file write a character to it and unmap, this is done for*/
189/* user defined number of times. */
190/* */
191/* Input: arg[0] number of times map - write -unmap is done */
192/* arg[1] Map type: */
193/* TRUE - MAP_PRIVATE */
194/* FALSE - MAP_SHARED */
195/* */
196/* Return: MWU_FAIL on error. */
197/* MWU_SUCCESS on error less completion of the loop. */
198/* */
199/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800200void *map_write_unmap(void *args)
201{ /* file descriptor of the file to be mapped. */
202 int fsize; /* size of the file to be created. */
203 int fd; /* temporary file descriptor */
204 int mwu_ndx = 0; /* index to number of map/write/unmap */
205 caddr_t *map_address; /* pointer to file in memory */
206 int map_type; /* MAP_PRIVATE or MAP_SHARED */
207 long *mwuargs = /* local pointer to arguments */
208 (long *)args;
plars865695b2001-08-27 22:15:12 +0000209
Wanlong Gao354ebb42012-12-07 10:10:04 +0800210 while (mwu_ndx++ < (int)mwuargs[0]) {
211 if ((fd = mkfile(&fsize)) == -1) {
212 fprintf(stderr,
213 "main(): mkfile(): Failed to create temp file.\n");
214 pthread_exit((void *)-1);
215 }
plars865695b2001-08-27 22:15:12 +0000216
Wanlong Gao354ebb42012-12-07 10:10:04 +0800217 if ((int)mwuargs[1])
218 map_type = MAP_PRIVATE;
219 else
220 map_type = MAP_SHARED;
221 if ((map_address =
222 mmap(0, (size_t) fsize, PROT_WRITE | PROT_READ, map_type,
223 (int)fd, 0))
224 == (caddr_t *) - 1) {
225 perror("map_write_unmap(): mmap()");
226 pthread_exit((void *)-1);
227 }
plars865695b2001-08-27 22:15:12 +0000228
Wanlong Gao354ebb42012-12-07 10:10:04 +0800229 memset(map_address, 'A', fsize);
plars865695b2001-08-27 22:15:12 +0000230
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 fprintf(stdout,
232 "Map address = %p\nNum iter: [%d]\nTotal Num Iter: [%d]",
233 map_address, mwu_ndx, (int)mwuargs[0]);
234 usleep(1);
235 if (munmap(map_address, (size_t) fsize) == -1) {
236 perror("map_write_unmap(): mmap()");
237 pthread_exit((void *)-1);
238 }
239 close(fd);
240 }
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200241 pthread_exit(NULL);
plars865695b2001-08-27 22:15:12 +0000242}
243
plars865695b2001-08-27 22:15:12 +0000244/******************************************************************************/
245/* */
246/* Function: main */
247/* */
248/* Descrption: Create a large file of size up to a Giga Bytes. write to it */
249/* lower case alphabet 'a'. Map the file and change the contents */
250/* to 'A's (upper case alphabet), write the contents to the file,*/
251/* and unmap the file from memory. Spwan a certian number of */
iyermanojc839ac42001-11-09 23:24:13 +0000252/* LWP's that will do the above. */
plars865695b2001-08-27 22:15:12 +0000253/* */
254/* Return: exits with -1 on error */
255/* exits with a 0 on success. */
256/* */
257/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800258int main(int argc, /* number of input parameters. */
259 char **argv)
260{ /* pointer to the command line arguments. */
261 int c; /* command line options */
262 int num_iter; /* number of iteration to perform */
263 int num_thrd; /* number of threads to create */
264 int thrd_ndx; /* index into the array of threads. */
265 float exec_time; /* period for which the test is executed */
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500266 void *status; /* exit status for light weight process */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800267 int sig_ndx; /* index into signal handler structure. */
268 pthread_t thid[1000]; /* pids of process that will map/write/unmap */
269 long chld_args[3]; /* arguments to funcs execed by child process */
270 extern char *optarg; /* arguments passed to each option */
271 struct sigaction sigptr; /* set up signal, for interval timer */
272 int map_private = /* if TRUE mapping is private, ie, MAP_PRIVATE */
273 FALSE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800274
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 static struct signal_info {
276 int signum; /* signal number that hasto be handled */
277 char *signame; /* name of the signal to be handled. */
278 } sig_info[] = {
279 {
280 SIGHUP, "SIGHUP"}, {
281 SIGINT, "SIGINT"}, {
282 SIGQUIT, "SIGQUIT"}, {
283 SIGABRT, "SIGABRT"}, {
284 SIGBUS, "SIGBUS"}, {
285 SIGSEGV, "SIGSEGV"}, {
286 SIGALRM, "SIGALRM"}, {
287 SIGUSR1, "SIGUSR1"}, {
288 SIGUSR2, "SIGUSR2"}, {
289 -1, "ENDSIG"}
290 };
plars865695b2001-08-27 22:15:12 +0000291
Wanlong Gao354ebb42012-12-07 10:10:04 +0800292 /* set up the default values */
293 num_iter = 1000; /* repeate map - write - unmap operation 1000 times */
294 num_thrd = 40; /* number of LWP's to create */
295 exec_time = 24; /* minimum time period for which to run the tests */
plars865695b2001-08-27 22:15:12 +0000296
Wanlong Gao354ebb42012-12-07 10:10:04 +0800297 while ((c = getopt(argc, argv, "h:l:n:px:")) != -1) {
298 switch (c) {
299 case 'h':
300 usage(argv[0]);
301 break;
302 case 'l':
303 if ((num_iter = atoi(optarg)) == 0)
304 num_iter = 1000;
305 break;
306 case 'n':
307 if ((num_thrd = atoi(optarg)) == 0)
308 num_thrd = 20;
309 break;
310 case 'p':
311 map_private = TRUE;
312 break;
313 case 'x':
314 if ((exec_time = atof(optarg)) == 0)
315 exec_time = 24;
316 break;
317 default:
318 usage(argv[0]);
319 break;
320 }
321 }
plars865695b2001-08-27 22:15:12 +0000322
Wanlong Gao354ebb42012-12-07 10:10:04 +0800323 /* set up signals */
324 sigptr.sa_handler = (void (*)(int signal))sig_handler;
325 sigfillset(&sigptr.sa_mask);
326 sigptr.sa_flags = SA_SIGINFO;
327 for (sig_ndx = 0; sig_info[sig_ndx].signum != -1; sig_ndx++) {
328 sigaddset(&sigptr.sa_mask, sig_info[sig_ndx].signum);
329 if (sigaction(sig_info[sig_ndx].signum, &sigptr,
Cyril Hrubiscf0d6262014-09-23 14:03:31 +0200330 NULL) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800331 perror("man(): sigaction()");
332 fprintf(stderr,
333 "could not set handler for SIGALRM, errno = %d\n",
334 errno);
335 exit(-1);
336 }
337 }
338 chld_args[0] = num_iter;
339 chld_args[1] = map_private;
340 alarm(exec_time * 3600.00);
plars865695b2001-08-27 22:15:12 +0000341
Wanlong Gao354ebb42012-12-07 10:10:04 +0800342 fprintf(stdout,
343 "\n\n\nTest is set to run with the following parameters:\n"
344 "\tDuration of test: [%f]hrs\n"
345 "\tNumber of threads created: [%d]\n"
346 "\tnumber of map-write-unmaps: [%d]\n"
347 "\tmap_private?(T=1 F=0): [%d]\n\n\n\n", exec_time, num_thrd,
348 num_iter, map_private);
plars865695b2001-08-27 22:15:12 +0000349
Wanlong Gao354ebb42012-12-07 10:10:04 +0800350 for (;;) {
351 /* create num_thrd number of threads. */
352 for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
353 if (pthread_create
354 (&thid[thrd_ndx], NULL, map_write_unmap,
355 chld_args)) {
356 perror("main(): pthread_create()");
357 exit(-1);
358 }
359 sched_yield();
360 }
plars865695b2001-08-27 22:15:12 +0000361
Wanlong Gao354ebb42012-12-07 10:10:04 +0800362 /* wait for the children to terminate */
363 for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500364 if (pthread_join(thid[thrd_ndx], &status)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800365 perror("main(): pthread_create()");
366 exit(-1);
367 } else {
368 if (status) {
369 fprintf(stderr,
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500370 "thread [%d] - process exited with errors %ld\n",
371 WEXITSTATUS((long)status),
372 (long)status);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800373 exit(-1);
374 }
375 }
376 }
377 }
378 exit(0);
Cyril Hrubisfea169d2011-11-09 16:28:30 +0100379}