diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | rt/Makefile | 4 | ||||
-rw-r--r-- | rt/tst-shm.c | 199 |
3 files changed, 206 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog index 61e7fd5b58..a561b60122 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2000-04-11 Ulrich Drepper <drepper@redhat.com> + * rt/Makefile (tests): Add tst-shm. + Add rules to generate tst-shm. + * rt/tst-shm.c: New file. + * sysdeps/unix/sysv/linux/shm_open.c (shm_open): Set FD_CLOEXEC for descriptor. diff --git a/rt/Makefile b/rt/Makefile index bb07ad0f4e..038636c497 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -39,7 +39,7 @@ include ../Makeconfig ifeq ($(have-thread-library),yes) -tests := tst-aio tst-aio64 tst-clock +tests := tst-aio tst-aio64 tst-clock tst-shm extra-libs := librt extra-libs-others := $(extra-libs) @@ -57,8 +57,10 @@ ifeq (yes,$(build-shared)) $(objpfx)tst-aio: $(objpfx)librt.so $(shared-thread-library) $(objpfx)tst-aio64: $(objpfx)librt.so $(shared-thread-library) $(objpfx)tst-clock: $(objpfx)librt.so $(shared-thread-library) +$(objpfx)tst-shm: $(objpfx)librt.so $(shared-thread-library) else $(objpfx)tst-aio: $(objpfx)librt.a $(static-thread-library) $(objpfx)tst-aio64: $(objpfx)librt.a $(static-thread-library) $(objpfx)tst-clock: $(objpfx)librt.a $(static-thread-library) +$(objpfx)tst-shm: $(objpfx)librt.a $(static-thread-library) endif diff --git a/rt/tst-shm.c b/rt/tst-shm.c new file mode 100644 index 0000000000..a1ec6df585 --- /dev/null +++ b/rt/tst-shm.c @@ -0,0 +1,199 @@ +/* Test program for POSIX shm_* functions. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + + +/* We want to see output immediately. */ +#define STDOUT_UNBUFFERED + + +static int +do_open (void) +{ + int fd; + + /* Create the shared memory object. */ + fd = shm_open ("/shm-test", O_RDWR, 0600); + if (fd == -1) + { + /* We don't regard this as a bug. Simply don't run the test. It could + means there is no such implementation or the object is already in + use in which case we don't want to disturb. */ + perror ("failed to open shared memory object: shm_open"); + return -1; + } + + return fd; +} + + +static void +worker (int write_now) +{ + struct timespec ts; + struct stat st; + int i; + int fd = do_open (); + char *mem; + + if (fd == -1) + exit (fd); + + if (fstat (fd, &st) == -1 || st.st_size != 4000) + error (EXIT_FAILURE, 0, "stat failed"); + + mem = mmap (NULL, 4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mem == NULL) + error (EXIT_FAILURE, 0, "mmap failed"); + + ts.tv_sec = 0; + ts.tv_nsec = 500000000; + + if (write_now) + for (i = 0; i <= 4; ++i) + mem[i] = i; + else + /* Wait until the first bytes of the memory region are 0, 1, 2, 3, 4. */ + while (1) + { + for (i = 0; i <= 4; ++i) + if (mem[i] != i) + break; + + if (i > 4) + /* OK, that's done. */ + break; + + nanosleep (&ts, NULL); + } + + if (!write_now) + for (i = 0; i <= 4; ++i) + mem[i] = 4 + i; + else + /* Wait until the first bytes of the memory region are 4, 5, 6, 7, 8. */ + while (1) + { + for (i = 0; i <= 4; ++i) + if (mem[i] != 4 + i) + break; + + if (i > 4) + /* OK, that's done. */ + break; + + nanosleep (&ts, NULL); + } + + if (munmap (mem, 4000) == -1) + error (EXIT_FAILURE, errno, "munmap"); + + close (fd); + + exit (0); +} + + +int +do_test (void) +{ + int fd; + pid_t pid1; + pid_t pid2; + int status1; + int status2; + + /* Create the shared memory object. */ + fd = shm_open ("/shm-test", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600); + if (fd == -1) + { + /* We don't regard this as a bug. Simply don't run the test. It could + means there is no such implementation or the object is already in + use in which case we don't want to disturb. */ + perror ("failed to create a shared memory object: shm_open"); + return 0; + } + + /* Size the object. We make it 4000 bytes long. */ + if (ftruncate (fd, 4000) == -1) + { + /* This failed. Must be a bug in the implementation of the + shared memory itself. */ + perror ("failed to size of shared memory object: ftruncate"); + close (fd); + shm_unlink ("/shm-test"); + return 0; + } + + /* Spawn to processes which will do the work. */ + pid1 = fork (); + if (pid1 == 0) + worker (0); + else if (pid1 == -1) + { + /* Couldn't create a second process. */ + perror ("fork"); + close (fd); + shm_unlink ("/shm-test"); + return 0; + } + + pid2 = fork (); + if (pid2 == 0) + worker (1); + else if (pid2 == -1) + { + /* Couldn't create a second process. */ + int ignore; + perror ("fork"); + kill (pid1, SIGTERM); + waitpid (pid1, &ignore, 0); + close (fd); + shm_unlink ("/shm-test"); + return 0; + } + + /* Wait until the two processes are finished. */ + waitpid (pid1, &status1, 0); + waitpid (pid2, &status2, 0); + + /* Now we can unlink the shared object. */ + shm_unlink ("/shm-test"); + + return (!WIFEXITED (status1) || WEXITSTATUS (status1) != 0 + || !WIFEXITED (status2) || WEXITSTATUS (status2) != 0); +} +#define TEST_FUNCTION do_test () + +#define CLEANUP_HANDLER shm_unlink ("/shm-test"); + + +#include "../test-skeleton.c" |