/* * test.c * * Tests kernel handling of shared private data pages. * * (C) Stephen C. Tweedie, 1998 */ #include #include #include #include #include #include #include #include int memory = 8; /* Default --- use 8 MB of heap */ int rprocesses = 8; /* Number of reader processes */ int wprocesses = 1; /* Number of writer processes */ int do_fork = 0; /* Enable random fork/die if true */ int pagesize; char *progname; char *heap; /* Allocated space for a large working set */ int *patterns; /* Record the patterns we expect in each heap page */ int nr_pages; /* How many pages are in the heap */ void setup_memory(void); /* Setup the heap and pattern arrays*/ void fork_child(int n, int write); /* Spawn a new child process */ void fork_new_child(void); /* Perform a fork/die in this child */ void *safe_malloc(size_t); /* Error-testing malloc */ void run_test(int write); /* Run the test sweep within a child */ void null_handler(int); /* Just a null signal handler */ void page_error(int); /* Report a heap pattern mismatch */ #define page_val(page) (* (int *) (heap + pagesize * (page))) void usage(char *error) { if (error) fprintf (stderr, "%s: %s\n", progname, error); fprintf (stderr, "Usage: %s [-h] [-m memsize] " "[-r readers] [-w writers]\n", progname); exit (error ? 1 : 0); } int main(int argc, char *argv[]) { int c, i; progname = argv[0]; while (c = getopt(argc, argv, "fhm:r:w:"), c != EOF) { switch (c) { case ':': usage("missing argument"); case '?': usage("unrecognised argument"); case 'f': do_fork = 1; break; case 'h': usage(0); case 'm': memory = strtoul(optarg, 0, 0); break; case 'r': rprocesses = strtoul(optarg, 0, 0); break; case 'w': wprocesses = strtoul(optarg, 0, 0); break; default: usage("unknown error"); } } fprintf (stderr, "Starting test run with %d megabyte heap.\n", memory); setup_memory(); for (i=0; i 10) { count = 0; patterns[page] = page_val(page) = random(); } } } void fork_new_child(void) { int old_pid = getpid(); int pid; pid = fork(); if (pid == -1) { perror("fork"); exit(errno); } if (pid) { /* Are we the parent? Wait for the child to print the fork banner. */ pause(); exit(0); } else { /* Are we the child? Print a banner, then signal the parent to continue. */ fprintf (stderr, "Child %05d forked into pid %05d\n", old_pid, getpid()); kill (old_pid, SIGUSR1); } } void *safe_malloc(size_t size) { void * result = malloc(size); if (!result) { fprintf (stderr, "Failed to malloc %d bytes.\n", size); exit(1); } return result; } void null_handler(int n) { } void page_error(int page) { fprintf (stderr, "Child %05d failed at page %d, address %08x: " "expected %08x, found %08x\n", getpid(), page, &page_val(page), patterns[page], page_val(page)); exit(3); }