Merge glibc-ports into ports/ directory.
[platform/upstream/glibc.git] / rt / tst-shm.c
1 /* Test program for POSIX shm_* functions.
2    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
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 stat64 st;
63   int i;
64   int fd = do_open ();
65   char *mem;
66
67   if (fd == -1)
68     exit (fd);
69
70   if (fstat64 (fd, &st) == -1)
71     error (EXIT_FAILURE, 0, "stat failed");
72   if (st.st_size != 4000)
73     error (EXIT_FAILURE, 0, "size incorrect");
74
75   mem = mmap (NULL, 4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
76   if (mem == NULL)
77     error (EXIT_FAILURE, 0, "mmap failed");
78
79   ts.tv_sec = 0;
80   ts.tv_nsec = 500000000;
81
82   if (write_now)
83     for (i = 0; i <= 4; ++i)
84       mem[i] = i;
85   else
86     /* Wait until the first bytes of the memory region are 0, 1, 2, 3, 4.  */
87     while (1)
88       {
89         for (i = 0; i <= 4; ++i)
90           if (mem[i] != i)
91             break;
92
93         if (i > 4)
94           /* OK, that's done.  */
95           break;
96
97         nanosleep (&ts, NULL);
98       }
99
100   if (!write_now)
101     for (i = 0; i <= 4; ++i)
102       mem[i] = 4 + i;
103   else
104     /* Wait until the first bytes of the memory region are 4, 5, 6, 7, 8.  */
105     while (1)
106       {
107         for (i = 0; i <= 4; ++i)
108           if (mem[i] != 4 + i)
109             break;
110
111         if (i > 4)
112           /* OK, that's done.  */
113           break;
114
115         nanosleep (&ts, NULL);
116       }
117
118   if (munmap (mem, 4000) == -1)
119     error (EXIT_FAILURE, errno, "munmap");
120
121   close (fd);
122
123   exit (0);
124 }
125
126
127 static int
128 do_test (void)
129 {
130   int fd;
131   pid_t pid1;
132   pid_t pid2;
133   int status1;
134   int status2;
135   struct stat64 st;
136
137   /* Create the shared memory object.  */
138   fd = shm_open ("/shm-test", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
139   if (fd == -1)
140     {
141       /* We don't regard this as a bug.  Simply don't run the test.  It could
142          means there is no such implementation or the object is already in
143          use in which case we don't want to disturb.  */
144       perror ("failed to create a shared memory object: shm_open");
145       return 0;
146     }
147
148   /* Size the object.  We make it 4000 bytes long.  */
149   if (ftruncate (fd, 4000) == -1)
150     {
151       /* This failed.  Must be a bug in the implementation of the
152          shared memory itself.  */
153       perror ("failed to size of shared memory object: ftruncate");
154       close (fd);
155       shm_unlink ("/shm-test");
156       return 0;
157     }
158
159   if (fstat64 (fd, &st) == -1)
160     {
161       shm_unlink ("/shm-test");
162       error (EXIT_FAILURE, 0, "initial stat failed");
163     }
164   if (st.st_size != 4000)
165     {
166       shm_unlink ("/shm-test");
167       error (EXIT_FAILURE, 0, "initial size not correct");
168     }
169
170   /* Spawn to processes which will do the work.  */
171   pid1 = fork ();
172   if (pid1 == 0)
173     worker (0);
174   else if (pid1 == -1)
175     {
176       /* Couldn't create a second process.  */
177       perror ("fork");
178       close (fd);
179       shm_unlink ("/shm-test");
180       return 0;
181     }
182
183   pid2 = fork ();
184   if (pid2 == 0)
185     worker (1);
186   else if (pid2 == -1)
187     {
188       /* Couldn't create a second process.  */
189       int ignore;
190       perror ("fork");
191       kill (pid1, SIGTERM);
192       waitpid (pid1, &ignore, 0);
193       close (fd);
194       shm_unlink ("/shm-test");
195       return 0;
196     }
197
198   /* Wait until the two processes are finished.  */
199   waitpid (pid1, &status1, 0);
200   waitpid (pid2, &status2, 0);
201
202   /* Now we can unlink the shared object.  */
203   shm_unlink ("/shm-test");
204
205   return (!WIFEXITED (status1) || WEXITSTATUS (status1) != 0
206           || !WIFEXITED (status2) || WEXITSTATUS (status2) != 0);
207 }
208 #define TEST_FUNCTION do_test ()
209
210 #define CLEANUP_HANDLER shm_unlink ("/shm-test");
211
212
213 #include "../test-skeleton.c"