• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Copyright (C) Bull S.A. 1996
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *   Copyright (C) 2008 CAI Qian <caiqian@cclom.cn>
5  *
6  *   This program is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU General Public License as
8  *   published by the Free Software Foundation; either version 2 of the
9  *   License, or (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14  *   the GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  *   USA
20  */
21 /*---------------------------------------------------------------------+
22 |                           shmem_test_06.c                            |
23 | ==================================================================== |
24 | Title:        Segment Register 0xE                                   |
25 |                                                                      |
26 | Purpose:      simultaneous attachment of more than ten shared        |
27 |               memory regions to a process. Using segment registers   |
28 |               0x3 to 0xC and 0xE .                                   |
29 |                                                                      |
30 | Description:  Simplistic test to verify that a process can obtain    |
31 |               11 shared memory regions.                              |
32 |                                                                      |
33 |                                                                      |
34 | Algorithm:    *  from 1 up to 11                                     |
35 |               {                                                      |
36 |               o  Create a key to uniquely identify the shared segment|
37 |		   using ftok()	subroutine.			       |
38 |               o  Obtain a unique shared memory identifier with       |
39 |                  shmget ()                                           |
40 |               o  Map the shared memory segment to the current        |
41 |                  process with shmat ()                               |
42 |               o  Index through the shared memory segment             |
43 |               }                                                      |
44 |               *  from 1 up to 11                                     |
45 |               {                                                      |
46 |               o  Detach from the segment with shmdt()                |
47 |               o  Release the shared memory segment with shmctl ()    |
48 |               }                                                      |
49 |                                                                      |
50 | System calls: The following system calls are tested:                 |
51 |                                                                      |
52 |               ftok()                                                 |
53 |               shmget ()                                              |
54 |               shmat ()                                               |
55 |               shmdt ()                                               |
56 |               shmctl ()                                              |
57 |                                                                      |
58 | Usage:        shmem_test_06                                          |
59 |                                                                      |
60 | To compile:   cc -O -g  shmem_test_06.c -o shmem_test_06 -lbsd       |
61 |                                                                      |
62 | Last update:                                                         |
63 |                                                                      |
64 | Change Activity                                                      |
65 |                                                                      |
66 |   Version  Date    Name  Reason                                      |
67 |    0.1     010797  J.Malcles  initial version for 4.2.G              |
68 |                                                                      |
69 |                                                                      |
70 +---------------------------------------------------------------------*/
71 
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75 #include <errno.h>
76 #include <unistd.h>
77 #include <sys/shm.h>
78 
79 #include <sys/types.h>
80 #include <sys/ipc.h>
81 
82 #include <sys/stat.h>
83 int offsets_cnt = 11;
84 /* Defines
85  *
86  * MAX_SHMEM_SIZE: maximum shared memory segment size of 256MB
87  *
88  * MAX_SHMEM_NUMBER: maximum number of simultaneous attached shared memory
89  * regions
90  *
91  * DEFAULT_SHMEM_SIZE: default shared memory size, unless specified with
92  * -s command line option
93  *
94  * SHMEM_MODE: shared memory access permissions (permit process to read
95  * and write access)
96  *
97  * USAGE: usage statement
98  */
99 #define MAX_SHMEM_SIZE		256*1024*1024
100 #define MAX_SHMEM_NUMBER	11
101 #define DEFAULT_SHMEM_SIZE	1024*1024
102 #define	SHMEM_MODE		(SHM_R | SHM_W)
103 #define USAGE	"\nUsage: %s [-s shmem_size]\n\n" \
104 		"\t-s shmem_size  size of shared memory segment (bytes)\n" \
105 		"\t               (must be less than 256MB!)\n\n"
106 
107 #define GOTHERE printf("got to line %d\n", __LINE__);
108 
109 /*
110  * Function prototypes
111  *
112  * parse_args (): Parse command line arguments
113  * sys_error (): System error message function
114  * error (): Error message function
115  */
116 void parse_args(int, char **);
117 void sys_error(const char *, int);
118 void error(const char *, int);
119 
120 /*
121  * Global variables
122  *
123  * shmem_size: shared memory segment size (in bytes)
124  */
125 int shmem_size = DEFAULT_SHMEM_SIZE;
126 
127 /*---------------------------------------------------------------------+
128 |                               main                                   |
129 | ==================================================================== |
130 |                                                                      |
131 |                                                                      |
132 | Function:  Main program  (see prolog for more details)               |
133 |                                                                      |
134 | Returns:   (0)  Successful completion                                |
135 |            (-1) Error occurred                                       |
136 |                                                                      |
137 +---------------------------------------------------------------------*/
main(int argc,char ** argv)138 int main(int argc, char **argv)
139 {
140 	int i;
141 
142 	int shmid[MAX_SHMEM_NUMBER];	/* (Unique) Shared memory identifier */
143 
144 	char *shmptr[MAX_SHMEM_NUMBER];	/* Shared memory segment address */
145 	char *ptr;		/* Index into shared memory segment */
146 
147 	int value = 0;		/* Value written into shared memory segment */
148 
149 	key_t mykey[MAX_SHMEM_NUMBER];
150 	char *null_file = "/dev/null";
151 	char proj[MAX_SHMEM_NUMBER] = {
152 		'3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'E'
153 	};
154 
155 	/*
156 	 * Parse command line arguments and print out program header
157 	 */
158 	parse_args(argc, argv);
159 	printf("%s: IPC Shared Memory TestSuite program\n", *argv);
160 
161 	for (i = 0; i < offsets_cnt; i++) {
162 		char tmpstr[256];
163 		/*
164 		 * Create a key to uniquely identify the shared segment
165 		 */
166 
167 		mykey[i] = ftok(null_file, proj[i]);
168 
169 		printf
170 		    ("\n\tmykey to uniquely identify the shared memory segment 0x%x\n",
171 		     mykey[i]);
172 
173 		printf("\n\tGet shared memory segment (%d bytes)\n",
174 		       shmem_size);
175 		/*
176 		 * Obtain a unique shared memory identifier with shmget ().
177 		 */
178 
179 		if ((long)
180 		    (shmid[i] =
181 		     shmget(mykey[i], shmem_size, IPC_CREAT | 0666)) < 0)
182 			sys_error("shmget failed", __LINE__);
183 
184 		printf("\n\tAttach shared memory segment to process\n");
185 
186 		if ((long)(shmptr[i] = shmat(shmid[i], NULL, 0)) == -1) {
187 			/* If shmat(2) failed, we need the currect process address
188 			   space layout to debug. The failure can be random. */
189 			sprintf(tmpstr, "cat /proc/%d/maps >&2", (int)getpid());
190 			fprintf(stderr, "heap %p\n", sbrk(0));
191 			system(tmpstr);
192 
193 			sprintf(tmpstr, "shmat failed - return: %ld",
194 				(long)shmptr[i]);
195 			sys_error(tmpstr, __LINE__);
196 		}
197 
198 		printf("\n\tShared memory segment address : %p \n", shmptr[i]);
199 
200 		printf("\n\tIndex through shared memory segment ...\n");
201 
202 		/*
203 		 * Index through the shared memory segment
204 		 */
205 
206 		for (ptr = shmptr[i]; ptr < (shmptr[i] + shmem_size); ptr++)
207 			*ptr = value++;
208 
209 	}			// for 1..11
210 
211 	printf("\n\tDetach from the segment using the shmdt subroutine\n");
212 
213 	printf("\n\tRelease shared memory\n");
214 
215 	for (i = 0; i < offsets_cnt; i++) {
216 		// Detach from the segment
217 
218 		shmdt(shmptr[i]);
219 
220 		// Release shared memory
221 
222 		if (shmctl(shmid[i], IPC_RMID, 0) < 0)
223 			sys_error("shmctl failed", __LINE__);
224 
225 	}			// 2nd for 1..11
226 	/*
227 	 * Program completed successfully -- exit
228 	 */
229 
230 	printf("\nsuccessful!\n");
231 
232 	return (0);
233 
234 }
235 
236 /*---------------------------------------------------------------------+
237 |                             parse_args ()                            |
238 | ==================================================================== |
239 |                                                                      |
240 | Function:  Parse the command line arguments & initialize global      |
241 |            variables.                                                |
242 |                                                                      |
243 | Updates:   (command line options)                                    |
244 |                                                                      |
245 |            [-s] size: shared memory segment size                     |
246 |                                                                      |
247 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)248 void parse_args(int argc, char **argv)
249 {
250 	int i;
251 	int errflag = 0;
252 	char *program_name = *argv;
253 	extern char *optarg;	/* Command line option */
254 
255 	while ((i = getopt(argc, argv, "s:?")) != EOF) {
256 		switch (i) {
257 		case 's':
258 			shmem_size = atoi(optarg);
259 			break;
260 		case '?':
261 			errflag++;
262 			break;
263 		}
264 	}
265 
266 	if (shmem_size < 1 || shmem_size > MAX_SHMEM_SIZE)
267 		errflag++;
268 
269 	if (errflag) {
270 		fprintf(stderr, USAGE, program_name);
271 		exit(2);
272 	}
273 }
274 
275 /*---------------------------------------------------------------------+
276   |                             sys_error ()                             |
277   | ==================================================================== |
278   |                                                                      |
279   | Function:  Creates system error message and calls error ()           |
280   |                                                                      |
281   +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)282 void sys_error(const char *msg, int line)
283 {
284 	char syserr_msg[256];
285 
286 	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
287 	error(syserr_msg, line);
288 }
289 
290 /*---------------------------------------------------------------------+
291 |                               error ()                               |
292 | ==================================================================== |
293 |                                                                      |
294 | Function:  Prints out message and exits...                           |
295 |                                                                      |
296 +---------------------------------------------------------------------*/
error(const char * msg,int line)297 void error(const char *msg, int line)
298 {
299 	fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
300 	exit(-1);
301 }
302