xref: /freebsd/contrib/sendmail/libsm/t-shm.c (revision b6bacd3150f411c3de886f7615bc22129b6974ad)
1 /*
2  * Copyright (c) 2000-2002, 2004 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.20 2004/08/03 20:51:36 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 		}
87 	}
88 	return sm_shmstop((void *) shm, shmid, owner);
89 }
90 
91 
92 /*
93 **  SHMBIG -- testing of shared memory
94 **
95 **	Parameters:
96 **		owner -- create segment.
97 **		size -- size of segment.
98 **
99 **	Returns:
100 **		0 on success
101 **		< 0 on failure.
102 */
103 
104 int shmbig __P((bool, int));
105 
106 int
107 shmbig(owner, size)
108 	bool owner;
109 	int size;
110 {
111 	int *shm, shmid;
112 	int i;
113 
114 	shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner);
115 	if (shm == (int *) 0)
116 	{
117 		perror("shminit failed");
118 		return -1;
119 	}
120 
121 	for (i = 0; i < size / sizeof(int); i++)
122 		shm[i] = i;
123 	for (i = 0; i < size / sizeof(int); i++)
124 	{
125 		if (shm[i] != i)
126 		{
127 			fprintf(stderr, "failed at %d: %d", i, shm[i]);
128 		}
129 	}
130 
131 	return sm_shmstop((void *) shm, shmid, owner);
132 }
133 
134 
135 /*
136 **  SHMTEST -- test of shared memory
137 **
138 **	Parameters:
139 **		owner -- create segment.
140 **
141 **	Returns:
142 **		0 on success
143 **		< 0 on failure.
144 */
145 
146 # define MAX_CNT	10
147 
148 int shmtest __P((int));
149 
150 int
151 shmtest(owner)
152 	int owner;
153 {
154 	int *shm, shmid;
155 	int cnt = 0;
156 
157 	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
158 	if (shm == (int *) 0)
159 	{
160 		perror("shminit failed");
161 		return -1;
162 	}
163 
164 	if (owner)
165 	{
166 		int r;
167 
168 		*shm = 1;
169 		while (*shm == 1 && cnt++ < MAX_CNT)
170 			sleep(1);
171 		SM_TEST(cnt <= MAX_CNT);
172 
173 		/* release and re-acquire the segment */
174 		r = sm_shmstop((void *) shm, shmid, owner);
175 		SM_TEST(r == 0);
176 		shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
177 		SM_TEST(shm != (int *) 0);
178 	}
179 	else
180 	{
181 		while (*shm != 1 && cnt++ < MAX_CNT)
182 			sleep(1);
183 		SM_TEST(cnt <= MAX_CNT);
184 		*shm = 2;
185 
186 		/* wait a momemt so the segment is still in use */
187 		sleep(2);
188 	}
189 	return sm_shmstop((void *) shm, shmid, owner);
190 }
191 
192 int
193 main(argc, argv)
194 	int argc;
195 	char *argv[];
196 {
197 	bool interactive = false;
198 	bool owner = false;
199 	int big = -1;
200 	int ch;
201 	int r = 0;
202 	int status;
203 	extern char *optarg;
204 
205 # define OPTIONS	"b:io"
206 	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
207 	{
208 		switch ((char) ch)
209 		{
210 		  case 'b':
211 			big = atoi(optarg);
212 			break;
213 
214 		  case 'i':
215 			interactive = true;
216 			break;
217 
218 		  case 'o':
219 			owner = true;
220 			break;
221 
222 		  default:
223 			break;
224 		}
225 	}
226 
227 	if (interactive)
228 		r = shminter(owner);
229 	else if (big > 0)
230 		r = shmbig(true, big);
231 	else
232 	{
233 		pid_t pid;
234 		extern int SmTestNumErrors;
235 
236 		if ((pid = fork()) < 0)
237 		{
238 			perror("fork failed\n");
239 			return -1;
240 		}
241 
242 		sm_test_begin(argc, argv, "test shared memory");
243 		if (pid == 0)
244 		{
245 			/* give the parent the chance to setup data */
246 			sleep(1);
247 			r = shmtest(false);
248 		}
249 		else
250 		{
251 			r = shmtest(true);
252 			(void) wait(&status);
253 		}
254 		SM_TEST(r == 0);
255 		if (SmTestNumErrors > 0)
256 			printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
257 		return sm_test_end();
258 	}
259 	return r;
260 }
261 #else /* SM_CONF_SHM */
262 int
263 main(argc, argv)
264 	int argc;
265 	char *argv[];
266 {
267 	printf("No support for shared memory configured on this machine\n");
268 	return 0;
269 }
270 #endif /* SM_CONF_SHM */
271