1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker *
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) International Business Machines Corp., 2001
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker * (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13*49cdfc7eSAndroid Build Coastguard Worker * the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker *
15*49cdfc7eSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
16*49cdfc7eSAndroid Build Coastguard Worker * along with this program; if not, write to the Free Software
17*49cdfc7eSAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*49cdfc7eSAndroid Build Coastguard Worker */
19*49cdfc7eSAndroid Build Coastguard Worker
20*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
21*49cdfc7eSAndroid Build Coastguard Worker /* */
22*49cdfc7eSAndroid Build Coastguard Worker /* File: mmstress.c */
23*49cdfc7eSAndroid Build Coastguard Worker /* */
24*49cdfc7eSAndroid Build Coastguard Worker /* Description: This is a test program that performs general stress with */
25*49cdfc7eSAndroid Build Coastguard Worker /* memory race conditions. It contains seven testcases that */
26*49cdfc7eSAndroid Build Coastguard Worker /* will test race conditions between simultaneous read fault, */
27*49cdfc7eSAndroid Build Coastguard Worker /* write fault, copy on write (COW) fault e.t.c. */
28*49cdfc7eSAndroid Build Coastguard Worker /* This testcase is intended to execute on the Linux operating */
29*49cdfc7eSAndroid Build Coastguard Worker /* system and can be easily ported to work on other operating */
30*49cdfc7eSAndroid Build Coastguard Worker /* systems as well. */
31*49cdfc7eSAndroid Build Coastguard Worker /* */
32*49cdfc7eSAndroid Build Coastguard Worker /* Usage: mmstress -h -n TEST NUMBER -p NPAGES -t EXECUTION TIME -v -V */
33*49cdfc7eSAndroid Build Coastguard Worker /* -h - Help */
34*49cdfc7eSAndroid Build Coastguard Worker /* -n TEST NUMBER - Execute a particular testcase */
35*49cdfc7eSAndroid Build Coastguard Worker /* -p NPAGES - Use NPAGES pages for tests */
36*49cdfc7eSAndroid Build Coastguard Worker /* -t EXECUTION TIME - Execute test for a certain time */
37*49cdfc7eSAndroid Build Coastguard Worker /* -v - Verbose output */
38*49cdfc7eSAndroid Build Coastguard Worker /* -V - Version of this program */
39*49cdfc7eSAndroid Build Coastguard Worker /* */
40*49cdfc7eSAndroid Build Coastguard Worker /* Author: Manoj Iyer - [email protected] */
41*49cdfc7eSAndroid Build Coastguard Worker /* */
42*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
43*49cdfc7eSAndroid Build Coastguard Worker
44*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
45*49cdfc7eSAndroid Build Coastguard Worker /* */
46*49cdfc7eSAndroid Build Coastguard Worker /* Apr-13-2001 Created: Manoj Iyer, IBM Austin. */
47*49cdfc7eSAndroid Build Coastguard Worker /* These tests are adapted from AIX vmm FVT tests. */
48*49cdfc7eSAndroid Build Coastguard Worker /* */
49*49cdfc7eSAndroid Build Coastguard Worker /* Oct-24-2001 Modified. */
50*49cdfc7eSAndroid Build Coastguard Worker /* - freed buffers that were allocated. */
51*49cdfc7eSAndroid Build Coastguard Worker /* - closed removed files. This will remove the disk full error */
52*49cdfc7eSAndroid Build Coastguard Worker /* - use pthread_exit in case of theads instead of return. This */
53*49cdfc7eSAndroid Build Coastguard Worker /* was really bad to use return! */
54*49cdfc7eSAndroid Build Coastguard Worker /* - created usage function. */
55*49cdfc7eSAndroid Build Coastguard Worker /* - pthread_join checks for thread exit status reported by */
56*49cdfc7eSAndroid Build Coastguard Worker /* pthread_exit() */
57*49cdfc7eSAndroid Build Coastguard Worker /* */
58*49cdfc7eSAndroid Build Coastguard Worker /* Oct-25-2001 Modified. */
59*49cdfc7eSAndroid Build Coastguard Worker /* - Fixed bug in usage() */
60*49cdfc7eSAndroid Build Coastguard Worker /* - malloc'ed pointer for pthread return value. */
61*49cdfc7eSAndroid Build Coastguard Worker /* - changed scheme. If no options are specified, all the tests */
62*49cdfc7eSAndroid Build Coastguard Worker /* will be run once. */
63*49cdfc7eSAndroid Build Coastguard Worker /* */
64*49cdfc7eSAndroid Build Coastguard Worker /* Nov-02-2001 Modified - Paul Larson */
65*49cdfc7eSAndroid Build Coastguard Worker /* - Added sched_yield to thread_fault to fix hang */
66*49cdfc7eSAndroid Build Coastguard Worker /* - Removed thread_mmap */
67*49cdfc7eSAndroid Build Coastguard Worker /* */
68*49cdfc7eSAndroid Build Coastguard Worker /* Nov-09-2001 Modified - Manoj Iyer */
69*49cdfc7eSAndroid Build Coastguard Worker /* - Removed compile warnings. */
70*49cdfc7eSAndroid Build Coastguard Worker /* - Added missing header file. #include <stdlib.h> */
71*49cdfc7eSAndroid Build Coastguard Worker /* */
72*49cdfc7eSAndroid Build Coastguard Worker /* Oct-28-2003 Modified - Manoj Iyer */
73*49cdfc7eSAndroid Build Coastguard Worker /* - missing parenthesis added. */
74*49cdfc7eSAndroid Build Coastguard Worker /* - formatting changes. */
75*49cdfc7eSAndroid Build Coastguard Worker /* - increased NUMPAGES to 9999. */
76*49cdfc7eSAndroid Build Coastguard Worker /* */
77*49cdfc7eSAndroid Build Coastguard Worker /* Jan-30-2003 Modified - Gary Williams */
78*49cdfc7eSAndroid Build Coastguard Worker /* - fixed a race condition between the two threads */
79*49cdfc7eSAndroid Build Coastguard Worker /* - made it so if any of the testcases fail the test will fail */
80*49cdfc7eSAndroid Build Coastguard Worker /* - fixed so status of child in test 6 is used to determine result */
81*49cdfc7eSAndroid Build Coastguard Worker /* - fixed the use of the remove_files function in a conditional */
82*49cdfc7eSAndroid Build Coastguard Worker /* */
83*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
84*49cdfc7eSAndroid Build Coastguard Worker
85*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
86*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
87*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
88*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
89*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
90*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
91*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
92*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
93*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
94*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
95*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
96*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
97*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
98*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
99*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
100*49cdfc7eSAndroid Build Coastguard Worker #include <getopt.h>
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
103*49cdfc7eSAndroid Build Coastguard Worker
104*49cdfc7eSAndroid Build Coastguard Worker /* GLOBAL DEFINES */
105*49cdfc7eSAndroid Build Coastguard Worker #define SIGENDSIG -1 /* end of signal marker */
106*49cdfc7eSAndroid Build Coastguard Worker #define THNUM 0 /* array element pointing to number of threads */
107*49cdfc7eSAndroid Build Coastguard Worker #define MAPADDR 1 /* array element pointing to map address */
108*49cdfc7eSAndroid Build Coastguard Worker #define PAGESIZ 2 /* array element pointing to page size */
109*49cdfc7eSAndroid Build Coastguard Worker #define FLTIPE 3 /* array element pointing to fault type */
110*49cdfc7eSAndroid Build Coastguard Worker #define READ_FAULT 0 /* instructs routine to simulate read fault */
111*49cdfc7eSAndroid Build Coastguard Worker #define WRITE_FAULT 1 /* instructs routine to simulate write fault */
112*49cdfc7eSAndroid Build Coastguard Worker #define COW_FAULT 2 /* instructs routine to simulate copy-on-write fault */
113*49cdfc7eSAndroid Build Coastguard Worker #define NUMTHREAD 32 /* number of threads to spawn default to 32 */
114*49cdfc7eSAndroid Build Coastguard Worker #define NUMPAGES 9999 /* default (random) value of number of pages */
115*49cdfc7eSAndroid Build Coastguard Worker #ifndef TRUE
116*49cdfc7eSAndroid Build Coastguard Worker #define TRUE 1
117*49cdfc7eSAndroid Build Coastguard Worker #endif
118*49cdfc7eSAndroid Build Coastguard Worker #ifndef FALSE
119*49cdfc7eSAndroid Build Coastguard Worker #define FALSE 0
120*49cdfc7eSAndroid Build Coastguard Worker #endif
121*49cdfc7eSAndroid Build Coastguard Worker #define FAILED (-1) /* return status for all funcs indicating failure */
122*49cdfc7eSAndroid Build Coastguard Worker #define SUCCESS 0 /* return status for all routines indicating success */
123*49cdfc7eSAndroid Build Coastguard Worker
124*49cdfc7eSAndroid Build Coastguard Worker #define BRKSZ 512*1024 /* program data space allocation value */
125*49cdfc7eSAndroid Build Coastguard Worker
126*49cdfc7eSAndroid Build Coastguard Worker static volatile int wait_thread; /* used to wake up sleeping threads */
127*49cdfc7eSAndroid Build Coastguard Worker static volatile int thread_begin; /* used to coordinate threads */
128*49cdfc7eSAndroid Build Coastguard Worker static int verbose_print = FALSE; /* print more test information */
129*49cdfc7eSAndroid Build Coastguard Worker
130*49cdfc7eSAndroid Build Coastguard Worker static int pages_num = NUMPAGES; /* number of pages to use for tests */
131*49cdfc7eSAndroid Build Coastguard Worker static volatile int alarm_fired;
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "mmstress";
134*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 6;
135*49cdfc7eSAndroid Build Coastguard Worker
sig_handler(int signal)136*49cdfc7eSAndroid Build Coastguard Worker static void sig_handler(int signal)
137*49cdfc7eSAndroid Build Coastguard Worker {
138*49cdfc7eSAndroid Build Coastguard Worker if (signal != SIGALRM) {
139*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
140*49cdfc7eSAndroid Build Coastguard Worker "sig_handlder(): unexpected signal caught [%d]\n",
141*49cdfc7eSAndroid Build Coastguard Worker signal);
142*49cdfc7eSAndroid Build Coastguard Worker exit(TBROK);
143*49cdfc7eSAndroid Build Coastguard Worker }
144*49cdfc7eSAndroid Build Coastguard Worker
145*49cdfc7eSAndroid Build Coastguard Worker alarm_fired = 1;
146*49cdfc7eSAndroid Build Coastguard Worker }
147*49cdfc7eSAndroid Build Coastguard Worker
usage(char * progname)148*49cdfc7eSAndroid Build Coastguard Worker static void usage(char *progname)
149*49cdfc7eSAndroid Build Coastguard Worker {
150*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "usage:%s -h -n test -t time -v [-V]\n", progname);
151*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-h displays all options\n");
152*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-n test number, if no test number\n"
153*49cdfc7eSAndroid Build Coastguard Worker "\t is specified, all the tests will be run\n");
154*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-p specify the number of pages to\n"
155*49cdfc7eSAndroid Build Coastguard Worker "\t use for allocation\n");
156*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-t specify the time in hours\n");
157*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-v verbose output\n");
158*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\t-V program version\n");
159*49cdfc7eSAndroid Build Coastguard Worker exit(1);
160*49cdfc7eSAndroid Build Coastguard Worker }
161*49cdfc7eSAndroid Build Coastguard Worker
set_timer(int run_time)162*49cdfc7eSAndroid Build Coastguard Worker static void set_timer(int run_time)
163*49cdfc7eSAndroid Build Coastguard Worker {
164*49cdfc7eSAndroid Build Coastguard Worker struct itimerval timer;
165*49cdfc7eSAndroid Build Coastguard Worker
166*49cdfc7eSAndroid Build Coastguard Worker memset(&timer, 0, sizeof(struct itimerval));
167*49cdfc7eSAndroid Build Coastguard Worker timer.it_interval.tv_usec = 0;
168*49cdfc7eSAndroid Build Coastguard Worker timer.it_interval.tv_sec = 0;
169*49cdfc7eSAndroid Build Coastguard Worker timer.it_value.tv_usec = 0;
170*49cdfc7eSAndroid Build Coastguard Worker timer.it_value.tv_sec = (time_t) (run_time * 3600.0);
171*49cdfc7eSAndroid Build Coastguard Worker
172*49cdfc7eSAndroid Build Coastguard Worker if (setitimer(ITIMER_REAL, &timer, NULL)) {
173*49cdfc7eSAndroid Build Coastguard Worker perror("set_timer(): setitimer()");
174*49cdfc7eSAndroid Build Coastguard Worker exit(1);
175*49cdfc7eSAndroid Build Coastguard Worker }
176*49cdfc7eSAndroid Build Coastguard Worker }
177*49cdfc7eSAndroid Build Coastguard Worker
178*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
179*49cdfc7eSAndroid Build Coastguard Worker /* */
180*49cdfc7eSAndroid Build Coastguard Worker /* Function: thread_fault */
181*49cdfc7eSAndroid Build Coastguard Worker /* */
182*49cdfc7eSAndroid Build Coastguard Worker /* Description: Executes as a thread function and accesses the memory pages */
183*49cdfc7eSAndroid Build Coastguard Worker /* depending on the fault_type to be generated. This function */
184*49cdfc7eSAndroid Build Coastguard Worker /* can cause READ fault, WRITE fault, COW fault. */
185*49cdfc7eSAndroid Build Coastguard Worker /* */
186*49cdfc7eSAndroid Build Coastguard Worker /* Input: void *args - argments passed to the exec routine by */
187*49cdfc7eSAndroid Build Coastguard Worker /* pthread_create() */
188*49cdfc7eSAndroid Build Coastguard Worker /* */
189*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
thread_fault(void * args)190*49cdfc7eSAndroid Build Coastguard Worker static void *thread_fault(void *args)
191*49cdfc7eSAndroid Build Coastguard Worker {
192*49cdfc7eSAndroid Build Coastguard Worker long *local_args = args; /* local pointer to list of arguments */
193*49cdfc7eSAndroid Build Coastguard Worker /* local_args[THNUM] - the thread number */
194*49cdfc7eSAndroid Build Coastguard Worker /* local_args[MAPADDR] - map address */
195*49cdfc7eSAndroid Build Coastguard Worker /* local_args[PAGESIZ] - page size */
196*49cdfc7eSAndroid Build Coastguard Worker /* local_args[FLTIPE] - fault type */
197*49cdfc7eSAndroid Build Coastguard Worker int pgnum_ndx = 0; /* index to the number of pages */
198*49cdfc7eSAndroid Build Coastguard Worker char *start_addr /* start address of the page */
199*49cdfc7eSAndroid Build Coastguard Worker = (void *) (local_args[MAPADDR]
200*49cdfc7eSAndroid Build Coastguard Worker + (int)local_args[THNUM]
201*49cdfc7eSAndroid Build Coastguard Worker * (pages_num / NUMTHREAD)
202*49cdfc7eSAndroid Build Coastguard Worker * local_args[PAGESIZ]);
203*49cdfc7eSAndroid Build Coastguard Worker char read_from_addr = 0; /* address to which read from page is done */
204*49cdfc7eSAndroid Build Coastguard Worker char write_to_addr[] = { 'a' }; /* character to be writen to the page */
205*49cdfc7eSAndroid Build Coastguard Worker
206*49cdfc7eSAndroid Build Coastguard Worker /*************************************************************/
207*49cdfc7eSAndroid Build Coastguard Worker /* The way it was, args could be overwritten by subsequent uses
208*49cdfc7eSAndroid Build Coastguard Worker * of it before this routine had a chance to use the data.
209*49cdfc7eSAndroid Build Coastguard Worker * This flag stops the overwrite until this routine gets to
210*49cdfc7eSAndroid Build Coastguard Worker * here. At this point, it is done initializing and it is
211*49cdfc7eSAndroid Build Coastguard Worker * safe for the parent thread to continue (which will change
212*49cdfc7eSAndroid Build Coastguard Worker * args).
213*49cdfc7eSAndroid Build Coastguard Worker */
214*49cdfc7eSAndroid Build Coastguard Worker thread_begin = FALSE;
215*49cdfc7eSAndroid Build Coastguard Worker
216*49cdfc7eSAndroid Build Coastguard Worker while (wait_thread)
217*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
218*49cdfc7eSAndroid Build Coastguard Worker
219*49cdfc7eSAndroid Build Coastguard Worker for (; pgnum_ndx < (pages_num / NUMTHREAD); pgnum_ndx++) {
220*49cdfc7eSAndroid Build Coastguard Worker /* if the fault to be generated is READ_FAULT, read from the page */
221*49cdfc7eSAndroid Build Coastguard Worker /* else write a character to the page. */
222*49cdfc7eSAndroid Build Coastguard Worker ((int)local_args[3] == READ_FAULT) ? (read_from_addr =
223*49cdfc7eSAndroid Build Coastguard Worker *start_addr)
224*49cdfc7eSAndroid Build Coastguard Worker : (*start_addr = write_to_addr[0]);
225*49cdfc7eSAndroid Build Coastguard Worker start_addr += local_args[PAGESIZ];
226*49cdfc7eSAndroid Build Coastguard Worker if (verbose_print)
227*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO,
228*49cdfc7eSAndroid Build Coastguard Worker "thread_fault(): generating fault type %ld"
229*49cdfc7eSAndroid Build Coastguard Worker " @page address %p", local_args[3],
230*49cdfc7eSAndroid Build Coastguard Worker start_addr);
231*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
232*49cdfc7eSAndroid Build Coastguard Worker }
233*49cdfc7eSAndroid Build Coastguard Worker pthread_exit(NULL);
234*49cdfc7eSAndroid Build Coastguard Worker }
235*49cdfc7eSAndroid Build Coastguard Worker
236*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
237*49cdfc7eSAndroid Build Coastguard Worker /* */
238*49cdfc7eSAndroid Build Coastguard Worker /* Function: remove_tmpfiles */
239*49cdfc7eSAndroid Build Coastguard Worker /* */
240*49cdfc7eSAndroid Build Coastguard Worker /* Description: remove temporary files that were created by the tests. */
241*49cdfc7eSAndroid Build Coastguard Worker /* */
242*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
remove_files(char * filename,char * addr)243*49cdfc7eSAndroid Build Coastguard Worker static int remove_files(char *filename, char *addr)
244*49cdfc7eSAndroid Build Coastguard Worker {
245*49cdfc7eSAndroid Build Coastguard Worker if (addr)
246*49cdfc7eSAndroid Build Coastguard Worker if (munmap(addr, sysconf(_SC_PAGESIZE) * pages_num) < 0) {
247*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): munmap()");
248*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
249*49cdfc7eSAndroid Build Coastguard Worker }
250*49cdfc7eSAndroid Build Coastguard Worker if (strcmp(filename, "NULL") && strcmp(filename, "/dev/zero")) {
251*49cdfc7eSAndroid Build Coastguard Worker if (unlink(filename)) {
252*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): ulink()");
253*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
254*49cdfc7eSAndroid Build Coastguard Worker }
255*49cdfc7eSAndroid Build Coastguard Worker } else {
256*49cdfc7eSAndroid Build Coastguard Worker if (verbose_print)
257*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "file %s removed", filename);
258*49cdfc7eSAndroid Build Coastguard Worker
259*49cdfc7eSAndroid Build Coastguard Worker }
260*49cdfc7eSAndroid Build Coastguard Worker return SUCCESS;
261*49cdfc7eSAndroid Build Coastguard Worker }
262*49cdfc7eSAndroid Build Coastguard Worker
263*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
264*49cdfc7eSAndroid Build Coastguard Worker /* */
265*49cdfc7eSAndroid Build Coastguard Worker /* Function: map_and_thread */
266*49cdfc7eSAndroid Build Coastguard Worker /* */
267*49cdfc7eSAndroid Build Coastguard Worker /* Description: Creates mappings with the required properties, of MAP_PRIVATE */
268*49cdfc7eSAndroid Build Coastguard Worker /* MAP_SHARED and of PROT_RED / PROT_READ|PROT_WRITE. */
269*49cdfc7eSAndroid Build Coastguard Worker /* Create threads and execute a routine that will generate the */
270*49cdfc7eSAndroid Build Coastguard Worker /* desired fault condition, viz, read, write and cow fault. */
271*49cdfc7eSAndroid Build Coastguard Worker /* */
272*49cdfc7eSAndroid Build Coastguard Worker /* Input: char *tmpfile - name of temporary file that is created */
273*49cdfc7eSAndroid Build Coastguard Worker /* int fault_type - type of fault that is to be generated. */
274*49cdfc7eSAndroid Build Coastguard Worker /* */
275*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
map_and_thread(char * tmpfile,void * (* exec_func)(void *),int fault_type,int num_thread)276*49cdfc7eSAndroid Build Coastguard Worker int map_and_thread(char *tmpfile,
277*49cdfc7eSAndroid Build Coastguard Worker void *(*exec_func) (void *),
278*49cdfc7eSAndroid Build Coastguard Worker int fault_type,
279*49cdfc7eSAndroid Build Coastguard Worker int num_thread)
280*49cdfc7eSAndroid Build Coastguard Worker {
281*49cdfc7eSAndroid Build Coastguard Worker int fd = 0; /* file descriptor of the file created */
282*49cdfc7eSAndroid Build Coastguard Worker int thrd_ndx = 0; /* index to the number of threads created */
283*49cdfc7eSAndroid Build Coastguard Worker int map_type = 0; /* specifies the type of the mapped object */
284*49cdfc7eSAndroid Build Coastguard Worker void *th_status; /* status of the thread when it is finished */
285*49cdfc7eSAndroid Build Coastguard Worker long th_args[5]; /* argument list passed to thread_fault() */
286*49cdfc7eSAndroid Build Coastguard Worker char *empty_buf = NULL; /* empty buffer used to fill temp file */
287*49cdfc7eSAndroid Build Coastguard Worker long pagesize /* contains page size at runtime */
288*49cdfc7eSAndroid Build Coastguard Worker = sysconf(_SC_PAGESIZE);
289*49cdfc7eSAndroid Build Coastguard Worker static pthread_t pthread_ids[NUMTHREAD];
290*49cdfc7eSAndroid Build Coastguard Worker /* contains ids of the threads created */
291*49cdfc7eSAndroid Build Coastguard Worker void * map_addr = NULL; /* address where the file is mapped */
292*49cdfc7eSAndroid Build Coastguard Worker ssize_t written = 0;
293*49cdfc7eSAndroid Build Coastguard Worker ssize_t bytes;
294*49cdfc7eSAndroid Build Coastguard Worker
295*49cdfc7eSAndroid Build Coastguard Worker /* Create a file with permissions 0666, and open it with RDRW perms */
296*49cdfc7eSAndroid Build Coastguard Worker /* if the name is not a NULL */
297*49cdfc7eSAndroid Build Coastguard Worker
298*49cdfc7eSAndroid Build Coastguard Worker if (strcmp(tmpfile, "NULL")) {
299*49cdfc7eSAndroid Build Coastguard Worker if ((fd =
300*49cdfc7eSAndroid Build Coastguard Worker open(tmpfile, O_RDWR | O_CREAT,
301*49cdfc7eSAndroid Build Coastguard Worker S_IRWXO | S_IRWXU | S_IRWXG))
302*49cdfc7eSAndroid Build Coastguard Worker == -1) {
303*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): open()");
304*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
305*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
306*49cdfc7eSAndroid Build Coastguard Worker }
307*49cdfc7eSAndroid Build Coastguard Worker
308*49cdfc7eSAndroid Build Coastguard Worker /* Write pagesize * pages_num bytes to the file */
309*49cdfc7eSAndroid Build Coastguard Worker empty_buf = malloc(pagesize * pages_num);
310*49cdfc7eSAndroid Build Coastguard Worker if (!empty_buf) {
311*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): malloc()");
312*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, NULL);
313*49cdfc7eSAndroid Build Coastguard Worker close(fd);
314*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
315*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
316*49cdfc7eSAndroid Build Coastguard Worker }
317*49cdfc7eSAndroid Build Coastguard Worker
318*49cdfc7eSAndroid Build Coastguard Worker /* Writing fewer bytes than required is not an error so retry if
319*49cdfc7eSAndroid Build Coastguard Worker * fewer were written; if that happened due to some permanent
320*49cdfc7eSAndroid Build Coastguard Worker * error like ENOSPC the following retry will fail and a proper
321*49cdfc7eSAndroid Build Coastguard Worker * errno will be reported.
322*49cdfc7eSAndroid Build Coastguard Worker */
323*49cdfc7eSAndroid Build Coastguard Worker do {
324*49cdfc7eSAndroid Build Coastguard Worker bytes = write(fd, empty_buf + written,
325*49cdfc7eSAndroid Build Coastguard Worker pagesize * pages_num - written);
326*49cdfc7eSAndroid Build Coastguard Worker if (bytes < 0) {
327*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): write()");
328*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
329*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
330*49cdfc7eSAndroid Build Coastguard Worker close(fd);
331*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, NULL);
332*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
333*49cdfc7eSAndroid Build Coastguard Worker }
334*49cdfc7eSAndroid Build Coastguard Worker written += bytes;
335*49cdfc7eSAndroid Build Coastguard Worker } while (written < pagesize * pages_num);
336*49cdfc7eSAndroid Build Coastguard Worker map_type = (fault_type == COW_FAULT) ? MAP_PRIVATE : MAP_SHARED;
337*49cdfc7eSAndroid Build Coastguard Worker
338*49cdfc7eSAndroid Build Coastguard Worker /* Map the file, if the required fault type is COW_FAULT map the file */
339*49cdfc7eSAndroid Build Coastguard Worker /* private, else map the file shared. if READ_FAULT is required to be */
340*49cdfc7eSAndroid Build Coastguard Worker /* generated map the file with read protection else map with read - */
341*49cdfc7eSAndroid Build Coastguard Worker /* write protection. */
342*49cdfc7eSAndroid Build Coastguard Worker
343*49cdfc7eSAndroid Build Coastguard Worker if ((map_addr = (void *) mmap(0, pagesize * pages_num,
344*49cdfc7eSAndroid Build Coastguard Worker ((fault_type == READ_FAULT) ?
345*49cdfc7eSAndroid Build Coastguard Worker PROT_READ : PROT_READ |
346*49cdfc7eSAndroid Build Coastguard Worker PROT_WRITE), map_type, fd, 0))
347*49cdfc7eSAndroid Build Coastguard Worker == MAP_FAILED) {
348*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): mmap()");
349*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
350*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
351*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, NULL);
352*49cdfc7eSAndroid Build Coastguard Worker close(fd);
353*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
354*49cdfc7eSAndroid Build Coastguard Worker } else {
355*49cdfc7eSAndroid Build Coastguard Worker if (verbose_print)
356*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO,
357*49cdfc7eSAndroid Build Coastguard Worker "map_and_thread(): mmap success, address = %p",
358*49cdfc7eSAndroid Build Coastguard Worker map_addr);
359*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
360*49cdfc7eSAndroid Build Coastguard Worker }
361*49cdfc7eSAndroid Build Coastguard Worker }
362*49cdfc7eSAndroid Build Coastguard Worker
363*49cdfc7eSAndroid Build Coastguard Worker /* As long as wait is set to TRUE, the thread that will be created will */
364*49cdfc7eSAndroid Build Coastguard Worker /* loop in its exec routine */
365*49cdfc7eSAndroid Build Coastguard Worker
366*49cdfc7eSAndroid Build Coastguard Worker wait_thread = TRUE;
367*49cdfc7eSAndroid Build Coastguard Worker
368*49cdfc7eSAndroid Build Coastguard Worker /* Create a few threads, ideally number of threads equals number of CPU'S */
369*49cdfc7eSAndroid Build Coastguard Worker /* so that we can assume that each thread will run on a single CPU in */
370*49cdfc7eSAndroid Build Coastguard Worker /* of SMP machines. Currently we will create NR_CPUS number of threads. */
371*49cdfc7eSAndroid Build Coastguard Worker
372*49cdfc7eSAndroid Build Coastguard Worker th_args[1] = (long)map_addr;
373*49cdfc7eSAndroid Build Coastguard Worker th_args[2] = pagesize;
374*49cdfc7eSAndroid Build Coastguard Worker th_args[3] = fault_type;
375*49cdfc7eSAndroid Build Coastguard Worker do {
376*49cdfc7eSAndroid Build Coastguard Worker th_args[0] = thrd_ndx;
377*49cdfc7eSAndroid Build Coastguard Worker th_args[4] = (long)0;
378*49cdfc7eSAndroid Build Coastguard Worker
379*49cdfc7eSAndroid Build Coastguard Worker /*************************************************************/
380*49cdfc7eSAndroid Build Coastguard Worker /* The way it was, args could be overwritten by subsequent uses
381*49cdfc7eSAndroid Build Coastguard Worker * of it before the called routine had a chance to fully initialize.
382*49cdfc7eSAndroid Build Coastguard Worker * This flag stops the overwrite until that routine gets to
383*49cdfc7eSAndroid Build Coastguard Worker * begin. At that point, it is done initializing and it is
384*49cdfc7eSAndroid Build Coastguard Worker * safe for the this thread to continue (which will change
385*49cdfc7eSAndroid Build Coastguard Worker * args).
386*49cdfc7eSAndroid Build Coastguard Worker * A basic race condition.
387*49cdfc7eSAndroid Build Coastguard Worker */
388*49cdfc7eSAndroid Build Coastguard Worker thread_begin = TRUE;
389*49cdfc7eSAndroid Build Coastguard Worker if (pthread_create(&pthread_ids[thrd_ndx++], NULL, exec_func,
390*49cdfc7eSAndroid Build Coastguard Worker (void *)&th_args)) {
391*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): pthread_create()");
392*49cdfc7eSAndroid Build Coastguard Worker thread_begin = FALSE;
393*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
394*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
395*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, map_addr);
396*49cdfc7eSAndroid Build Coastguard Worker close(fd);
397*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
398*49cdfc7eSAndroid Build Coastguard Worker } else {
399*49cdfc7eSAndroid Build Coastguard Worker /***************************************************/
400*49cdfc7eSAndroid Build Coastguard Worker /* Yield until new thread is done with args.
401*49cdfc7eSAndroid Build Coastguard Worker */
402*49cdfc7eSAndroid Build Coastguard Worker while (thread_begin)
403*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
404*49cdfc7eSAndroid Build Coastguard Worker }
405*49cdfc7eSAndroid Build Coastguard Worker } while (thrd_ndx < num_thread);
406*49cdfc7eSAndroid Build Coastguard Worker
407*49cdfc7eSAndroid Build Coastguard Worker if (verbose_print)
408*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "map_and_thread(): pthread_create() success");
409*49cdfc7eSAndroid Build Coastguard Worker wait_thread = FALSE;
410*49cdfc7eSAndroid Build Coastguard Worker
411*49cdfc7eSAndroid Build Coastguard Worker /* suspend the execution of the calling thread till the execution of the */
412*49cdfc7eSAndroid Build Coastguard Worker /* other thread has been terminated. */
413*49cdfc7eSAndroid Build Coastguard Worker
414*49cdfc7eSAndroid Build Coastguard Worker for (thrd_ndx = 0; thrd_ndx < NUMTHREAD; thrd_ndx++) {
415*49cdfc7eSAndroid Build Coastguard Worker if (pthread_join(pthread_ids[thrd_ndx], &th_status)) {
416*49cdfc7eSAndroid Build Coastguard Worker perror("map_and_thread(): pthread_join()");
417*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
418*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
419*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, map_addr);
420*49cdfc7eSAndroid Build Coastguard Worker close(fd);
421*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
422*49cdfc7eSAndroid Build Coastguard Worker } else {
423*49cdfc7eSAndroid Build Coastguard Worker if ((long)th_status == 1) {
424*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO,
425*49cdfc7eSAndroid Build Coastguard Worker "thread [%ld] - process exited with errors",
426*49cdfc7eSAndroid Build Coastguard Worker (long)pthread_ids[thrd_ndx]);
427*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
428*49cdfc7eSAndroid Build Coastguard Worker remove_files(tmpfile, map_addr);
429*49cdfc7eSAndroid Build Coastguard Worker close(fd);
430*49cdfc7eSAndroid Build Coastguard Worker exit(1);
431*49cdfc7eSAndroid Build Coastguard Worker }
432*49cdfc7eSAndroid Build Coastguard Worker }
433*49cdfc7eSAndroid Build Coastguard Worker }
434*49cdfc7eSAndroid Build Coastguard Worker
435*49cdfc7eSAndroid Build Coastguard Worker /* remove the temporary file that was created. - clean up */
436*49cdfc7eSAndroid Build Coastguard Worker /* but dont try to remove special files. */
437*49cdfc7eSAndroid Build Coastguard Worker
438*49cdfc7eSAndroid Build Coastguard Worker /***********************************************/
439*49cdfc7eSAndroid Build Coastguard Worker /* Was if !(remove_files()) ...
440*49cdfc7eSAndroid Build Coastguard Worker * If that routine succeeds, it returns SUCCESS, which
441*49cdfc7eSAndroid Build Coastguard Worker * happens to be 0. So if the routine succeeded, the
442*49cdfc7eSAndroid Build Coastguard Worker * above condition would indicate failure. This change
443*49cdfc7eSAndroid Build Coastguard Worker * fixes that.
444*49cdfc7eSAndroid Build Coastguard Worker */
445*49cdfc7eSAndroid Build Coastguard Worker if (remove_files(tmpfile, map_addr) == FAILED) {
446*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
447*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
448*49cdfc7eSAndroid Build Coastguard Worker }
449*49cdfc7eSAndroid Build Coastguard Worker
450*49cdfc7eSAndroid Build Coastguard Worker free(empty_buf);
451*49cdfc7eSAndroid Build Coastguard Worker close(fd);
452*49cdfc7eSAndroid Build Coastguard Worker return SUCCESS;
453*49cdfc7eSAndroid Build Coastguard Worker }
454*49cdfc7eSAndroid Build Coastguard Worker
455*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
456*49cdfc7eSAndroid Build Coastguard Worker /* */
457*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous read */
458*49cdfc7eSAndroid Build Coastguard Worker /* faults in the same address space. */
459*49cdfc7eSAndroid Build Coastguard Worker /* */
460*49cdfc7eSAndroid Build Coastguard Worker /* Description: map a file into memory, create threads and execute a thread */
461*49cdfc7eSAndroid Build Coastguard Worker /* function that will cause read faults by simultaneously reading*/
462*49cdfc7eSAndroid Build Coastguard Worker /* from this memory space. */
463*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test1(void)464*49cdfc7eSAndroid Build Coastguard Worker static int test1(void)
465*49cdfc7eSAndroid Build Coastguard Worker {
466*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test1: Test case tests the race condition between "
467*49cdfc7eSAndroid Build Coastguard Worker "simultaneous read faults in the same address space.");
468*49cdfc7eSAndroid Build Coastguard Worker return map_and_thread("./tmp.file.1", thread_fault, READ_FAULT, NUMTHREAD);
469*49cdfc7eSAndroid Build Coastguard Worker }
470*49cdfc7eSAndroid Build Coastguard Worker
471*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
472*49cdfc7eSAndroid Build Coastguard Worker /* */
473*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous write */
474*49cdfc7eSAndroid Build Coastguard Worker /* faults in the same address space. */
475*49cdfc7eSAndroid Build Coastguard Worker /* */
476*49cdfc7eSAndroid Build Coastguard Worker /* Description: map a file into memory, create threads and execute a thread */
477*49cdfc7eSAndroid Build Coastguard Worker /* function that will cause write faults by simultaneously */
478*49cdfc7eSAndroid Build Coastguard Worker /* writing to this memory space. */
479*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test2(void)480*49cdfc7eSAndroid Build Coastguard Worker static int test2(void)
481*49cdfc7eSAndroid Build Coastguard Worker {
482*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test2: Test case tests the race condition between "
483*49cdfc7eSAndroid Build Coastguard Worker "simultaneous write faults in the same address space.");
484*49cdfc7eSAndroid Build Coastguard Worker return map_and_thread("./tmp.file.2", thread_fault, WRITE_FAULT, NUMTHREAD);
485*49cdfc7eSAndroid Build Coastguard Worker }
486*49cdfc7eSAndroid Build Coastguard Worker
487*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
488*49cdfc7eSAndroid Build Coastguard Worker /* */
489*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous COW */
490*49cdfc7eSAndroid Build Coastguard Worker /* faults in the same address space. */
491*49cdfc7eSAndroid Build Coastguard Worker /* */
492*49cdfc7eSAndroid Build Coastguard Worker /* Description: map a file into memory, create threads and execute a thread */
493*49cdfc7eSAndroid Build Coastguard Worker /* function that will cause COW faults by simultaneously */
494*49cdfc7eSAndroid Build Coastguard Worker /* writing to this memory space. */
495*49cdfc7eSAndroid Build Coastguard Worker /* */
496*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test3(void)497*49cdfc7eSAndroid Build Coastguard Worker static int test3(void)
498*49cdfc7eSAndroid Build Coastguard Worker {
499*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test3: Test case tests the race condition between "
500*49cdfc7eSAndroid Build Coastguard Worker "simultaneous COW faults in the same address space.");
501*49cdfc7eSAndroid Build Coastguard Worker return map_and_thread("./tmp.file.3", thread_fault, COW_FAULT, NUMTHREAD);
502*49cdfc7eSAndroid Build Coastguard Worker }
503*49cdfc7eSAndroid Build Coastguard Worker
504*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
505*49cdfc7eSAndroid Build Coastguard Worker /* */
506*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous READ */
507*49cdfc7eSAndroid Build Coastguard Worker /* faults in the same address space. File mapped is /dev/zero */
508*49cdfc7eSAndroid Build Coastguard Worker /* */
509*49cdfc7eSAndroid Build Coastguard Worker /* Description: Map a file into memory, create threads and execute a thread */
510*49cdfc7eSAndroid Build Coastguard Worker /* function that will cause READ faults by simultaneously */
511*49cdfc7eSAndroid Build Coastguard Worker /* writing to this memory space. */
512*49cdfc7eSAndroid Build Coastguard Worker /* */
513*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test4(void)514*49cdfc7eSAndroid Build Coastguard Worker static int test4(void)
515*49cdfc7eSAndroid Build Coastguard Worker {
516*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test4: Test case tests the race condition between "
517*49cdfc7eSAndroid Build Coastguard Worker "simultaneous READ faults in the same address space. "
518*49cdfc7eSAndroid Build Coastguard Worker "The file mapped is /dev/zero");
519*49cdfc7eSAndroid Build Coastguard Worker return map_and_thread("/dev/zero", thread_fault, COW_FAULT, NUMTHREAD);
520*49cdfc7eSAndroid Build Coastguard Worker }
521*49cdfc7eSAndroid Build Coastguard Worker
522*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
523*49cdfc7eSAndroid Build Coastguard Worker /* */
524*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous */
525*49cdfc7eSAndroid Build Coastguard Worker /* fork - exit faults in the same address space. */
526*49cdfc7eSAndroid Build Coastguard Worker /* */
527*49cdfc7eSAndroid Build Coastguard Worker /* Description: Initialize large data in the parent process, fork a child and */
528*49cdfc7eSAndroid Build Coastguard Worker /* and the parent waits for the child to complete execution. */
529*49cdfc7eSAndroid Build Coastguard Worker /* */
530*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test5(void)531*49cdfc7eSAndroid Build Coastguard Worker static int test5(void)
532*49cdfc7eSAndroid Build Coastguard Worker {
533*49cdfc7eSAndroid Build Coastguard Worker int fork_ndx = 0;
534*49cdfc7eSAndroid Build Coastguard Worker pid_t pid = 0;
535*49cdfc7eSAndroid Build Coastguard Worker int wait_status = 0;
536*49cdfc7eSAndroid Build Coastguard Worker
537*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test5: Test case tests the race condition between "
538*49cdfc7eSAndroid Build Coastguard Worker "simultaneous fork - exit faults in the same address space.");
539*49cdfc7eSAndroid Build Coastguard Worker
540*49cdfc7eSAndroid Build Coastguard Worker /* increment the program's data space by 200*1024 (BRKSZ) bytes */
541*49cdfc7eSAndroid Build Coastguard Worker
542*49cdfc7eSAndroid Build Coastguard Worker if (sbrk(BRKSZ) == (void *) - 1) {
543*49cdfc7eSAndroid Build Coastguard Worker perror("test5(): sbrk()");
544*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
545*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
546*49cdfc7eSAndroid Build Coastguard Worker }
547*49cdfc7eSAndroid Build Coastguard Worker
548*49cdfc7eSAndroid Build Coastguard Worker /* fork NUMTHREAD number of processes, assumption is on SMP each will get */
549*49cdfc7eSAndroid Build Coastguard Worker /* a separate CPU if NRCPUS = NUMTHREAD. The child does nothing; exits */
550*49cdfc7eSAndroid Build Coastguard Worker /* immediately, parent waits for child to complete execution. */
551*49cdfc7eSAndroid Build Coastguard Worker do {
552*49cdfc7eSAndroid Build Coastguard Worker if (!(pid = fork()))
553*49cdfc7eSAndroid Build Coastguard Worker _exit(0);
554*49cdfc7eSAndroid Build Coastguard Worker else {
555*49cdfc7eSAndroid Build Coastguard Worker if (pid != -1)
556*49cdfc7eSAndroid Build Coastguard Worker wait(&wait_status);
557*49cdfc7eSAndroid Build Coastguard Worker }
558*49cdfc7eSAndroid Build Coastguard Worker
559*49cdfc7eSAndroid Build Coastguard Worker } while (fork_ndx++ < NUMTHREAD);
560*49cdfc7eSAndroid Build Coastguard Worker
561*49cdfc7eSAndroid Build Coastguard Worker if (sbrk(-BRKSZ) == (void *) - 1) {
562*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test5(): rollback sbrk failed");
563*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
564*49cdfc7eSAndroid Build Coastguard Worker perror("test5(): sbrk()");
565*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
566*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
567*49cdfc7eSAndroid Build Coastguard Worker }
568*49cdfc7eSAndroid Build Coastguard Worker return SUCCESS;
569*49cdfc7eSAndroid Build Coastguard Worker }
570*49cdfc7eSAndroid Build Coastguard Worker
571*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
572*49cdfc7eSAndroid Build Coastguard Worker /* */
573*49cdfc7eSAndroid Build Coastguard Worker /* Test: Test case tests the race condition between simultaneous */
574*49cdfc7eSAndroid Build Coastguard Worker /* fork - exec - exit faults in the same address space. */
575*49cdfc7eSAndroid Build Coastguard Worker /* */
576*49cdfc7eSAndroid Build Coastguard Worker /* Description: Initialize large data in the parent process, fork a child and */
577*49cdfc7eSAndroid Build Coastguard Worker /* and the parent waits for the child to complete execution. The */
578*49cdfc7eSAndroid Build Coastguard Worker /* child program execs a dummy program. */
579*49cdfc7eSAndroid Build Coastguard Worker /* */
580*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
test6(void)581*49cdfc7eSAndroid Build Coastguard Worker static int test6(void)
582*49cdfc7eSAndroid Build Coastguard Worker {
583*49cdfc7eSAndroid Build Coastguard Worker int res = SUCCESS;
584*49cdfc7eSAndroid Build Coastguard Worker int fork_ndx = 0;
585*49cdfc7eSAndroid Build Coastguard Worker pid_t pid = 0;
586*49cdfc7eSAndroid Build Coastguard Worker int wait_status;
587*49cdfc7eSAndroid Build Coastguard Worker char *argv_init[2] = { "arg1", NULL };
588*49cdfc7eSAndroid Build Coastguard Worker
589*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test6: Test case tests the race condition between "
590*49cdfc7eSAndroid Build Coastguard Worker "simultaneous fork -exec - exit faults in the same address space.");
591*49cdfc7eSAndroid Build Coastguard Worker
592*49cdfc7eSAndroid Build Coastguard Worker /* increment the program's data space by 200*1024 (BRKSZ) bytes */
593*49cdfc7eSAndroid Build Coastguard Worker if (sbrk(BRKSZ) == (void *) - 1) {
594*49cdfc7eSAndroid Build Coastguard Worker perror("test6(): sbrk()");
595*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
596*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
597*49cdfc7eSAndroid Build Coastguard Worker }
598*49cdfc7eSAndroid Build Coastguard Worker
599*49cdfc7eSAndroid Build Coastguard Worker /* fork NUMTHREAD number of processes, assumption is on SMP each will get */
600*49cdfc7eSAndroid Build Coastguard Worker /* a separate CPU if NRCPUS = NUMTHREAD. The child execs a dummy program */
601*49cdfc7eSAndroid Build Coastguard Worker /* and parent waits for child to complete execution. */
602*49cdfc7eSAndroid Build Coastguard Worker do {
603*49cdfc7eSAndroid Build Coastguard Worker if (!(pid = fork())) {
604*49cdfc7eSAndroid Build Coastguard Worker if (execvp("mmstress_dummy", argv_init) == -1) {
605*49cdfc7eSAndroid Build Coastguard Worker if (execvp("./mmstress_dummy", argv_init) == -1) {
606*49cdfc7eSAndroid Build Coastguard Worker perror("test6(): execvp()");
607*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
608*49cdfc7eSAndroid Build Coastguard Worker exit(99);
609*49cdfc7eSAndroid Build Coastguard Worker }
610*49cdfc7eSAndroid Build Coastguard Worker }
611*49cdfc7eSAndroid Build Coastguard Worker } else {
612*49cdfc7eSAndroid Build Coastguard Worker if (pid != -1)
613*49cdfc7eSAndroid Build Coastguard Worker wait(&wait_status);
614*49cdfc7eSAndroid Build Coastguard Worker
615*49cdfc7eSAndroid Build Coastguard Worker if (WEXITSTATUS(wait_status) != 0)
616*49cdfc7eSAndroid Build Coastguard Worker res = FAILED;
617*49cdfc7eSAndroid Build Coastguard Worker }
618*49cdfc7eSAndroid Build Coastguard Worker
619*49cdfc7eSAndroid Build Coastguard Worker } while (fork_ndx++ < NUMTHREAD);
620*49cdfc7eSAndroid Build Coastguard Worker
621*49cdfc7eSAndroid Build Coastguard Worker if (sbrk(-BRKSZ) == (void *) - 1) {
622*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "test6(): rollback sbrk failed");
623*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
624*49cdfc7eSAndroid Build Coastguard Worker perror("test6(): sbrk()");
625*49cdfc7eSAndroid Build Coastguard Worker fflush(NULL);
626*49cdfc7eSAndroid Build Coastguard Worker return FAILED;
627*49cdfc7eSAndroid Build Coastguard Worker }
628*49cdfc7eSAndroid Build Coastguard Worker
629*49cdfc7eSAndroid Build Coastguard Worker return res;
630*49cdfc7eSAndroid Build Coastguard Worker }
631*49cdfc7eSAndroid Build Coastguard Worker
632*49cdfc7eSAndroid Build Coastguard Worker static int (*(test_ptr)[]) () = {test1, test2, test3, test4, test5, test6};
633*49cdfc7eSAndroid Build Coastguard Worker
run_test(unsigned int i)634*49cdfc7eSAndroid Build Coastguard Worker static void run_test(unsigned int i)
635*49cdfc7eSAndroid Build Coastguard Worker {
636*49cdfc7eSAndroid Build Coastguard Worker int rc;
637*49cdfc7eSAndroid Build Coastguard Worker
638*49cdfc7eSAndroid Build Coastguard Worker rc = test_ptr[i]();
639*49cdfc7eSAndroid Build Coastguard Worker
640*49cdfc7eSAndroid Build Coastguard Worker if (rc == SUCCESS)
641*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TPASS, "TEST %d Passed", i + 1);
642*49cdfc7eSAndroid Build Coastguard Worker else
643*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL, "TEST %d Failed", i + 1);
644*49cdfc7eSAndroid Build Coastguard Worker
645*49cdfc7eSAndroid Build Coastguard Worker if (alarm_fired)
646*49cdfc7eSAndroid Build Coastguard Worker tst_exit();
647*49cdfc7eSAndroid Build Coastguard Worker }
648*49cdfc7eSAndroid Build Coastguard Worker
main(int argc,char ** argv)649*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
650*49cdfc7eSAndroid Build Coastguard Worker {
651*49cdfc7eSAndroid Build Coastguard Worker static char *version_info = "mmstress V1.00 04/17/2001";
652*49cdfc7eSAndroid Build Coastguard Worker int ch;
653*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
654*49cdfc7eSAndroid Build Coastguard Worker int test_num = 0;
655*49cdfc7eSAndroid Build Coastguard Worker int test_time = 0;
656*49cdfc7eSAndroid Build Coastguard Worker int run_once = TRUE;
657*49cdfc7eSAndroid Build Coastguard Worker
658*49cdfc7eSAndroid Build Coastguard Worker static struct signal_info {
659*49cdfc7eSAndroid Build Coastguard Worker int signum;
660*49cdfc7eSAndroid Build Coastguard Worker char *signame;
661*49cdfc7eSAndroid Build Coastguard Worker } sig_info[] = {
662*49cdfc7eSAndroid Build Coastguard Worker {SIGHUP, "SIGHUP"},
663*49cdfc7eSAndroid Build Coastguard Worker {SIGINT, "SIGINT"},
664*49cdfc7eSAndroid Build Coastguard Worker {SIGQUIT, "SIGQUIT"},
665*49cdfc7eSAndroid Build Coastguard Worker {SIGABRT, "SIGABRT"},
666*49cdfc7eSAndroid Build Coastguard Worker {SIGBUS, "SIGBUS"},
667*49cdfc7eSAndroid Build Coastguard Worker {SIGSEGV, "SIGSEGV"},
668*49cdfc7eSAndroid Build Coastguard Worker {SIGALRM, "SIGALRM"},
669*49cdfc7eSAndroid Build Coastguard Worker {SIGUSR1, "SIGUSR1"},
670*49cdfc7eSAndroid Build Coastguard Worker {SIGUSR2, "SIGUSR2"},
671*49cdfc7eSAndroid Build Coastguard Worker {SIGENDSIG, "ENDSIG"}
672*49cdfc7eSAndroid Build Coastguard Worker };
673*49cdfc7eSAndroid Build Coastguard Worker
674*49cdfc7eSAndroid Build Coastguard Worker setvbuf(stdout, NULL, _IONBF, 0);
675*49cdfc7eSAndroid Build Coastguard Worker setvbuf(stderr, NULL, _IONBF, 0);
676*49cdfc7eSAndroid Build Coastguard Worker
677*49cdfc7eSAndroid Build Coastguard Worker if (argc < 2)
678*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "run %s -h for all options", argv[0]);
679*49cdfc7eSAndroid Build Coastguard Worker
680*49cdfc7eSAndroid Build Coastguard Worker while ((ch = getopt(argc, argv, "hn:p:t:vV")) != -1) {
681*49cdfc7eSAndroid Build Coastguard Worker switch (ch) {
682*49cdfc7eSAndroid Build Coastguard Worker case 'h':
683*49cdfc7eSAndroid Build Coastguard Worker usage(argv[0]);
684*49cdfc7eSAndroid Build Coastguard Worker break;
685*49cdfc7eSAndroid Build Coastguard Worker case 'n':
686*49cdfc7eSAndroid Build Coastguard Worker test_num = atoi(optarg);
687*49cdfc7eSAndroid Build Coastguard Worker break;
688*49cdfc7eSAndroid Build Coastguard Worker case 'p':
689*49cdfc7eSAndroid Build Coastguard Worker pages_num = atoi(optarg);
690*49cdfc7eSAndroid Build Coastguard Worker break;
691*49cdfc7eSAndroid Build Coastguard Worker case 't':
692*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO,
693*49cdfc7eSAndroid Build Coastguard Worker "Test is scheduled to run for %d hours",
694*49cdfc7eSAndroid Build Coastguard Worker test_time = atoi(optarg));
695*49cdfc7eSAndroid Build Coastguard Worker run_once = FALSE;
696*49cdfc7eSAndroid Build Coastguard Worker break;
697*49cdfc7eSAndroid Build Coastguard Worker case 'v':
698*49cdfc7eSAndroid Build Coastguard Worker verbose_print = TRUE;
699*49cdfc7eSAndroid Build Coastguard Worker break;
700*49cdfc7eSAndroid Build Coastguard Worker case 'V':
701*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "%s: %s", argv[0], version_info);
702*49cdfc7eSAndroid Build Coastguard Worker break;
703*49cdfc7eSAndroid Build Coastguard Worker case '?':
704*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
705*49cdfc7eSAndroid Build Coastguard Worker "%s: unknown option - %c ignored\n",
706*49cdfc7eSAndroid Build Coastguard Worker argv[0], optopt);
707*49cdfc7eSAndroid Build Coastguard Worker break;
708*49cdfc7eSAndroid Build Coastguard Worker default:
709*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK, NULL, "%s: getopt() failed!!!",
710*49cdfc7eSAndroid Build Coastguard Worker argv[0]);
711*49cdfc7eSAndroid Build Coastguard Worker }
712*49cdfc7eSAndroid Build Coastguard Worker }
713*49cdfc7eSAndroid Build Coastguard Worker
714*49cdfc7eSAndroid Build Coastguard Worker set_timer(test_time);
715*49cdfc7eSAndroid Build Coastguard Worker
716*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; sig_info[i].signum != -1; i++) {
717*49cdfc7eSAndroid Build Coastguard Worker if (signal(sig_info[i].signum, sig_handler) == SIG_ERR) {
718*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, NULL, "signal(%s) failed",
719*49cdfc7eSAndroid Build Coastguard Worker sig_info[i].signame);
720*49cdfc7eSAndroid Build Coastguard Worker }
721*49cdfc7eSAndroid Build Coastguard Worker }
722*49cdfc7eSAndroid Build Coastguard Worker
723*49cdfc7eSAndroid Build Coastguard Worker tst_tmpdir();
724*49cdfc7eSAndroid Build Coastguard Worker
725*49cdfc7eSAndroid Build Coastguard Worker do {
726*49cdfc7eSAndroid Build Coastguard Worker if (!test_num) {
727*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(test_ptr); i++)
728*49cdfc7eSAndroid Build Coastguard Worker run_test(i);
729*49cdfc7eSAndroid Build Coastguard Worker } else {
730*49cdfc7eSAndroid Build Coastguard Worker if (test_num > (int)ARRAY_SIZE(test_ptr)) {
731*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK, NULL, "Invalid test number %i",
732*49cdfc7eSAndroid Build Coastguard Worker test_num);
733*49cdfc7eSAndroid Build Coastguard Worker }
734*49cdfc7eSAndroid Build Coastguard Worker
735*49cdfc7eSAndroid Build Coastguard Worker run_test(test_num-1);
736*49cdfc7eSAndroid Build Coastguard Worker }
737*49cdfc7eSAndroid Build Coastguard Worker } while (!run_once);
738*49cdfc7eSAndroid Build Coastguard Worker
739*49cdfc7eSAndroid Build Coastguard Worker tst_rmdir();
740*49cdfc7eSAndroid Build Coastguard Worker tst_exit();
741*49cdfc7eSAndroid Build Coastguard Worker }
742