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