xref: /freebsd/contrib/sendmail/libsm/t-shm.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
1 /*
2  * Copyright (c) 2000-2002 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.19 2004/04/20 23:14:21 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
149 shmtest(owner)
150 	int owner;
151 {
152 	int *shm, shmid;
153 	int cnt = 0;
154 
155 	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
156 	if (shm == (int *) 0)
157 	{
158 		perror("shminit failed");
159 		return -1;
160 	}
161 
162 	if (owner)
163 	{
164 		int r;
165 
166 		*shm = 1;
167 		while (*shm == 1 && cnt++ < MAX_CNT)
168 			sleep(1);
169 		SM_TEST(cnt <= MAX_CNT);
170 
171 		/* release and re-acquire the segment */
172 		r = sm_shmstop((void *) shm, shmid, owner);
173 		SM_TEST(r == 0);
174 		shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
175 		SM_TEST(shm != (int *) 0);
176 	}
177 	else
178 	{
179 		while (*shm != 1 && cnt++ < MAX_CNT)
180 			sleep(1);
181 		SM_TEST(cnt <= MAX_CNT);
182 		*shm = 2;
183 
184 		/* wait a momemt so the segment is still in use */
185 		sleep(2);
186 	}
187 	return sm_shmstop((void *) shm, shmid, owner);
188 }
189 
190 int
191 main(argc, argv)
192 	int argc;
193 	char *argv[];
194 {
195 	bool interactive = false;
196 	bool owner = false;
197 	int big = -1;
198 	int ch;
199 	int r = 0;
200 	int status;
201 	extern char *optarg;
202 
203 # define OPTIONS	"b:io"
204 	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
205 	{
206 		switch ((char) ch)
207 		{
208 		  case 'b':
209 			big = atoi(optarg);
210 			break;
211 
212 		  case 'i':
213 			interactive = true;
214 			break;
215 
216 		  case 'o':
217 			owner = true;
218 			break;
219 
220 		  default:
221 			break;
222 		}
223 	}
224 
225 	if (interactive)
226 		r = shminter(owner);
227 	else if (big > 0)
228 		r = shmbig(true, big);
229 	else
230 	{
231 		pid_t pid;
232 		extern int SmTestNumErrors;
233 
234 		if ((pid = fork()) < 0)
235 		{
236 			perror("fork failed\n");
237 			return -1;
238 		}
239 
240 		sm_test_begin(argc, argv, "test shared memory");
241 		if (pid == 0)
242 		{
243 			/* give the parent the chance to setup data */
244 			sleep(1);
245 			r = shmtest(false);
246 		}
247 		else
248 		{
249 			r = shmtest(true);
250 			(void) wait(&status);
251 		}
252 		SM_TEST(r == 0);
253 		if (SmTestNumErrors > 0)
254 			printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
255 		return sm_test_end();
256 	}
257 	return r;
258 }
259 #else /* SM_CONF_SHM */
260 int
261 main(argc, argv)
262 	int argc;
263 	char *argv[];
264 {
265 	printf("No support for shared memory configured on this machine\n");
266 	return 0;
267 }
268 #endif /* SM_CONF_SHM */
269