Program to test POSIX shm_* functions.
[kopensolaris-gnu/glibc.git] / rt / tst-shm.c
1 /* Test program for POSIX shm_* functions.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <errno.h>
21 #include <error.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32
33
34 /* We want to see output immediately.  */
35 #define STDOUT_UNBUFFERED
36
37
38 static int
39 do_open (void)
40 {
41   int fd;
42
43   /* Create the shared memory object.  */
44   fd = shm_open ("/shm-test", O_RDWR, 0600);
45   if (fd == -1)
46     {
47       /* We don't regard this as a bug.  Simply don't run the test.  It could
48          means there is no such implementation or the object is already in
49          use in which case we don't want to disturb.  */
50       perror ("failed to open shared memory object: shm_open");
51       return -1;
52     }
53
54   return fd;
55 }
56
57
58 static void
59 worker (int write_now)
60 {
61   struct timespec ts;
62   struct stat st;
63   int i;
64   int fd = do_open ();
65   char *mem;
66
67   if (fd == -1)
68     exit (fd);
69
70   if (fstat (fd, &st) == -1 || st.st_size != 4000)
71     error (EXIT_FAILURE, 0, "stat failed");
72
73   mem = mmap (NULL, 4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
74   if (mem == NULL)
75     error (EXIT_FAILURE, 0, "mmap failed");
76
77   ts.tv_sec = 0;
78   ts.tv_nsec = 500000000;
79
80   if (write_now)
81     for (i = 0; i <= 4; ++i)
82       mem[i] = i;
83   else
84     /* Wait until the first bytes of the memory region are 0, 1, 2, 3, 4.  */
85     while (1)
86       {
87         for (i = 0; i <= 4; ++i)
88           if (mem[i] != i)
89             break;
90
91         if (i > 4)
92           /* OK, that's done.  */
93           break;
94
95         nanosleep (&ts, NULL);
96       }
97
98   if (!write_now)
99     for (i = 0; i <= 4; ++i)
100       mem[i] = 4 + i;
101   else
102     /* Wait until the first bytes of the memory region are 4, 5, 6, 7, 8.  */
103     while (1)
104       {
105         for (i = 0; i <= 4; ++i)
106           if (mem[i] != 4 + i)
107             break;
108
109         if (i > 4)
110           /* OK, that's done.  */
111           break;
112
113         nanosleep (&ts, NULL);
114       }
115
116   if (munmap (mem, 4000) == -1)
117     error (EXIT_FAILURE, errno, "munmap");
118
119   close (fd);
120
121   exit (0);
122 }
123
124
125 int
126 do_test (void)
127 {
128   int fd;
129   pid_t pid1;
130   pid_t pid2;
131   int status1;
132   int status2;
133
134   /* Create the shared memory object.  */
135   fd = shm_open ("/shm-test", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
136   if (fd == -1)
137     {
138       /* We don't regard this as a bug.  Simply don't run the test.  It could
139          means there is no such implementation or the object is already in
140          use in which case we don't want to disturb.  */
141       perror ("failed to create a shared memory object: shm_open");
142       return 0;
143     }
144
145   /* Size the object.  We make it 4000 bytes long.  */
146   if (ftruncate (fd, 4000) == -1)
147     {
148       /* This failed.  Must be a bug in the implementation of the
149          shared memory itself.  */
150       perror ("failed to size of shared memory object: ftruncate");
151       close (fd);
152       shm_unlink ("/shm-test");
153       return 0;
154     }
155
156   /* Spawn to processes which will do the work.  */
157   pid1 = fork ();
158   if (pid1 == 0)
159     worker (0);
160   else if (pid1 == -1)
161     {
162       /* Couldn't create a second process.  */
163       perror ("fork");
164       close (fd);
165       shm_unlink ("/shm-test");
166       return 0;
167     }
168
169   pid2 = fork ();
170   if (pid2 == 0)
171     worker (1);
172   else if (pid2 == -1)
173     {
174       /* Couldn't create a second process.  */
175       int ignore;
176       perror ("fork");
177       kill (pid1, SIGTERM);
178       waitpid (pid1, &ignore, 0);
179       close (fd);
180       shm_unlink ("/shm-test");
181       return 0;
182     }
183
184   /* Wait until the two processes are finished.  */
185   waitpid (pid1, &status1, 0);
186   waitpid (pid2, &status2, 0);
187
188   /* Now we can unlink the shared object.  */
189   shm_unlink ("/shm-test");
190
191   return (!WIFEXITED (status1) || WEXITSTATUS (status1) != 0
192           || !WIFEXITED (status2) || WEXITSTATUS (status2) != 0);
193 }
194 #define TEST_FUNCTION do_test ()
195
196 #define CLEANUP_HANDLER shm_unlink ("/shm-test");
197
198
199 #include "../test-skeleton.c"