xref: /freebsd/contrib/sendmail/libsm/t-shm.c (revision 2e3f49888ec8851bafb22011533217487764fdb0)
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
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
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
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
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