/*
*
* Copyright (c) International Business Machines Corp., 2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
/* 11/01/2002 Port to LTP robbiew@us.ibm.com */
/* page01.c */
/*======================================================================
=================== TESTPLAN SEGMENT ===================
CALLS: malloc(3)
Run with KILL flag
>KEYS: < paging behavior
>WHAT: < Does the system balk at heavy demands on it's paging facilities?
>HOW: < Create a number of process, each of which requests a large
< chunk of memory to be assigned to an array. Write to each
< element in that array, and verify that what was written/stored
< is what was expected.
>BUGS: <
======================================================================*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int bd_arg(char *);
/** LTP Port **/
#include "test.h"
void blenter(void);
void setup(void);
void anyfail(void);
void ok_exit(void);
void forkfail(void);
void terror(char *);
int instress(void);
#define FAILED 0
#define PASSED 1
int local_flag = PASSED;
int block_number;
FILE *temp;
char *TCID = "page01"; /* Test program identifier. */
int TST_TOTAL = 1; /* Total number of test cases. */
/**************/
int main(argc, argv)
int argc;
char *argv[];
{
int nchild;
int memory_size;
int error_count, i, j, pid, status;
int *number_pointer;
int *memory_pointer;
int child, count;
setup();
if (argc < 2) {
memory_size = 256 * 1024;
nchild = 50;
} else if (argc == 3) {
if (sscanf(argv[1], "%d", &memory_size) != 1)
bd_arg(argv[1]);
if (sscanf(argv[2], "%d", &nchild) != 1)
bd_arg(argv[2]);
} else {
printf("page01 [memory size (words)] [nchild]\n");
tst_resm(TCONF, "\tBad arg count.\n");
exit(1);
}
blenter();
error_count = 0;
/****************************************/
/* */
/* attempt to fork a number of */
/* identical processes */
/* */
/****************************************/
for (i = 1; i <= nchild; i++) {
if ((pid = fork()) == -1) {
terror("Fork failed (may be OK if under stress)");
if (instress())
ok_exit();
forkfail();
} else if (pid == 0) {
/********************************/
/* */
/* allocate memory of size */
/* "memory_size" */
/* */
/********************************/
memory_pointer = malloc(memory_size * sizeof(int));
if (memory_pointer == 0) {
tst_resm(TBROK,
"Cannot allocate memory - malloc failed.\n");
if (i < 2) {
tst_resm(TBROK,
"This should not happen for first two children.\n");
tst_brkm(TFAIL, NULL,
"Child %d - fail.\n",
i);
} else {
tst_resm(TCONF,
"This is ok for all but first two children.\n");
tst_brkm(TCONF, NULL,
"Child %d - ok.\n", i);
}
}
number_pointer = memory_pointer;
/********************************/
/* */
/* write to it */
/* */
/********************************/
for (j = 1; j <= memory_size; j++)
*(number_pointer++) = j;
sleep(1);
/********************************/
/* */
/* and read from it to */
/* check that what was written */
/* is still there */
/* */
/********************************/
number_pointer = memory_pointer;
for (j = 1; j <= memory_size; j++) {
if (*(number_pointer++) != j)
error_count++;
}
exit(error_count);
}
}
/****************************************/
/* */
/* wait for the child processes */
/* to teminate and report the # */
/* of deviations recognized */
/* */
/****************************************/
count = 0;
while ((child = wait(&status)) > 0) {
#ifdef DEBUG
tst_resm(TINFO, "Test {%d} exited status %d\n", child, status);
#endif
if (status)
local_flag = FAILED;
count++;
}
if (count != nchild) {
tst_resm(TWARN, "Wrong number of children waited on.\n");
tst_resm(TWARN, "Count = %d, expected = %d.\n", count, nchild);
}
anyfail();
/** NOT REACHED **/
tst_exit();
}
int bd_arg(str)
char *str;
{
tst_resm(TCONF, "\tCannot parse %s as a number.\n", str);
exit(1);
}
/** LTP Port **/
/*
* setup
*
* Do set up - here its a dummy function
*/
void setup()
{
tst_tmpdir();
temp = stderr;
}
/*
* Function: blenter()
*
* Description: Print message on entering a new block
*/
void blenter()
{
local_flag = PASSED;
return;
}
/*
*
* Function: anyfail()
*
* Description: Exit a test.
*/
void anyfail()
{
(local_flag == FAILED) ? tst_resm(TFAIL, "Test failed")
: tst_resm(TPASS, "Test passed");
tst_rmdir();
tst_exit();
}
/*
* ok_exit
*
* Calling block passed the test
*/
void ok_exit()
{
local_flag = PASSED;
return;
}
/*
* forkfail()
*
* exit on failure
*/
void forkfail()
{
tst_brkm(TBROK, tst_rmdir, "Reason: %s\n", strerror(errno));
}
/*
* Function: terror
*
* Description: prints error message this may not be because some part of the
* test case failed, for example fork() failed. We will log this
* failure as TBROK instead of TFAIL.
*/
void terror(char *message)
{
tst_resm(TBROK, "Reason: %s:%s\n", message, strerror(errno));
return;
}
/*
* instress
*
* Assume that we are always running under stress, so this function will
* return > 0 value always.
*/
int instress()
{
tst_resm(TINFO, "System resource may be too low, fork() malloc()"
" etc are likely to fail.\n");
return 1;
}