diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2001-04-19 09:16:40 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2001-04-19 09:16:40 +0000 |
commit | e8cec9646ed21bffa7edfb5709ed7b0327884036 (patch) | |
tree | 9ab5a81c5ae0fb43f80e9f890953d5eb5c6768d6 | |
parent | b78d6f6e7b8e38f4f3be6f9ff8e88ce535765256 (diff) | |
download | newlib-e8cec9646ed21bffa7edfb5709ed7b0327884036.zip newlib-e8cec9646ed21bffa7edfb5709ed7b0327884036.tar.gz newlib-e8cec9646ed21bffa7edfb5709ed7b0327884036.tar.bz2 |
* winsup.api/mmaptest02.c: New test.
* winsup.api/mmaptest03.c: Ditto.
* winsup.api/mmaptest04.c: Ditto.
-rw-r--r-- | winsup/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | winsup/testsuite/winsup.api/mmaptest02.c | 189 | ||||
-rw-r--r-- | winsup/testsuite/winsup.api/mmaptest03.c | 127 | ||||
-rw-r--r-- | winsup/testsuite/winsup.api/mmaptest04.c | 96 |
4 files changed, 418 insertions, 0 deletions
diff --git a/winsup/testsuite/ChangeLog b/winsup/testsuite/ChangeLog index 0aa4f83..0e1b95c 100644 --- a/winsup/testsuite/ChangeLog +++ b/winsup/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-04-19 Corinna Vinschen <corinna@vinschen.de> + + * winsup.api/mmaptest02.c: New test. + * winsup.api/mmaptest03.c: Ditto. + * winsup.api/mmaptest04.c: Ditto. + 2001-04-03 Corinna Vinschen <corinna@vinschen.de> * winsup.api/mmaptest01.c: New test. diff --git a/winsup/testsuite/winsup.api/mmaptest02.c b/winsup/testsuite/winsup.api/mmaptest02.c new file mode 100644 index 0000000..3e7b929 --- /dev/null +++ b/winsup/testsuite/winsup.api/mmaptest02.c @@ -0,0 +1,189 @@ +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <setjmp.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +sigset_t unblock_sigsegv; +jmp_buf r; +size_t pg; + +int fd; + +/* Checks behaviour of anonymous mmap. + + test_1: If we map a 2-page region and unmap its second page, the first page + must remain. + + test_2: If we map a 2-page region and unmap its first page, the second + page must remain. + + test_3: If we map two consecutive 1-page regions and unmap them both with + one munmap, both must go away. +*/ + +void +perror_exit (char *str, int code) +{ + perror (str); + exit (code); +} + +void +anonmap_init () +{ + sigemptyset (&unblock_sigsegv); + sigaddset (&unblock_sigsegv, SIGSEGV); + pg = getpagesize (); + fd = open ("/dev/zero", O_RDWR); +} + +char * +anonmap (size_t size) +{ + return (char *) mmap (0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); +} + +void +anonfree (char *loc, size_t size) +{ + munmap (loc, size); +} + +void +sigsegv (int unused) +{ + sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0); + longjmp (r, 1); +} + +int +compare_pointers (const void *a, const void *b) +{ + const char *x = *(const char *const *)a; + const char *y = *(const char *const *)b; + + if (x > y) + return 1; + if (x < y) + return -1; + return 0; +} + +void +test_1 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 1 mmap", 1); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 1 fault", 2); + + x[0] = 1; + x[pg] = 1; + + anonfree (x + pg, pg); + x[0] = 2; + + if (setjmp (r) == 0) + { + x[pg] = 1; + perror_exit ("test 1 no fault", 3); + } +} + +void +test_2 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 2 mmap", 4); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 2 fault", 5); + + x[0] = 1; + x[pg] = 1; + + anonfree (x, pg); + x[pg] = 2; + + if (setjmp (r) == 0) + { + x[0] = 1; + perror_exit ("test 2 no fault", 6); + } +} + +void +test_3 () +{ + char *x[10]; + char *y; + int i; + + /* There's no way to guarantee we get consecutive pages from the OS. The + approach taken here is to allocate ten of them, sort the list, and + look for consecutive pages. */ + for (i = 0; i < 10; i++) + { + x[i] = anonmap (pg); + if (x[i] == (char *)MAP_FAILED) + perror_exit ("test 3 mmap 1", 7); + } + qsort (x, 10, sizeof (char *), compare_pointers); + + y = 0; + for (i = 0; i < 9; i++) + if (x[i] + pg == x[i+1]) + { + y = x[i]; + break; + } + if (y == 0) + { + fputs ("test 3: couldn't get two consecutive pages, giving up\n", stderr); + exit (65); + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 3 fault", 8); + + y[0] = 1; + y[pg] = 1; + + anonfree (y, pg * 2); + + if (setjmp (r) == 0) + { + y[0] = 1; + perror_exit ("test 3 no fault 1", 9); + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r) == 0) + { + y[pg] = 1; + perror_exit ("test 3 no fault 2", 10); + } +} + +int +main () +{ + anonmap_init(); + + test_1(); + test_2(); + test_3(); + + exit(0); +} diff --git a/winsup/testsuite/winsup.api/mmaptest03.c b/winsup/testsuite/winsup.api/mmaptest03.c new file mode 100644 index 0000000..6cff971 --- /dev/null +++ b/winsup/testsuite/winsup.api/mmaptest03.c @@ -0,0 +1,127 @@ +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <setjmp.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/wait.h> +#include <errno.h> + +/* - Checks if mapping of already closed file survives fork() + - Checks if mapping the same region of the same file twice + is done correctly. +*/ + +sigset_t unblock_sigsegv; +jmp_buf r; + +/* filler for file */ +char const line[] = "y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1 y1"; + +void +perror_exit (char *str) +{ + perror (str); + exit (1); +} + +void +sigsegv (int unused) +{ + sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0); + longjmp (r, 1); +} + +int +main(int argc, char **argv) +{ + int i, fd, status; + struct stat statbuf; + char c, *buf1, *buf2; + pid_t pid; + + /* Create data file */ + if ((fd = open("y.txt", O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) + perror_exit ("Can't create data file"); + write (fd, line, sizeof(line) - 1); + close (fd); + + /* Open data file */ + if ((fd = open("y.txt", O_RDONLY)) == -1) + perror_exit ("Can't open data file"); + + if (fstat(fd, &statbuf) < 0) + perror_exit ("fstat failed"); + + if (!statbuf.st_size) + perror_exit ("filesize is 0"); + + if ((buf1 = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) + == MAP_FAILED) + perror_exit ("mmap 1 failed"); + + close(fd); + + /* Open data file a second time */ + if ((fd = open("y.txt", O_RDONLY)) == -1) + perror_exit ("Can't open data file in second run"); + + if ((buf2 = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) + == MAP_FAILED) + perror_exit ("mmap 2 failed"); + + close(fd); + + sigemptyset (&unblock_sigsegv); + sigaddset (&unblock_sigsegv, SIGSEGV); + signal (SIGSEGV, sigsegv); + + if (setjmp (r)) + perror_exit ("SEGV in fork"); + + pid = fork(); + + if (pid == -1) + perror_exit ("fork failed"); + + if (setjmp (r)) + perror_exit (pid ? "SEGV in parent" : "SEGV in child"); + + c = buf1[0]; + c = buf2[0]; + + if (setjmp (r)) + perror_exit (pid ? "SEGV in parent's munmap" : "SEGV in child's munmap"); + + if (munmap(buf1, statbuf.st_size)) + perror_exit (pid ? "munmap failed in parent" : "munmap failed in child"); + + if (setjmp (r) == 0) + { + c = buf1[0]; + perror_exit (pid ? "no SEGV in parent after munmap" : "no SEGV in child after munmap"); + } + + if (setjmp (r)) + perror_exit (pid ? "SEGV in parent after munmap" : "SEGV in child after munmap"); + + c = buf2[0]; + + if (setjmp (r)) + perror_exit (pid ? "SEGV in parent's munmap" : "SEGV in child's munmap"); + + if (munmap(buf2, statbuf.st_size)) + perror_exit (pid ? "munmap failed in parent" : "munmap failed in child"); + + if (pid) + { + waitpid (pid, &status, 0); + unlink ("y.txt"); + if (!WIFEXITED (status) || WEXITSTATUS (status)) + return 1; + } + + return 0; +} diff --git a/winsup/testsuite/winsup.api/mmaptest04.c b/winsup/testsuite/winsup.api/mmaptest04.c new file mode 100644 index 0000000..e8cc0a6 --- /dev/null +++ b/winsup/testsuite/winsup.api/mmaptest04.c @@ -0,0 +1,96 @@ +#include <sys/types.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <errno.h> + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = 65536; //getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = (char *) malloc (pagesize); + if (!data) + exit (1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftestmmap", 0600); + if (fd < 0) + { + printf ("creat: %d\n", errno); + exit (1); + } + if (write (fd, data, pagesize) != pagesize) + { + printf ("write: %d\n", errno); + exit (1); + } + close (fd); + + /* + * Next, try to mmap the file. + */ + fd = open ("conftestmmap", O_RDWR); + if (fd < 0) + { + printf ("write: %d\n", errno); + exit (1); + } + if ((data2 = mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0L)) == MAP_FAILED) + { + printf ("mmap: %d\n", errno); + exit (1); + } + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + { + printf ("check-if: %d\n", errno); + exit (1); + } + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + { + printf ("malloc2: %d\n", errno); + exit (1); + } + if (read (fd, data3, pagesize) != pagesize) + { + printf ("read: %d\n", errno); + exit (1); + } + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + { + printf ("check-if2: %d\n", errno); + exit (1); + } + if (msync (data2, pagesize, MS_SYNC)) + { + printf ("msync: %d\n", errno); + exit (1); + } + if (munmap (data2, pagesize)) + { + printf ("munmap: %d\n", errno); + exit (1); + } + close (fd); + unlink ("conftestmmap"); + exit (0); +} |