aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2001-04-19 09:16:40 +0000
committerCorinna Vinschen <corinna@vinschen.de>2001-04-19 09:16:40 +0000
commite8cec9646ed21bffa7edfb5709ed7b0327884036 (patch)
tree9ab5a81c5ae0fb43f80e9f890953d5eb5c6768d6
parentb78d6f6e7b8e38f4f3be6f9ff8e88ce535765256 (diff)
downloadnewlib-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/ChangeLog6
-rw-r--r--winsup/testsuite/winsup.api/mmaptest02.c189
-rw-r--r--winsup/testsuite/winsup.api/mmaptest03.c127
-rw-r--r--winsup/testsuite/winsup.api/mmaptest04.c96
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);
+}