| /******************************************************************************/ |
| /* */ |
| /* Copyright (c) International Business Machines Corp., 2001 */ |
| /* */ |
| /* 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 */ |
| /* */ |
| /******************************************************************************/ |
| |
| /******************************************************************************/ |
| /* */ |
| /* History: July - 02 - 2001 Created by Manoj Iyer, IBM Austin TX. */ |
| /* email:manjo@austin.ibm.com */ |
| /* */ |
| /* July - 07 - 2001 Modified - changed MAP_PRIVATE to MAP_SHARED */ |
| /* read defect 187 for details. */ |
| /* */ |
| /* July - 09 - 2001 Modified - added option to MAP_PRIVATE or */ |
| /* MAP_SHARED, -p, default is to MAP_SHARED. */ |
| /* */ |
| /* July - 09 - 2001 Modified - added option '-a' MAP_ANONYMOUS. */ |
| /* Default is to map a file. */ |
| /* */ |
| /* Aug - 01 - 2001 Modified - added option 'a' to getop list. */ |
| /* */ |
| /* Oct - 25 - 2001 Modified - changed scheme. Test will be run */ |
| /* once unless -x option is used. */ |
| /* */ |
| /* Apr - 16 - 2003 Modified - replaced tempnam() use with */ |
| /* mkstemp(). -Robbie Williamson */ |
| /* email:robbiew@us.ibm.com */ |
| /* */ |
| /* May - 12 - 2003 Modified - remove the huge files when */ |
| /* we are done with the test - Paul Larson */ |
| /* email:plars@linuxtestproject.org */ |
| /* File: mmap2.c */ |
| /* */ |
| /* Description: Test the LINUX memory manager. The program is aimed at */ |
| /* stressing the memory manager by repeaded map/write/unmap of a */ |
| /* of a large gb size file. */ |
| /* */ |
| /* Create a file of the specified size in gb, map the file, */ |
| /* change the contents of the file and unmap it. This is repeated*/ |
| /* several times for the specified number of hours. */ |
| /* */ |
| /******************************************************************************/ |
| |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <sys/mman.h> |
| #include <sched.h> |
| #include <stdlib.h> |
| #include <signal.h> |
| #include <sys/time.h> |
| #include <sys/wait.h> |
| #include <signal.h> |
| #include <string.h> |
| #include <getopt.h> |
| #include "test.h" |
| |
| #define GB 1000000000 |
| #ifndef TRUE |
| #define TRUE 1 |
| #endif |
| #ifndef FALSE |
| #define FALSE 0 |
| #endif |
| |
| static int mkfile(int size) |
| { |
| int fd; |
| int index = 0; |
| char buff[4096]; |
| char template[PATH_MAX]; |
| |
| memset(buff, 'a', 4096); |
| snprintf(template, PATH_MAX, "ashfileXXXXXX"); |
| fd = mkstemp(template); |
| if (fd == -1) { |
| perror("mkfile(): mkstemp()"); |
| return -1; |
| } else { |
| unlink(template); |
| fprintf(stdout, "creating tmp file and writing 'a' to it "); |
| } |
| |
| while (index < (size * GB)) { |
| index += 4096; |
| if (write(fd, buff, 4096) == -1) { |
| perror("mkfile(): write()"); |
| return -1; |
| } |
| } |
| fprintf(stdout, "created file of size %d\n" |
| "content of the file is 'a'\n", index); |
| |
| if (fsync(fd) == -1) { |
| perror("mkfile(): fsync()"); |
| return -1; |
| } |
| return fd; |
| } |
| |
| static void sig_handler(int signal) |
| { |
| if (signal != SIGALRM) { |
| fprintf(stderr, "sig_handlder(): unexpected signal caught" |
| "[%d]\n", signal); |
| exit(-1); |
| } else |
| fprintf(stdout, "Test ended, success\n"); |
| exit(0); |
| } |
| |
| static void usage(char *progname) |
| { |
| fprintf(stderr, |
| "Usage: %s -h -s -x\n" |
| "\t -a set map_flags to MAP_ANONYMOUS\n" |
| "\t -h help, usage message.\n" |
| "\t -p set map_flag to MAP_PRIVATE.\tdefault:" |
| "MAP_SHARED\n" |
| "\t -s size of the file/memory to be mmaped.\tdefault:" |
| "1GB\n" |
| "\t -x time for which test is to be run.\tdefault:" |
| "24 Hrs\n", progname); |
| exit(-1); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int fd; |
| int fsize = 1; |
| float exec_time = 24; |
| int c; |
| int sig_ndx; |
| int map_flags = MAP_SHARED; |
| int map_anon = FALSE; |
| int run_once = TRUE; |
| char *memptr; |
| struct sigaction sigptr; |
| |
| static struct signal_info { |
| int signum; |
| char *signame; |
| } sig_info[] = { |
| { |
| SIGHUP, "SIGHUP"}, { |
| SIGINT, "SIGINT"}, { |
| SIGQUIT, "SIGQUIT"}, { |
| SIGABRT, "SIGABRT"}, { |
| SIGBUS, "SIGBUS"}, { |
| SIGSEGV, "SIGSEGV"}, { |
| SIGALRM, "SIGALRM"}, { |
| SIGUSR1, "SIGUSR1"}, { |
| SIGUSR2, "SIGUSR2"}, { |
| -1, "ENDSIG"} |
| }; |
| |
| while ((c = getopt(argc, argv, "ahps:x:")) != -1) { |
| switch (c) { |
| case 'a': |
| map_anon = TRUE; |
| break; |
| case 'h': |
| usage(argv[0]); |
| exit(-1); |
| break; |
| case 'p': |
| map_flags = MAP_PRIVATE; |
| break; |
| case 's': |
| fsize = atoi(optarg); |
| if (fsize == 0) |
| fprintf(stderr, "Using default " |
| "fsize %d GB\n", fsize = 1); |
| break; |
| case 'x': |
| exec_time = atof(optarg); |
| if (exec_time == 0) |
| fprintf(stderr, "Using default exec " |
| "time %f hrs", exec_time = (float)24); |
| run_once = FALSE; |
| break; |
| default: |
| usage(argv[0]); |
| break; |
| } |
| } |
| |
| fprintf(stdout, "MM Stress test, map/write/unmap large file\n" |
| "\tTest scheduled to run for: %f\n" |
| "\tSize of temp file in GB: %d\n", exec_time, fsize); |
| |
| alarm(exec_time * 3600.00); |
| |
| sigptr.sa_handler = sig_handler; |
| sigfillset(&sigptr.sa_mask); |
| sigptr.sa_flags = 0; |
| for (sig_ndx = 0; sig_info[sig_ndx].signum != -1; sig_ndx++) { |
| sigaddset(&sigptr.sa_mask, sig_info[sig_ndx].signum); |
| if (sigaction(sig_info[sig_ndx].signum, &sigptr, |
| NULL) == -1) { |
| perror("man(): sigaction()"); |
| fprintf(stderr, "could not set handler for SIGALRM," |
| "errno = %d\n", errno); |
| exit(-1); |
| } |
| } |
| |
| do { |
| if (!map_anon) { |
| fd = mkfile(fsize); |
| if (fd == -1) { |
| fprintf(stderr, "main(): mkfile(): Failed " |
| "to create temp file.\n"); |
| exit(-1); |
| } |
| } else { |
| fd = -1; |
| map_flags = map_flags | MAP_ANONYMOUS; |
| } |
| memptr = mmap(0, (fsize * GB), PROT_READ | PROT_WRITE, |
| map_flags, fd, 0); |
| if (memptr == MAP_FAILED) { |
| perror("main(): mmap()"); |
| exit(-1); |
| } else |
| fprintf(stdout, "file mapped at %p\n" |
| "changing file content to 'A'\n", memptr); |
| |
| memset(memptr, 'A', ((fsize * GB) / sizeof(char))); |
| |
| if (msync(memptr, ((fsize * GB) / sizeof(char)), |
| MS_SYNC | MS_INVALIDATE) == -1) { |
| perror("main(): msync()"); |
| exit(-1); |
| } |
| |
| if (munmap(memptr, (fsize * GB) / sizeof(char)) == -1) { |
| perror("main(): munmap()"); |
| exit(-1); |
| } else |
| fprintf(stdout, "unmapped file at %p\n", memptr); |
| |
| close(fd); |
| sync(); |
| } while (TRUE && !run_once); |
| exit(0); |
| } |