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