blob: 5f3897bc0543201524d005344fff95f02813495a [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/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +000021/* */
22/* File: mmstress.c */
23/* */
24/* Description: This is a test program that performs general stress with */
subrata_modak6089dfc2007-06-22 11:58:01 +000025/* memory race conditions. It contains seven testcases that */
iyermanoje32534b2003-10-31 06:51:38 +000026/* will test race conditions between simultaneous read fault, */
27/* write fault, copy on write (COW) fault e.t.c. */
subrata_modak6089dfc2007-06-22 11:58:01 +000028/* This testcase is intended to execute on the Linux operating */
iyermanoje32534b2003-10-31 06:51:38 +000029/* system and can be easily ported to work on other operating */
30/* systems as well. */
31/* */
subrata_modakb6ecbe32008-07-11 10:22:53 +000032/* Usage: mmstress -h -n TEST NUMBER -p NPAGES -t EXECUTION TIME -v -V */
iyermanoje32534b2003-10-31 06:51:38 +000033/* -h - Help */
subrata_modak6089dfc2007-06-22 11:58:01 +000034/* -n TEST NUMBER - Execute a particular testcase */
subrata_modakb6ecbe32008-07-11 10:22:53 +000035/* -p NPAGES - Use NPAGES pages for tests */
iyermanoje32534b2003-10-31 06:51:38 +000036/* -t EXECUTION TIME - Execute test for a certain time */
37/* -v - Verbose output */
38/* -V - Version of this program */
39/* */
40/* Author: Manoj Iyer - manjo@mail.utexas.edu */
41/* */
plars865695b2001-08-27 22:15:12 +000042/******************************************************************************/
subrata_modak4bb656a2009-02-26 12:02:09 +000043
iyermanoje32534b2003-10-31 06:51:38 +000044/******************************************************************************/
45/* */
46/* Apr-13-2001 Created: Manoj Iyer, IBM Austin. */
47/* These tests are adapted from AIX vmm FVT tests. */
48/* */
49/* Oct-24-2001 Modified. */
50/* - freed buffers that were allocated. */
51/* - closed removed files. This will remove the disk full error */
52/* - use pthread_exit in case of theads instead of return. This */
53/* was really bad to use return! */
54/* - created usage function. */
55/* - pthread_join checks for thread exit status reported by */
56/* pthread_exit() */
57/* */
58/* Oct-25-2001 Modified. */
59/* - Fixed bug in usage() */
60/* - malloc'ed pointer for pthread return value. */
61/* - changed scheme. If no options are specified, all the tests */
62/* will be run once. */
63/* */
64/* Nov-02-2001 Modified - Paul Larson */
65/* - Added sched_yield to thread_fault to fix hang */
66/* - Removed thread_mmap */
67/* */
68/* Nov-09-2001 Modified - Manoj Iyer */
69/* - Removed compile warnings. */
70/* - Added missing header file. #include <stdlib.h> */
71/* */
72/* Oct-28-2003 Modified - Manoj Iyer */
subrata_modak6089dfc2007-06-22 11:58:01 +000073/* - missing parenthesis added. */
iyermanoje32534b2003-10-31 06:51:38 +000074/* - formatting changes. */
75/* - increased NUMPAGES to 9999. */
76/* */
robbiew6efe64c2004-01-30 15:43:53 +000077/* Jan-30-2003 Modified - Gary Williams */
78/* - fixed a race condition between the two threads */
subrata_modak6089dfc2007-06-22 11:58:01 +000079/* - made it so if any of the testcases fail the test will fail */
robbiew6efe64c2004-01-30 15:43:53 +000080/* - fixed so status of child in test 6 is used to determine result */
81/* - fixed the use of the remove_files function in a conditional */
82/* */
iyermanoje32534b2003-10-31 06:51:38 +000083/******************************************************************************/
Garrett Cooper4b258212010-11-03 10:17:50 -070084
Cyril Hrubis631fc312017-03-22 17:42:21 +010085#include <stdio.h>
86#include <sys/types.h>
87#include <sys/stat.h>
88#include <fcntl.h>
89#include <unistd.h>
90#include <sys/mman.h>
91#include <sys/wait.h>
92#include <sys/time.h>
93#include <pthread.h>
94#include <signal.h>
95#include <errno.h>
96#include <stdlib.h>
97#include <string.h>
98#include <sched.h>
vapier03bc52c2007-07-21 20:53:44 +000099#include <stdint.h>
Cyril Hrubis631fc312017-03-22 17:42:21 +0100100#include <getopt.h>
vapier03bc52c2007-07-21 20:53:44 +0000101
102#include "test.h"
plars865695b2001-08-27 22:15:12 +0000103
iyermanoje32534b2003-10-31 06:51:38 +0000104/* GLOBAL DEFINES */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800105#define SIGENDSIG -1 /* end of signal marker */
106#define THNUM 0 /* array element pointing to number of threads */
107#define MAPADDR 1 /* array element pointing to map address */
108#define PAGESIZ 2 /* array element pointing to page size */
109#define FLTIPE 3 /* array element pointing to fault type */
110#define READ_FAULT 0 /* instructs routine to simulate read fault */
111#define WRITE_FAULT 1 /* instructs routine to simulate write fault */
112#define COW_FAULT 2 /* instructs routine to simulate copy-on-write fault */
113#define NUMTHREAD 32 /* number of threads to spawn default to 32 */
114#define NUMPAGES 9999 /* default (random) value of number of pages */
plars865695b2001-08-27 22:15:12 +0000115#ifndef TRUE
iyermanoje32534b2003-10-31 06:51:38 +0000116#define TRUE 1
plars865695b2001-08-27 22:15:12 +0000117#endif
118#ifndef FALSE
iyermanoje32534b2003-10-31 06:51:38 +0000119#define FALSE 0
plars865695b2001-08-27 22:15:12 +0000120#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121#define FAILED (-1) /* return status for all funcs indicating failure */
122#define SUCCESS 0 /* return status for all routines indicating success */
iyermanoj15ae7bc2001-10-25 03:20:55 +0000123
Wanlong Gao354ebb42012-12-07 10:10:04 +0800124#define MAXTEST 6 /* total number of testcase in this program */
125#define BRKSZ 512*1024 /* program data space allocation value */
iyermanoj15ae7bc2001-10-25 03:20:55 +0000126
Cyril Hrubis631fc312017-03-22 17:42:21 +0100127static volatile int wait_thread; /* used to wake up sleeping threads */
128static volatile int thread_begin; /* used to coordinate threads */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129static int verbose_print = FALSE; /* print more test information */
plars865695b2001-08-27 22:15:12 +0000130
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131static int pages_num = NUMPAGES; /* number of pages to use for tests */
Cyril Hrubis631fc312017-03-22 17:42:21 +0100132static volatile int alarm_fired;
subrata_modakb6ecbe32008-07-11 10:22:53 +0000133
vapier03bc52c2007-07-21 20:53:44 +0000134char *TCID = "mmstress";
135int TST_TOTAL = 6;
plars865695b2001-08-27 22:15:12 +0000136
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137static void sig_handler(int signal)
Cyril Hrubis631fc312017-03-22 17:42:21 +0100138{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 if (signal != SIGALRM) {
140 fprintf(stderr,
141 "sig_handlder(): unexpected signal caught [%d]\n",
142 signal);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100143 exit(TBROK);
144 }
145
146 alarm_fired = 1;
plars865695b2001-08-27 22:15:12 +0000147}
148
Wanlong Gao354ebb42012-12-07 10:10:04 +0800149static void usage(char *progname)
Cyril Hrubis631fc312017-03-22 17:42:21 +0100150{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 fprintf(stderr, "usage:%s -h -n test -t time -v [-V]\n", progname);
152 fprintf(stderr, "\t-h displays all options\n");
153 fprintf(stderr, "\t-n test number, if no test number\n"
154 "\t is specified, all the tests will be run\n");
155 fprintf(stderr, "\t-p specify the number of pages to\n"
156 "\t use for allocation\n");
157 fprintf(stderr, "\t-t specify the time in hours\n");
158 fprintf(stderr, "\t-v verbose output\n");
159 fprintf(stderr, "\t-V program version\n");
160 exit(1);
iyermanoj15ae7bc2001-10-25 03:20:55 +0000161}
162
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163static void set_timer(int run_time)
Cyril Hrubis631fc312017-03-22 17:42:21 +0100164{
165 struct itimerval timer;
166
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 memset(&timer, 0, sizeof(struct itimerval));
168 timer.it_interval.tv_usec = 0;
169 timer.it_interval.tv_sec = 0;
170 timer.it_value.tv_usec = 0;
171 timer.it_value.tv_sec = (time_t) (run_time * 3600.0);
plars865695b2001-08-27 22:15:12 +0000172
Wanlong Gao354ebb42012-12-07 10:10:04 +0800173 if (setitimer(ITIMER_REAL, &timer, NULL)) {
174 perror("set_timer(): setitimer()");
175 exit(1);
176 }
plars865695b2001-08-27 22:15:12 +0000177}
178
plars865695b2001-08-27 22:15:12 +0000179/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000180/* */
181/* Function: thread_fault */
182/* */
plars865695b2001-08-27 22:15:12 +0000183/* Description: Executes as a thread function and accesses the memory pages */
iyermanoje32534b2003-10-31 06:51:38 +0000184/* depending on the fault_type to be generated. This function */
185/* can cause READ fault, WRITE fault, COW fault. */
186/* */
187/* Input: void *args - argments passed to the exec routine by */
188/* pthread_create() */
189/* */
plars865695b2001-08-27 22:15:12 +0000190/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800191static void *thread_fault(void *args)
Cyril Hrubis631fc312017-03-22 17:42:21 +0100192{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800193 long *local_args = args; /* local pointer to list of arguments */
194 /* local_args[THNUM] - the thread number */
195 /* local_args[MAPADDR] - map address */
196 /* local_args[PAGESIZ] - page size */
197 /* local_args[FLTIPE] - fault type */
198 int pgnum_ndx = 0; /* index to the number of pages */
Cyril Hrubis631fc312017-03-22 17:42:21 +0100199 char *start_addr /* start address of the page */
200 = (void *) (local_args[MAPADDR]
Wanlong Gao354ebb42012-12-07 10:10:04 +0800201 + (int)local_args[THNUM]
202 * (pages_num / NUMTHREAD)
203 * local_args[PAGESIZ]);
204 char read_from_addr = 0; /* address to which read from page is done */
205 char write_to_addr[] = { 'a' }; /* character to be writen to the page */
plars865695b2001-08-27 22:15:12 +0000206
robbiew6efe64c2004-01-30 15:43:53 +0000207 /*************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800208 /* The way it was, args could be overwritten by subsequent uses
209 * of it before this routine had a chance to use the data.
210 * This flag stops the overwrite until this routine gets to
211 * here. At this point, it is done initializing and it is
212 * safe for the parent thread to continue (which will change
213 * args).
214 */
215 thread_begin = FALSE;
robbiew6efe64c2004-01-30 15:43:53 +0000216
Wanlong Gao354ebb42012-12-07 10:10:04 +0800217 while (wait_thread)
218 sched_yield();
plars865695b2001-08-27 22:15:12 +0000219
Wanlong Gao354ebb42012-12-07 10:10:04 +0800220 for (; pgnum_ndx < (pages_num / NUMTHREAD); pgnum_ndx++) {
221 /* if the fault to be generated is READ_FAULT, read from the page */
222 /* else write a character to the page. */
223 ((int)local_args[3] == READ_FAULT) ? (read_from_addr =
224 *start_addr)
225 : (*start_addr = write_to_addr[0]);
226 start_addr += local_args[PAGESIZ];
227 if (verbose_print)
228 tst_resm(TINFO,
229 "thread_fault(): generating fault type %ld"
230 " @page address %p", local_args[3],
231 start_addr);
232 fflush(NULL);
233 }
Cyril Hrubis631fc312017-03-22 17:42:21 +0100234 pthread_exit(NULL);
plars865695b2001-08-27 22:15:12 +0000235}
236
plars865695b2001-08-27 22:15:12 +0000237/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000238/* */
239/* Function: remove_tmpfiles */
240/* */
241/* Description: remove temporary files that were created by the tests. */
242/* */
plars865695b2001-08-27 22:15:12 +0000243/******************************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800244static int remove_files(char *filename, char *addr)
Cyril Hrubis631fc312017-03-22 17:42:21 +0100245{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800246 if (addr)
247 if (munmap(addr, sysconf(_SC_PAGESIZE) * pages_num) < 0) {
248 perror("map_and_thread(): munmap()");
249 return FAILED;
250 }
251 if (strcmp(filename, "NULL") && strcmp(filename, "/dev/zero")) {
252 if (unlink(filename)) {
253 perror("map_and_thread(): ulink()");
254 return FAILED;
255 }
256 } else {
257 if (verbose_print)
258 tst_resm(TINFO, "file %s removed", filename);
Garrett Cooper2c282152010-12-16 00:55:50 -0800259
Wanlong Gao354ebb42012-12-07 10:10:04 +0800260 }
261 return SUCCESS;
plars865695b2001-08-27 22:15:12 +0000262}
263
plars865695b2001-08-27 22:15:12 +0000264/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000265/* */
266/* Function: map_and_thread */
267/* */
268/* Description: Creates mappings with the required properties, of MAP_PRIVATE */
269/* MAP_SHARED and of PROT_RED / PROT_READ|PROT_WRITE. */
270/* Create threads and execute a routine that will generate the */
271/* desired fault condition, viz, read, write and cow fault. */
272/* */
273/* Input: char *tmpfile - name of temporary file that is created */
274/* int fault_type - type of fault that is to be generated. */
275/* */
plars865695b2001-08-27 22:15:12 +0000276/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100277int map_and_thread(char *tmpfile,
278 void *(*exec_func) (void *),
279 int fault_type,
280 int num_thread)
281{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800282 int fd = 0; /* file descriptor of the file created */
283 int thrd_ndx = 0; /* index to the number of threads created */
284 int map_type = 0; /* specifies the type of the mapped object */
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500285 void *th_status; /* status of the thread when it is finished */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 long th_args[5]; /* argument list passed to thread_fault() */
287 char *empty_buf = NULL; /* empty buffer used to fill temp file */
288 long pagesize /* contains page size at runtime */
289 = sysconf(_SC_PAGESIZE);
290 static pthread_t pthread_ids[NUMTHREAD];
291 /* contains ids of the threads created */
Cyril Hrubis631fc312017-03-22 17:42:21 +0100292 void * map_addr = NULL; /* address where the file is mapped */
Garrett Cooper2c282152010-12-16 00:55:50 -0800293
Wanlong Gao354ebb42012-12-07 10:10:04 +0800294 /* Create a file with permissions 0666, and open it with RDRW perms */
295 /* if the name is not a NULL */
Garrett Cooper2c282152010-12-16 00:55:50 -0800296
Wanlong Gao354ebb42012-12-07 10:10:04 +0800297 if (strcmp(tmpfile, "NULL")) {
298 if ((fd =
299 open(tmpfile, O_RDWR | O_CREAT,
300 S_IRWXO | S_IRWXU | S_IRWXG))
301 == -1) {
302 perror("map_and_thread(): open()");
303 close(fd);
304 fflush(NULL);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100305 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800306 }
iyermanoje32534b2003-10-31 06:51:38 +0000307
Wanlong Gao354ebb42012-12-07 10:10:04 +0800308 /* Write pagesize * pages_num bytes to the file */
Cyril Hrubisd218f342014-09-23 13:14:56 +0200309 empty_buf = malloc(pagesize * pages_num);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 if (write(fd, empty_buf, pagesize * pages_num) !=
311 (pagesize * pages_num)) {
312 perror("map_and_thread(): write()");
313 free(empty_buf);
314 fflush(NULL);
315 remove_files(tmpfile, NULL);
316 close(fd);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100317 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800318 }
319 map_type = (fault_type == COW_FAULT) ? MAP_PRIVATE : MAP_SHARED;
plars865695b2001-08-27 22:15:12 +0000320
Wanlong Gao354ebb42012-12-07 10:10:04 +0800321 /* Map the file, if the required fault type is COW_FAULT map the file */
322 /* private, else map the file shared. if READ_FAULT is required to be */
323 /* generated map the file with read protection else map with read - */
324 /* write protection. */
plars865695b2001-08-27 22:15:12 +0000325
Cyril Hrubis631fc312017-03-22 17:42:21 +0100326 if ((map_addr = (void *) mmap(0, pagesize * pages_num,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800327 ((fault_type == READ_FAULT) ?
328 PROT_READ : PROT_READ |
329 PROT_WRITE), map_type, fd, 0))
330 == MAP_FAILED) {
331 perror("map_and_thread(): mmap()");
332 free(empty_buf);
333 fflush(NULL);
334 remove_files(tmpfile, NULL);
335 close(fd);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100336 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800337 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800338 if (verbose_print)
339 tst_resm(TINFO,
340 "map_and_thread(): mmap success, address = %p",
341 map_addr);
342 fflush(NULL);
343 }
344 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800345
Wanlong Gao354ebb42012-12-07 10:10:04 +0800346 /* As long as wait is set to TRUE, the thread that will be created will */
347 /* loop in its exec routine */
plars865695b2001-08-27 22:15:12 +0000348
Wanlong Gao354ebb42012-12-07 10:10:04 +0800349 wait_thread = TRUE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800350
Wanlong Gao354ebb42012-12-07 10:10:04 +0800351 /* Create a few threads, ideally number of threads equals number of CPU'S */
352 /* so that we can assume that each thread will run on a single CPU in */
353 /* of SMP machines. Currently we will create NR_CPUS number of threads. */
plars865695b2001-08-27 22:15:12 +0000354
Wanlong Gao354ebb42012-12-07 10:10:04 +0800355 th_args[1] = (long)map_addr;
356 th_args[2] = pagesize;
357 th_args[3] = fault_type;
358 do {
359 th_args[0] = thrd_ndx;
360 th_args[4] = (long)0;
Garrett Cooper2c282152010-12-16 00:55:50 -0800361
robbiew6efe64c2004-01-30 15:43:53 +0000362 /*************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800363 /* The way it was, args could be overwritten by subsequent uses
364 * of it before the called routine had a chance to fully initialize.
365 * This flag stops the overwrite until that routine gets to
366 * begin. At that point, it is done initializing and it is
367 * safe for the this thread to continue (which will change
368 * args).
369 * A basic race condition.
370 */
371 thread_begin = TRUE;
372 if (pthread_create(&pthread_ids[thrd_ndx++], NULL, exec_func,
373 (void *)&th_args)) {
374 perror("map_and_thread(): pthread_create()");
375 thread_begin = FALSE;
376 free(empty_buf);
377 fflush(NULL);
378 remove_files(tmpfile, map_addr);
379 close(fd);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100380 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800381 } else {
382 /***************************************************/
383 /* Yield until new thread is done with args.
384 */
385 while (thread_begin)
386 sched_yield();
387 }
388 } while (thrd_ndx < num_thread);
plars865695b2001-08-27 22:15:12 +0000389
Wanlong Gao354ebb42012-12-07 10:10:04 +0800390 if (verbose_print)
391 tst_resm(TINFO, "map_and_thread(): pthread_create() success");
392 wait_thread = FALSE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800393
Wanlong Gao354ebb42012-12-07 10:10:04 +0800394 /* suspend the execution of the calling thread till the execution of the */
395 /* other thread has been terminated. */
iyermanoje32534b2003-10-31 06:51:38 +0000396
Wanlong Gao354ebb42012-12-07 10:10:04 +0800397 for (thrd_ndx = 0; thrd_ndx < NUMTHREAD; thrd_ndx++) {
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500398 if (pthread_join(pthread_ids[thrd_ndx], &th_status)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800399 perror("map_and_thread(): pthread_join()");
400 free(empty_buf);
401 fflush(NULL);
402 remove_files(tmpfile, map_addr);
403 close(fd);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100404 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800405 } else {
Dave Kleikamp981d33a2013-05-06 11:47:30 -0500406 if ((long)th_status == 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800407 tst_resm(TINFO,
408 "thread [%ld] - process exited with errors",
409 (long)pthread_ids[thrd_ndx]);
410 free(empty_buf);
411 remove_files(tmpfile, map_addr);
412 close(fd);
413 exit(1);
414 }
415 }
416 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800417
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418 /* remove the temporary file that was created. - clean up */
419 /* but dont try to remove special files. */
iyermanoje32534b2003-10-31 06:51:38 +0000420
robbiew6efe64c2004-01-30 15:43:53 +0000421 /***********************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800422 /* Was if !(remove_files()) ...
423 * If that routine succeeds, it returns SUCCESS, which
424 * happens to be 0. So if the routine succeeded, the
425 * above condition would indicate failure. This change
426 * fixes that.
427 */
428 if (remove_files(tmpfile, map_addr) == FAILED) {
429 free(empty_buf);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100430 return FAILED;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800431 }
iyermanoje32534b2003-10-31 06:51:38 +0000432
Wanlong Gao354ebb42012-12-07 10:10:04 +0800433 free(empty_buf);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800434 close(fd);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100435 return SUCCESS;
plars865695b2001-08-27 22:15:12 +0000436}
437
plars865695b2001-08-27 22:15:12 +0000438/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000439/* */
440/* Test: Test case tests the race condition between simultaneous read */
441/* faults in the same address space. */
442/* */
443/* Description: map a file into memory, create threads and execute a thread */
subrata_modak6089dfc2007-06-22 11:58:01 +0000444/* function that will cause read faults by simultaneously reading*/
445/* from this memory space. */
plars865695b2001-08-27 22:15:12 +0000446/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100447static int test1(void)
plars865695b2001-08-27 22:15:12 +0000448{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800449 tst_resm(TINFO, "test1: Test case tests the race condition between "
450 "simultaneous read faults in the same address space.");
Cyril Hrubis631fc312017-03-22 17:42:21 +0100451 return map_and_thread("./tmp.file.1", thread_fault, READ_FAULT, NUMTHREAD);
plars865695b2001-08-27 22:15:12 +0000452}
453
plars865695b2001-08-27 22:15:12 +0000454/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000455/* */
456/* Test: Test case tests the race condition between simultaneous write */
457/* faults in the same address space. */
458/* */
plars865695b2001-08-27 22:15:12 +0000459/* Description: map a file into memory, create threads and execute a thread */
subrata_modak6089dfc2007-06-22 11:58:01 +0000460/* function that will cause write faults by simultaneously */
plars865695b2001-08-27 22:15:12 +0000461/* writing to this memory space. */
plars865695b2001-08-27 22:15:12 +0000462/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100463static int test2(void)
plars865695b2001-08-27 22:15:12 +0000464{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800465 tst_resm(TINFO, "test2: Test case tests the race condition between "
466 "simultaneous write faults in the same address space.");
Cyril Hrubis631fc312017-03-22 17:42:21 +0100467 return map_and_thread("./tmp.file.2", thread_fault, WRITE_FAULT, NUMTHREAD);
plars865695b2001-08-27 22:15:12 +0000468}
469
plars865695b2001-08-27 22:15:12 +0000470/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000471/* */
472/* Test: Test case tests the race condition between simultaneous COW */
473/* faults in the same address space. */
474/* */
plars865695b2001-08-27 22:15:12 +0000475/* Description: map a file into memory, create threads and execute a thread */
subrata_modak6089dfc2007-06-22 11:58:01 +0000476/* function that will cause COW faults by simultaneously */
plars865695b2001-08-27 22:15:12 +0000477/* writing to this memory space. */
iyermanoje32534b2003-10-31 06:51:38 +0000478/* */
plars865695b2001-08-27 22:15:12 +0000479/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100480static int test3(void)
plars865695b2001-08-27 22:15:12 +0000481{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800482 tst_resm(TINFO, "test3: Test case tests the race condition between "
483 "simultaneous COW faults in the same address space.");
Cyril Hrubis631fc312017-03-22 17:42:21 +0100484 return map_and_thread("./tmp.file.3", thread_fault, COW_FAULT, NUMTHREAD);
plars865695b2001-08-27 22:15:12 +0000485}
486
plars865695b2001-08-27 22:15:12 +0000487/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000488/* */
489/* Test: Test case tests the race condition between simultaneous READ */
subrata_modak6089dfc2007-06-22 11:58:01 +0000490/* faults in the same address space. File mapped is /dev/zero */
iyermanoje32534b2003-10-31 06:51:38 +0000491/* */
492/* Description: Map a file into memory, create threads and execute a thread */
subrata_modak6089dfc2007-06-22 11:58:01 +0000493/* function that will cause READ faults by simultaneously */
plars865695b2001-08-27 22:15:12 +0000494/* writing to this memory space. */
iyermanoje32534b2003-10-31 06:51:38 +0000495/* */
plars865695b2001-08-27 22:15:12 +0000496/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100497static int test4(void)
plars865695b2001-08-27 22:15:12 +0000498{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800499 tst_resm(TINFO, "test4: Test case tests the race condition between "
500 "simultaneous READ faults in the same address space. "
501 "The file mapped is /dev/zero");
Cyril Hrubis631fc312017-03-22 17:42:21 +0100502 return map_and_thread("/dev/zero", thread_fault, COW_FAULT, NUMTHREAD);
plars865695b2001-08-27 22:15:12 +0000503}
504
plars865695b2001-08-27 22:15:12 +0000505/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000506/* */
507/* Test: Test case tests the race condition between simultaneous */
508/* fork - exit faults in the same address space. */
509/* */
subrata_modak6089dfc2007-06-22 11:58:01 +0000510/* Description: Initialize large data in the parent process, fork a child and */
plars865695b2001-08-27 22:15:12 +0000511/* and the parent waits for the child to complete execution. */
iyermanoje32534b2003-10-31 06:51:38 +0000512/* */
plars865695b2001-08-27 22:15:12 +0000513/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100514static int test5(void)
plars865695b2001-08-27 22:15:12 +0000515{
Cyril Hrubis631fc312017-03-22 17:42:21 +0100516 int fork_ndx = 0;
517 pid_t pid = 0;
518 int wait_status = 0;
plars865695b2001-08-27 22:15:12 +0000519
Wanlong Gao354ebb42012-12-07 10:10:04 +0800520 tst_resm(TINFO, "test5: Test case tests the race condition between "
521 "simultaneous fork - exit faults in the same address space.");
plars865695b2001-08-27 22:15:12 +0000522
Wanlong Gao354ebb42012-12-07 10:10:04 +0800523 /* increment the program's data space by 200*1024 (BRKSZ) bytes */
iyermanoje32534b2003-10-31 06:51:38 +0000524
Cyril Hrubis631fc312017-03-22 17:42:21 +0100525 if (sbrk(BRKSZ) == (void *) - 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800526 perror("test5(): sbrk()");
527 fflush(NULL);
528 return FAILED;
529 }
subrata_modakb6ecbe32008-07-11 10:22:53 +0000530
Wanlong Gao354ebb42012-12-07 10:10:04 +0800531 /* fork NUMTHREAD number of processes, assumption is on SMP each will get */
532 /* a separate CPU if NRCPUS = NUMTHREAD. The child does nothing; exits */
533 /* immediately, parent waits for child to complete execution. */
534 do {
535 if (!(pid = fork()))
536 _exit(0);
537 else {
538 if (pid != -1)
539 wait(&wait_status);
540 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800541
Wanlong Gao354ebb42012-12-07 10:10:04 +0800542 } while (fork_ndx++ < NUMTHREAD);
Garrett Cooper2c282152010-12-16 00:55:50 -0800543
Cyril Hrubis631fc312017-03-22 17:42:21 +0100544 if (sbrk(-BRKSZ) == (void *) - 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800545 tst_resm(TINFO, "test5(): rollback sbrk failed");
546 fflush(NULL);
547 perror("test5(): sbrk()");
548 fflush(NULL);
549 return FAILED;
550 }
551 return SUCCESS;
plars865695b2001-08-27 22:15:12 +0000552}
553
plars865695b2001-08-27 22:15:12 +0000554/******************************************************************************/
iyermanoje32534b2003-10-31 06:51:38 +0000555/* */
556/* Test: Test case tests the race condition between simultaneous */
557/* fork - exec - exit faults in the same address space. */
558/* */
subrata_modak6089dfc2007-06-22 11:58:01 +0000559/* Description: Initialize large data in the parent process, fork a child and */
plars865695b2001-08-27 22:15:12 +0000560/* and the parent waits for the child to complete execution. The */
iyermanoje32534b2003-10-31 06:51:38 +0000561/* child program execs a dummy program. */
562/* */
plars865695b2001-08-27 22:15:12 +0000563/******************************************************************************/
Cyril Hrubis631fc312017-03-22 17:42:21 +0100564static int test6(void)
plars865695b2001-08-27 22:15:12 +0000565{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800566 int res = SUCCESS;
Cyril Hrubis631fc312017-03-22 17:42:21 +0100567 int fork_ndx = 0;
568 pid_t pid = 0;
569 int wait_status;
570 char *argv_init[2] = { "arg1", NULL };
plars865695b2001-08-27 22:15:12 +0000571
Wanlong Gao354ebb42012-12-07 10:10:04 +0800572 tst_resm(TINFO, "test6: Test case tests the race condition between "
573 "simultaneous fork -exec - exit faults in the same address space.");
plars865695b2001-08-27 22:15:12 +0000574
Wanlong Gao354ebb42012-12-07 10:10:04 +0800575 /* increment the program's data space by 200*1024 (BRKSZ) bytes */
Cyril Hrubis631fc312017-03-22 17:42:21 +0100576 if (sbrk(BRKSZ) == (void *) - 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800577 perror("test6(): sbrk()");
578 fflush(NULL);
579 return FAILED;
580 }
plars865695b2001-08-27 22:15:12 +0000581
Wanlong Gao354ebb42012-12-07 10:10:04 +0800582 /* fork NUMTHREAD number of processes, assumption is on SMP each will get */
583 /* a separate CPU if NRCPUS = NUMTHREAD. The child execs a dummy program */
584 /* and parent waits for child to complete execution. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800585 do {
586 if (!(pid = fork())) {
Cyril Hrubis98308f02013-12-12 13:36:03 +0100587 if (execvp("mmstress_dummy", argv_init) == -1) {
588 if (execvp("./mmstress_dummy", argv_init) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800589 perror("test6(): execvp()");
590 fflush(NULL);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800591 exit(99);
592 }
593 }
594 } else {
595 if (pid != -1)
596 wait(&wait_status);
Cyril Hrubis631fc312017-03-22 17:42:21 +0100597
Wanlong Gao354ebb42012-12-07 10:10:04 +0800598 if (WEXITSTATUS(wait_status) != 0)
599 res = FAILED;
robbiewa26240a2004-03-01 21:36:43 +0000600 }
plars865695b2001-08-27 22:15:12 +0000601
Wanlong Gao354ebb42012-12-07 10:10:04 +0800602 } while (fork_ndx++ < NUMTHREAD);
Garrett Cooper2c282152010-12-16 00:55:50 -0800603
Cyril Hrubis631fc312017-03-22 17:42:21 +0100604 if (sbrk(-BRKSZ) == (void *) - 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800605 tst_resm(TINFO, "test6(): rollback sbrk failed");
606 fflush(NULL);
607 perror("test6(): sbrk()");
608 fflush(NULL);
609 return FAILED;
610 }
Cyril Hrubis631fc312017-03-22 17:42:21 +0100611
Wanlong Gao354ebb42012-12-07 10:10:04 +0800612 return res;
plars865695b2001-08-27 22:15:12 +0000613}
614
Cyril Hrubis631fc312017-03-22 17:42:21 +0100615static int (*(test_ptr)[]) () = {test1, test2, test3, test4, test5, test6};
plars865695b2001-08-27 22:15:12 +0000616
Cyril Hrubis631fc312017-03-22 17:42:21 +0100617static void run_test(unsigned int i)
618{
619 int rc;
620
621 rc = test_ptr[i]();
622
623 if (rc == SUCCESS)
624 tst_resm(TPASS, "TEST %d Passed", i + 1);
625 else
626 tst_resm(TFAIL, "TEST %d Failed", i + 1);
627
628 if (alarm_fired)
629 tst_exit();
630}
631
632int main(int argc, char **argv)
633{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800634 static char *version_info = "mmstress V1.00 04/17/2001";
Cyril Hrubis631fc312017-03-22 17:42:21 +0100635 int ch, i;
636 int test_num = 0;
637 int test_time = 0;
638 int run_once = TRUE;
plars865695b2001-08-27 22:15:12 +0000639
Wanlong Gao354ebb42012-12-07 10:10:04 +0800640 static struct signal_info {
Cyril Hrubis631fc312017-03-22 17:42:21 +0100641 int signum;
642 char *signame;
643 } sig_info[] = {
644 {SIGHUP, "SIGHUP"},
645 {SIGINT, "SIGINT"},
646 {SIGQUIT, "SIGQUIT"},
647 {SIGABRT, "SIGABRT"},
648 {SIGBUS, "SIGBUS"},
649 {SIGSEGV, "SIGSEGV"},
650 {SIGALRM, "SIGALRM"},
651 {SIGUSR1, "SIGUSR1"},
652 {SIGUSR2, "SIGUSR2"},
653 {SIGENDSIG, "ENDSIG"}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800654 };
Garrett Cooper2c282152010-12-16 00:55:50 -0800655
Wanlong Gao354ebb42012-12-07 10:10:04 +0800656 setvbuf(stdout, NULL, _IONBF, 0);
657 setvbuf(stderr, NULL, _IONBF, 0);
subrata_modak6089dfc2007-06-22 11:58:01 +0000658
Wanlong Gao354ebb42012-12-07 10:10:04 +0800659 if (argc < 2)
660 tst_resm(TINFO, "run %s -h for all options", argv[0]);
iyermanoj5dea26e2001-10-25 15:47:38 +0000661
Wanlong Gao354ebb42012-12-07 10:10:04 +0800662 while ((ch = getopt(argc, argv, "hn:p:t:vV")) != -1) {
663 switch (ch) {
664 case 'h':
665 usage(argv[0]);
666 break;
667 case 'n':
Cyril Hrubis631fc312017-03-22 17:42:21 +0100668 test_num = atoi(optarg);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800669 break;
670 case 'p':
Cyril Hrubis631fc312017-03-22 17:42:21 +0100671 pages_num = atoi(optarg);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800672 break;
673 case 't':
Cyril Hrubis631fc312017-03-22 17:42:21 +0100674 tst_resm(TINFO,
675 "Test is scheduled to run for %d hours",
676 test_time = atoi(optarg));
677 run_once = FALSE;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800678 break;
679 case 'v':
680 verbose_print = TRUE;
681 break;
682 case 'V':
Cyril Hrubis631fc312017-03-22 17:42:21 +0100683 tst_resm(TINFO, "%s: %s", argv[0], version_info);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800684 break;
685 case '?':
Cyril Hrubis631fc312017-03-22 17:42:21 +0100686 fprintf(stderr,
687 "%s: unknown option - %c ignored\n",
688 argv[0], optopt);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800689 break;
690 default:
Cyril Hrubis631fc312017-03-22 17:42:21 +0100691 tst_brkm(TBROK, NULL, "%s: getopt() failed!!!\n",
692 argv[0]);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800693 }
694 }
plars865695b2001-08-27 22:15:12 +0000695
Wanlong Gao354ebb42012-12-07 10:10:04 +0800696 set_timer(test_time);
plars865695b2001-08-27 22:15:12 +0000697
Cyril Hrubis631fc312017-03-22 17:42:21 +0100698 for (i = 0; sig_info[i].signum != -1; i++) {
699 if (signal(sig_info[i].signum, sig_handler) == SIG_ERR) {
700 tst_brkm(TBROK | TERRNO, NULL, "signal(%s) failed",
701 sig_info[i].signame);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800702 }
703 }
plars865695b2001-08-27 22:15:12 +0000704
Cyril Hrubis631fc312017-03-22 17:42:21 +0100705 tst_tmpdir();
706
Wanlong Gao354ebb42012-12-07 10:10:04 +0800707 do {
708 if (!test_num) {
Cyril Hrubis631fc312017-03-22 17:42:21 +0100709 for (i = 0; i < MAXTEST; i++)
710 run_test(i);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800711 } else {
Cyril Hrubis631fc312017-03-22 17:42:21 +0100712 if (test_num >= MAXTEST) {
713 tst_brkm(TBROK, NULL, "Invalid test number %i",
714 test_num);
715 }
716
717 run_test(test_num);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800718 }
Cyril Hrubis631fc312017-03-22 17:42:21 +0100719 } while (!run_once);
iyermanoje32534b2003-10-31 06:51:38 +0000720
Cyril Hrubis631fc312017-03-22 17:42:21 +0100721 tst_rmdir();
722 tst_exit();
Jan Stancekdbad18f2012-03-13 11:32:24 +0100723}