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