1 /*
2 * Copyright (c) 2000-2002, 2004, 2005 Proofpoint, Inc. and its suppliers.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
9
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: t-shm.c,v 1.23 2013-11-22 20:51:43 ca Exp $")
12
13 #include <stdio.h>
14
15 #if SM_CONF_SHM
16 # include <stdlib.h>
17 # include <unistd.h>
18 # include <sys/wait.h>
19
20 # include <sm/heap.h>
21 # include <sm/string.h>
22 # include <sm/test.h>
23 # include <sm/conf.h>
24 # include <sm/shm.h>
25
26 # define SHMSIZE 1024
27 # define SHM_MAX 6400000
28 # define T_SHMKEY 21
29
30
31 /*
32 ** SHMINTER -- interactive testing of shared memory
33 **
34 ** Parameters:
35 ** owner -- create segment.
36 **
37 ** Returns:
38 ** 0 on success
39 ** < 0 on failure.
40 */
41
42 int shminter __P((bool));
43
44 int
shminter(owner)45 shminter(owner)
46 bool owner;
47 {
48 int *shm, shmid;
49 int i, t;
50
51 shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
52 if (shm == (int *) 0)
53 {
54 perror("shminit failed");
55 return -1;
56 }
57
58 while ((t = getchar()) != EOF)
59 {
60 switch (t)
61 {
62 case 'c':
63 *shm = 0;
64 break;
65 case 'i':
66 ++*shm;
67 break;
68 case 'd':
69 --*shm;
70 break;
71 case 's':
72 sleep(1);
73 break;
74 case 'l':
75 t = *shm;
76 for (i = 0; i < SHM_MAX; i++)
77 {
78 ++*shm;
79 }
80 if (*shm != SHM_MAX + t)
81 fprintf(stderr, "error: %d != %d\n",
82 *shm, SHM_MAX + t);
83 break;
84 case 'v':
85 printf("shmval: %d\n", *shm);
86 break;
87 case 'S':
88 i = sm_shmsetowner(shmid, getuid(), getgid(), 0644);
89 printf("sm_shmsetowner=%d\n", i);
90 break;
91 }
92 }
93 return sm_shmstop((void *) shm, shmid, owner);
94 }
95
96
97 /*
98 ** SHMBIG -- testing of shared memory
99 **
100 ** Parameters:
101 ** owner -- create segment.
102 ** size -- size of segment.
103 **
104 ** Returns:
105 ** 0 on success
106 ** < 0 on failure.
107 */
108
109 int shmbig __P((bool, int));
110
111 int
shmbig(owner,size)112 shmbig(owner, size)
113 bool owner;
114 int size;
115 {
116 int *shm, shmid;
117 int i;
118
119 shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner);
120 if (shm == (int *) 0)
121 {
122 perror("shminit failed");
123 return -1;
124 }
125
126 for (i = 0; i < size / sizeof(int); i++)
127 shm[i] = i;
128 for (i = 0; i < size / sizeof(int); i++)
129 {
130 if (shm[i] != i)
131 {
132 fprintf(stderr, "failed at %d: %d", i, shm[i]);
133 }
134 }
135
136 return sm_shmstop((void *) shm, shmid, owner);
137 }
138
139
140 /*
141 ** SHMTEST -- test of shared memory
142 **
143 ** Parameters:
144 ** owner -- create segment.
145 **
146 ** Returns:
147 ** 0 on success
148 ** < 0 on failure.
149 */
150
151 # define MAX_CNT 10
152
153 int shmtest __P((int));
154
155 int
shmtest(owner)156 shmtest(owner)
157 int owner;
158 {
159 int *shm, shmid;
160 int cnt = 0;
161
162 shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
163 if (shm == (int *) 0)
164 {
165 perror("shminit failed");
166 return -1;
167 }
168
169 if (owner)
170 {
171 int r;
172
173 r = sm_shmsetowner(shmid, getuid(), getgid(), 0660);
174 SM_TEST(r == 0);
175 *shm = 1;
176 while (*shm == 1 && cnt++ < MAX_CNT)
177 sleep(1);
178 SM_TEST(cnt <= MAX_CNT);
179
180 /* release and re-acquire the segment */
181 r = sm_shmstop((void *) shm, shmid, owner);
182 SM_TEST(r == 0);
183 shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
184 SM_TEST(shm != (int *) 0);
185 }
186 else
187 {
188 while (*shm != 1 && cnt++ < MAX_CNT)
189 sleep(1);
190 SM_TEST(cnt <= MAX_CNT);
191 *shm = 2;
192
193 /* wait a momemt so the segment is still in use */
194 sleep(2);
195 }
196 return sm_shmstop((void *) shm, shmid, owner);
197 }
198
199 int
main(argc,argv)200 main(argc, argv)
201 int argc;
202 char *argv[];
203 {
204 bool interactive = false;
205 bool owner = false;
206 int big = -1;
207 int ch;
208 int r = 0;
209 int status;
210 extern char *optarg;
211
212 # define OPTIONS "b:io"
213 while ((ch = getopt(argc, argv, OPTIONS)) != -1)
214 {
215 switch ((char) ch)
216 {
217 case 'b':
218 big = atoi(optarg);
219 break;
220
221 case 'i':
222 interactive = true;
223 break;
224
225 case 'o':
226 owner = true;
227 break;
228
229 default:
230 break;
231 }
232 }
233
234 if (interactive)
235 r = shminter(owner);
236 else if (big > 0)
237 r = shmbig(true, big);
238 else
239 {
240 pid_t pid;
241 extern int SmTestNumErrors;
242
243 if ((pid = fork()) < 0)
244 {
245 perror("fork failed\n");
246 return -1;
247 }
248
249 sm_test_begin(argc, argv, "test shared memory");
250 if (pid == 0)
251 {
252 /* give the parent the chance to setup data */
253 sleep(1);
254 r = shmtest(false);
255 }
256 else
257 {
258 r = shmtest(true);
259 (void) wait(&status);
260 }
261 SM_TEST(r == 0);
262 if (SmTestNumErrors > 0)
263 printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
264 return sm_test_end();
265 }
266 return r;
267 }
268 #else /* SM_CONF_SHM */
269 int
270 main(argc, argv)
271 int argc;
272 char *argv[];
273 {
274 printf("No support for shared memory configured on this machine\n");
275 return 0;
276 }
277 #endif /* SM_CONF_SHM */
278