plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 1 | /* |
| 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 Gao | 4548c6c | 2012-10-19 18:03:36 +0800 | [diff] [blame] | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 18 | */ |
| 19 | |
| 20 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 21 | /* */ |
| 22 | /* File: mmstress.c */ |
| 23 | /* */ |
| 24 | /* Description: This is a test program that performs general stress with */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 25 | /* memory race conditions. It contains seven testcases that */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 26 | /* will test race conditions between simultaneous read fault, */ |
| 27 | /* write fault, copy on write (COW) fault e.t.c. */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 28 | /* This testcase is intended to execute on the Linux operating */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 29 | /* system and can be easily ported to work on other operating */ |
| 30 | /* systems as well. */ |
| 31 | /* */ |
subrata_modak | b6ecbe3 | 2008-07-11 10:22:53 +0000 | [diff] [blame] | 32 | /* Usage: mmstress -h -n TEST NUMBER -p NPAGES -t EXECUTION TIME -v -V */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 33 | /* -h - Help */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 34 | /* -n TEST NUMBER - Execute a particular testcase */ |
subrata_modak | b6ecbe3 | 2008-07-11 10:22:53 +0000 | [diff] [blame] | 35 | /* -p NPAGES - Use NPAGES pages for tests */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 36 | /* -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 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 42 | /******************************************************************************/ |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 43 | |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 44 | /******************************************************************************/ |
| 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_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 73 | /* - missing parenthesis added. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 74 | /* - formatting changes. */ |
| 75 | /* - increased NUMPAGES to 9999. */ |
| 76 | /* */ |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 77 | /* Jan-30-2003 Modified - Gary Williams */ |
| 78 | /* - fixed a race condition between the two threads */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 79 | /* - made it so if any of the testcases fail the test will fail */ |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 80 | /* - 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 | /* */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 83 | /******************************************************************************/ |
Garrett Cooper | 4b25821 | 2010-11-03 10:17:50 -0700 | [diff] [blame] | 84 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 85 | #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> |
vapier | 03bc52c | 2007-07-21 20:53:44 +0000 | [diff] [blame] | 99 | #include <stdint.h> |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 100 | #include <getopt.h> |
vapier | 03bc52c | 2007-07-21 20:53:44 +0000 | [diff] [blame] | 101 | |
| 102 | #include "test.h" |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 103 | |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 104 | /* GLOBAL DEFINES */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 105 | #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 */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 115 | #ifndef TRUE |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 116 | #define TRUE 1 |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 117 | #endif |
| 118 | #ifndef FALSE |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 119 | #define FALSE 0 |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 120 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 121 | #define FAILED (-1) /* return status for all funcs indicating failure */ |
| 122 | #define SUCCESS 0 /* return status for all routines indicating success */ |
iyermanoj | 15ae7bc | 2001-10-25 03:20:55 +0000 | [diff] [blame] | 123 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 124 | #define MAXTEST 6 /* total number of testcase in this program */ |
| 125 | #define BRKSZ 512*1024 /* program data space allocation value */ |
iyermanoj | 15ae7bc | 2001-10-25 03:20:55 +0000 | [diff] [blame] | 126 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 127 | static volatile int wait_thread; /* used to wake up sleeping threads */ |
| 128 | static volatile int thread_begin; /* used to coordinate threads */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 129 | static int verbose_print = FALSE; /* print more test information */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 130 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 131 | static int pages_num = NUMPAGES; /* number of pages to use for tests */ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 132 | static volatile int alarm_fired; |
subrata_modak | b6ecbe3 | 2008-07-11 10:22:53 +0000 | [diff] [blame] | 133 | |
vapier | 03bc52c | 2007-07-21 20:53:44 +0000 | [diff] [blame] | 134 | char *TCID = "mmstress"; |
| 135 | int TST_TOTAL = 6; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 136 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 137 | static void sig_handler(int signal) |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 138 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 139 | if (signal != SIGALRM) { |
| 140 | fprintf(stderr, |
| 141 | "sig_handlder(): unexpected signal caught [%d]\n", |
| 142 | signal); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 143 | exit(TBROK); |
| 144 | } |
| 145 | |
| 146 | alarm_fired = 1; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 147 | } |
| 148 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 149 | static void usage(char *progname) |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 150 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 151 | 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); |
iyermanoj | 15ae7bc | 2001-10-25 03:20:55 +0000 | [diff] [blame] | 161 | } |
| 162 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 163 | static void set_timer(int run_time) |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 164 | { |
| 165 | struct itimerval timer; |
| 166 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 167 | 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); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 172 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 173 | if (setitimer(ITIMER_REAL, &timer, NULL)) { |
| 174 | perror("set_timer(): setitimer()"); |
| 175 | exit(1); |
| 176 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 177 | } |
| 178 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 179 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 180 | /* */ |
| 181 | /* Function: thread_fault */ |
| 182 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 183 | /* Description: Executes as a thread function and accesses the memory pages */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 184 | /* 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 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 190 | /******************************************************************************/ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 191 | static void *thread_fault(void *args) |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 192 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 193 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 199 | char *start_addr /* start address of the page */ |
| 200 | = (void *) (local_args[MAPADDR] |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 201 | + (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 */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 206 | |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 207 | /*************************************************************/ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 208 | /* 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; |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 216 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 217 | while (wait_thread) |
| 218 | sched_yield(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 219 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 220 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 234 | pthread_exit(NULL); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 235 | } |
| 236 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 237 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 238 | /* */ |
| 239 | /* Function: remove_tmpfiles */ |
| 240 | /* */ |
| 241 | /* Description: remove temporary files that were created by the tests. */ |
| 242 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 243 | /******************************************************************************/ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 244 | static int remove_files(char *filename, char *addr) |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 245 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 246 | 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 Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 259 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 260 | } |
| 261 | return SUCCESS; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 262 | } |
| 263 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 264 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 265 | /* */ |
| 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 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 276 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 277 | int map_and_thread(char *tmpfile, |
| 278 | void *(*exec_func) (void *), |
| 279 | int fault_type, |
| 280 | int num_thread) |
| 281 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 282 | 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 Kleikamp | 981d33a | 2013-05-06 11:47:30 -0500 | [diff] [blame] | 285 | void *th_status; /* status of the thread when it is finished */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 286 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 292 | void * map_addr = NULL; /* address where the file is mapped */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 293 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 294 | /* Create a file with permissions 0666, and open it with RDRW perms */ |
| 295 | /* if the name is not a NULL */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 296 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 297 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 305 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 306 | } |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 307 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 308 | /* Write pagesize * pages_num bytes to the file */ |
Cyril Hrubis | d218f34 | 2014-09-23 13:14:56 +0200 | [diff] [blame] | 309 | empty_buf = malloc(pagesize * pages_num); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 310 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 317 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 318 | } |
| 319 | map_type = (fault_type == COW_FAULT) ? MAP_PRIVATE : MAP_SHARED; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 320 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 321 | /* 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. */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 325 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 326 | if ((map_addr = (void *) mmap(0, pagesize * pages_num, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 327 | ((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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 336 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 337 | } else { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 338 | if (verbose_print) |
| 339 | tst_resm(TINFO, |
| 340 | "map_and_thread(): mmap success, address = %p", |
| 341 | map_addr); |
| 342 | fflush(NULL); |
| 343 | } |
| 344 | } |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 345 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 346 | /* As long as wait is set to TRUE, the thread that will be created will */ |
| 347 | /* loop in its exec routine */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 348 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 349 | wait_thread = TRUE; |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 350 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 351 | /* 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. */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 354 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 355 | 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 Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 361 | |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 362 | /*************************************************************/ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 363 | /* 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 380 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 381 | } 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); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 389 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 390 | if (verbose_print) |
| 391 | tst_resm(TINFO, "map_and_thread(): pthread_create() success"); |
| 392 | wait_thread = FALSE; |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 393 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 394 | /* suspend the execution of the calling thread till the execution of the */ |
| 395 | /* other thread has been terminated. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 396 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 397 | for (thrd_ndx = 0; thrd_ndx < NUMTHREAD; thrd_ndx++) { |
Dave Kleikamp | 981d33a | 2013-05-06 11:47:30 -0500 | [diff] [blame] | 398 | if (pthread_join(pthread_ids[thrd_ndx], &th_status)) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 399 | perror("map_and_thread(): pthread_join()"); |
| 400 | free(empty_buf); |
| 401 | fflush(NULL); |
| 402 | remove_files(tmpfile, map_addr); |
| 403 | close(fd); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 404 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 405 | } else { |
Dave Kleikamp | 981d33a | 2013-05-06 11:47:30 -0500 | [diff] [blame] | 406 | if ((long)th_status == 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 407 | 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 Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 417 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 418 | /* remove the temporary file that was created. - clean up */ |
| 419 | /* but dont try to remove special files. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 420 | |
robbiew | 6efe64c | 2004-01-30 15:43:53 +0000 | [diff] [blame] | 421 | /***********************************************/ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 422 | /* 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 430 | return FAILED; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 431 | } |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 432 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 433 | free(empty_buf); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 434 | close(fd); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 435 | return SUCCESS; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 436 | } |
| 437 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 438 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 439 | /* */ |
| 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_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 444 | /* function that will cause read faults by simultaneously reading*/ |
| 445 | /* from this memory space. */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 446 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 447 | static int test1(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 448 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 449 | tst_resm(TINFO, "test1: Test case tests the race condition between " |
| 450 | "simultaneous read faults in the same address space."); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 451 | return map_and_thread("./tmp.file.1", thread_fault, READ_FAULT, NUMTHREAD); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 452 | } |
| 453 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 454 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 455 | /* */ |
| 456 | /* Test: Test case tests the race condition between simultaneous write */ |
| 457 | /* faults in the same address space. */ |
| 458 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 459 | /* Description: map a file into memory, create threads and execute a thread */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 460 | /* function that will cause write faults by simultaneously */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 461 | /* writing to this memory space. */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 462 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 463 | static int test2(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 464 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 465 | tst_resm(TINFO, "test2: Test case tests the race condition between " |
| 466 | "simultaneous write faults in the same address space."); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 467 | return map_and_thread("./tmp.file.2", thread_fault, WRITE_FAULT, NUMTHREAD); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 468 | } |
| 469 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 470 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 471 | /* */ |
| 472 | /* Test: Test case tests the race condition between simultaneous COW */ |
| 473 | /* faults in the same address space. */ |
| 474 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 475 | /* Description: map a file into memory, create threads and execute a thread */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 476 | /* function that will cause COW faults by simultaneously */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 477 | /* writing to this memory space. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 478 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 479 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 480 | static int test3(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 481 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 482 | tst_resm(TINFO, "test3: Test case tests the race condition between " |
| 483 | "simultaneous COW faults in the same address space."); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 484 | return map_and_thread("./tmp.file.3", thread_fault, COW_FAULT, NUMTHREAD); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 485 | } |
| 486 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 487 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 488 | /* */ |
| 489 | /* Test: Test case tests the race condition between simultaneous READ */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 490 | /* faults in the same address space. File mapped is /dev/zero */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 491 | /* */ |
| 492 | /* Description: Map a file into memory, create threads and execute a thread */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 493 | /* function that will cause READ faults by simultaneously */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 494 | /* writing to this memory space. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 495 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 496 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 497 | static int test4(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 498 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 499 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 502 | return map_and_thread("/dev/zero", thread_fault, COW_FAULT, NUMTHREAD); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 503 | } |
| 504 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 505 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 506 | /* */ |
| 507 | /* Test: Test case tests the race condition between simultaneous */ |
| 508 | /* fork - exit faults in the same address space. */ |
| 509 | /* */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 510 | /* Description: Initialize large data in the parent process, fork a child and */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 511 | /* and the parent waits for the child to complete execution. */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 512 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 513 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 514 | static int test5(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 515 | { |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 516 | int fork_ndx = 0; |
| 517 | pid_t pid = 0; |
| 518 | int wait_status = 0; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 519 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 520 | tst_resm(TINFO, "test5: Test case tests the race condition between " |
| 521 | "simultaneous fork - exit faults in the same address space."); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 522 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 523 | /* increment the program's data space by 200*1024 (BRKSZ) bytes */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 524 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 525 | if (sbrk(BRKSZ) == (void *) - 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 526 | perror("test5(): sbrk()"); |
| 527 | fflush(NULL); |
| 528 | return FAILED; |
| 529 | } |
subrata_modak | b6ecbe3 | 2008-07-11 10:22:53 +0000 | [diff] [blame] | 530 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 531 | /* 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 Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 541 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 542 | } while (fork_ndx++ < NUMTHREAD); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 543 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 544 | if (sbrk(-BRKSZ) == (void *) - 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 545 | tst_resm(TINFO, "test5(): rollback sbrk failed"); |
| 546 | fflush(NULL); |
| 547 | perror("test5(): sbrk()"); |
| 548 | fflush(NULL); |
| 549 | return FAILED; |
| 550 | } |
| 551 | return SUCCESS; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 552 | } |
| 553 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 554 | /******************************************************************************/ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 555 | /* */ |
| 556 | /* Test: Test case tests the race condition between simultaneous */ |
| 557 | /* fork - exec - exit faults in the same address space. */ |
| 558 | /* */ |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 559 | /* Description: Initialize large data in the parent process, fork a child and */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 560 | /* and the parent waits for the child to complete execution. The */ |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 561 | /* child program execs a dummy program. */ |
| 562 | /* */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 563 | /******************************************************************************/ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 564 | static int test6(void) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 565 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 566 | int res = SUCCESS; |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 567 | int fork_ndx = 0; |
| 568 | pid_t pid = 0; |
| 569 | int wait_status; |
| 570 | char *argv_init[2] = { "arg1", NULL }; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 571 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 572 | tst_resm(TINFO, "test6: Test case tests the race condition between " |
| 573 | "simultaneous fork -exec - exit faults in the same address space."); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 574 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 575 | /* increment the program's data space by 200*1024 (BRKSZ) bytes */ |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 576 | if (sbrk(BRKSZ) == (void *) - 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 577 | perror("test6(): sbrk()"); |
| 578 | fflush(NULL); |
| 579 | return FAILED; |
| 580 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 581 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 582 | /* 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 Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 585 | do { |
| 586 | if (!(pid = fork())) { |
Cyril Hrubis | 98308f0 | 2013-12-12 13:36:03 +0100 | [diff] [blame] | 587 | if (execvp("mmstress_dummy", argv_init) == -1) { |
| 588 | if (execvp("./mmstress_dummy", argv_init) == -1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 589 | perror("test6(): execvp()"); |
| 590 | fflush(NULL); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 591 | exit(99); |
| 592 | } |
| 593 | } |
| 594 | } else { |
| 595 | if (pid != -1) |
| 596 | wait(&wait_status); |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 597 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 598 | if (WEXITSTATUS(wait_status) != 0) |
| 599 | res = FAILED; |
robbiew | a26240a | 2004-03-01 21:36:43 +0000 | [diff] [blame] | 600 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 601 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 602 | } while (fork_ndx++ < NUMTHREAD); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 603 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 604 | if (sbrk(-BRKSZ) == (void *) - 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 605 | tst_resm(TINFO, "test6(): rollback sbrk failed"); |
| 606 | fflush(NULL); |
| 607 | perror("test6(): sbrk()"); |
| 608 | fflush(NULL); |
| 609 | return FAILED; |
| 610 | } |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 611 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 612 | return res; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 613 | } |
| 614 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 615 | static int (*(test_ptr)[]) () = {test1, test2, test3, test4, test5, test6}; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 616 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 617 | static 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 | |
| 632 | int main(int argc, char **argv) |
| 633 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 634 | static char *version_info = "mmstress V1.00 04/17/2001"; |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 635 | int ch, i; |
| 636 | int test_num = 0; |
| 637 | int test_time = 0; |
| 638 | int run_once = TRUE; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 639 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 640 | static struct signal_info { |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 641 | 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 Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 654 | }; |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 655 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 656 | setvbuf(stdout, NULL, _IONBF, 0); |
| 657 | setvbuf(stderr, NULL, _IONBF, 0); |
subrata_modak | 6089dfc | 2007-06-22 11:58:01 +0000 | [diff] [blame] | 658 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 659 | if (argc < 2) |
| 660 | tst_resm(TINFO, "run %s -h for all options", argv[0]); |
iyermanoj | 5dea26e | 2001-10-25 15:47:38 +0000 | [diff] [blame] | 661 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 662 | 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 Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 668 | test_num = atoi(optarg); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 669 | break; |
| 670 | case 'p': |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 671 | pages_num = atoi(optarg); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 672 | break; |
| 673 | case 't': |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 674 | tst_resm(TINFO, |
| 675 | "Test is scheduled to run for %d hours", |
| 676 | test_time = atoi(optarg)); |
| 677 | run_once = FALSE; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 678 | break; |
| 679 | case 'v': |
| 680 | verbose_print = TRUE; |
| 681 | break; |
| 682 | case 'V': |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 683 | tst_resm(TINFO, "%s: %s", argv[0], version_info); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 684 | break; |
| 685 | case '?': |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 686 | fprintf(stderr, |
| 687 | "%s: unknown option - %c ignored\n", |
| 688 | argv[0], optopt); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 689 | break; |
| 690 | default: |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 691 | tst_brkm(TBROK, NULL, "%s: getopt() failed!!!\n", |
| 692 | argv[0]); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 693 | } |
| 694 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 695 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 696 | set_timer(test_time); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 697 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 698 | 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 Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 702 | } |
| 703 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 704 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 705 | tst_tmpdir(); |
| 706 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 707 | do { |
| 708 | if (!test_num) { |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 709 | for (i = 0; i < MAXTEST; i++) |
| 710 | run_test(i); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 711 | } else { |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 712 | if (test_num >= MAXTEST) { |
| 713 | tst_brkm(TBROK, NULL, "Invalid test number %i", |
| 714 | test_num); |
| 715 | } |
| 716 | |
| 717 | run_test(test_num); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 718 | } |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 719 | } while (!run_once); |
iyermanoj | e32534b | 2003-10-31 06:51:38 +0000 | [diff] [blame] | 720 | |
Cyril Hrubis | 631fc31 | 2017-03-22 17:42:21 +0100 | [diff] [blame] | 721 | tst_rmdir(); |
| 722 | tst_exit(); |
Jan Stancek | dbad18f | 2012-03-13 11:32:24 +0100 | [diff] [blame] | 723 | } |