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