1f08c3bdfSopenharmony_ci/******************************************************************************/
2f08c3bdfSopenharmony_ci/*									      */
3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines  Corp., 2001		      */
4f08c3bdfSopenharmony_ci/*									      */
5f08c3bdfSopenharmony_ci/* This program is free software;  you can redistribute it and/or modify      */
6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by       */
7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or          */
8f08c3bdfSopenharmony_ci/* (at your option) any later version.					      */
9f08c3bdfSopenharmony_ci/*									      */
10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful,	      */
11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY;  without even the implied warranty of	      */
12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	              */
13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details.			      */
14f08c3bdfSopenharmony_ci/*									      */
15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License	      */
16f08c3bdfSopenharmony_ci/* along with this program;  if not, write to the Free Software		      */
17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
18f08c3bdfSopenharmony_ci/*									      */
19f08c3bdfSopenharmony_ci/******************************************************************************/
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci/******************************************************************************/
22f08c3bdfSopenharmony_ci/*                                                                            */
23f08c3bdfSopenharmony_ci/* History:     Nov - 21 - 2001 Created - Manoj Iyer, IBM Austin TX.          */
24f08c3bdfSopenharmony_ci/*                               email:manjo@austin.ibm.com                   */
25f08c3bdfSopenharmony_ci/*                                                                            */
26f08c3bdfSopenharmony_ci/*		Nov - 26 - 2001 Modified - Manoj Iyer, IBM Austin Tx.         */
27f08c3bdfSopenharmony_ci/*				- Added function rm_shared_mem.               */
28f08c3bdfSopenharmony_ci/*                                                                            */
29f08c3bdfSopenharmony_ci/*		Dec - 03 - 2001 Modified - Manoj Iyer, IBM Austin Tx.         */
30f08c3bdfSopenharmony_ci/*				- Added code to spawn threads.		      */
31f08c3bdfSopenharmony_ci/*				- Removed dead code.		              */
32f08c3bdfSopenharmony_ci/*				- Checked in the initial version to CVS       */
33f08c3bdfSopenharmony_ci/*								              */
34f08c3bdfSopenharmony_ci/*		Feb - 27 - 2001 Modified - Manoj Iyer, IBM Austin TX.         */
35f08c3bdfSopenharmony_ci/*				- removed compiler warnings.                  */
36f08c3bdfSopenharmony_ci/*				- removed compiler errors.                    */
37f08c3bdfSopenharmony_ci/*                                                                            */
38f08c3bdfSopenharmony_ci/* File:	shm_test.c				                      */
39f08c3bdfSopenharmony_ci/*									      */
40f08c3bdfSopenharmony_ci/* Description:	This program is designed to stress the Memory management sub -*/
41f08c3bdfSopenharmony_ci/*		system of Linux. This program will spawn multiple pairs of    */
42f08c3bdfSopenharmony_ci/*		reader and writer threads. One thread will create the shared  */
43f08c3bdfSopenharmony_ci/*		segment of random size and write to this memory, the other    */
44f08c3bdfSopenharmony_ci/*		pair will read from this memory.		              */
45f08c3bdfSopenharmony_ci/*									      */
46f08c3bdfSopenharmony_ci/******************************************************************************/
47f08c3bdfSopenharmony_ci#include <pthread.h>		/* required by pthread functions                      */
48f08c3bdfSopenharmony_ci#include <stdio.h>		/* required by fprintf()                              */
49f08c3bdfSopenharmony_ci#include <stdlib.h>		/* required by exit(), atoi()                         */
50f08c3bdfSopenharmony_ci#include <string.h>		/* required by strncpy()                              */
51f08c3bdfSopenharmony_ci#include <unistd.h>		/* required by getopt(), mmap()                       */
52f08c3bdfSopenharmony_ci#include <sys/types.h>		/* required by open(), shmat(), shmdt()               */
53f08c3bdfSopenharmony_ci#include <sys/stat.h>		/* required by open()                                 */
54f08c3bdfSopenharmony_ci#include <sys/ipc.h>		/* required by shmat() shmdt(), shmctl()              */
55f08c3bdfSopenharmony_ci#include <sys/shm.h>		/* required by shmat() shmdt(), shmctl()              */
56f08c3bdfSopenharmony_ci#include <sys/mman.h>		/* required by mmap()                                 */
57f08c3bdfSopenharmony_ci#include <fcntl.h>		/* required by open()                                 */
58f08c3bdfSopenharmony_ci#include <stdint.h>		/* required by uintptr_t                              */
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_civoid noprintf(char *string, ...)
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci}
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci#ifdef DEBUG
65f08c3bdfSopenharmony_ci#define dprt	printf
66f08c3bdfSopenharmony_ci#else
67f08c3bdfSopenharmony_ci#define dprt	noprintf
68f08c3bdfSopenharmony_ci#endif
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci#define PTHREAD_EXIT(val)    do {\
71f08c3bdfSopenharmony_ci			exit_val = val; \
72f08c3bdfSopenharmony_ci                        dprt("pid[%d]: exiting with %d\n", getpid(),exit_val); \
73f08c3bdfSopenharmony_ci			pthread_exit((void *)(uintptr_t)exit_val); \
74f08c3bdfSopenharmony_ci				} while (0)
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci#define OPT_MISSING(prog, opt)   do{\
77f08c3bdfSopenharmony_ci			       fprintf(stderr, "%s: option -%c ", prog, opt); \
78f08c3bdfSopenharmony_ci                               fprintf(stderr, "requires an argument\n"); \
79f08c3bdfSopenharmony_ci                               usage(prog); \
80f08c3bdfSopenharmony_ci                                   } while (0)
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci#define MAXT	30		/* default number of threads to create.               */
83f08c3bdfSopenharmony_ci#define MAXR	1000		/* default number of repatetions to execute           */
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_cistruct child_args
86f08c3bdfSopenharmony_ci{
87f08c3bdfSopenharmony_ci	pthread_t threadid;
88f08c3bdfSopenharmony_ci	int num_reps;
89f08c3bdfSopenharmony_ci	int shmkey;
90f08c3bdfSopenharmony_ci	int map_size;
91f08c3bdfSopenharmony_ci	int is_reader;
92f08c3bdfSopenharmony_ci};
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci/******************************************************************************/
96f08c3bdfSopenharmony_ci/*								 	      */
97f08c3bdfSopenharmony_ci/* Function:	usage							      */
98f08c3bdfSopenharmony_ci/*									      */
99f08c3bdfSopenharmony_ci/* Description:	Print the usage message.				      */
100f08c3bdfSopenharmony_ci/*									      */
101f08c3bdfSopenharmony_ci/* Return:	exits with -1						      */
102f08c3bdfSopenharmony_ci/*									      */
103f08c3bdfSopenharmony_ci/******************************************************************************/
104f08c3bdfSopenharmony_cistatic void usage(char *progname)
105f08c3bdfSopenharmony_ci{				/* name of this program                       */
106f08c3bdfSopenharmony_ci	fprintf(stderr,
107f08c3bdfSopenharmony_ci		"Usage: %s -d NUMDIR -f NUMFILES -h -t NUMTHRD\n"
108f08c3bdfSopenharmony_ci		"\t -h Help!\n"
109f08c3bdfSopenharmony_ci		"\t -l Number of repatetions to execute:       Default: 1000\n"
110f08c3bdfSopenharmony_ci		"\t -t Number of threads to generate:          Default: 30\n",
111f08c3bdfSopenharmony_ci		progname);
112f08c3bdfSopenharmony_ci	exit(-1);
113f08c3bdfSopenharmony_ci}
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci/******************************************************************************/
116f08c3bdfSopenharmony_ci/*								 	      */
117f08c3bdfSopenharmony_ci/* Function:	rm_shared_mem						      */
118f08c3bdfSopenharmony_ci/*									      */
119f08c3bdfSopenharmony_ci/* Description:	This function removes the shared segments that were created   */
120f08c3bdfSopenharmony_ci/*		This function is called when shmat fails or logical end of    */
121f08c3bdfSopenharmony_ci/*		the while loop is reached in shmat_rd_wr function.         */
122f08c3bdfSopenharmony_ci/*									      */
123f08c3bdfSopenharmony_ci/* Input:	shm_id   - id of the shared memory segment to be removed      */
124f08c3bdfSopenharmony_ci/*		shm_addr - address of the shared memory segment to be removed */
125f08c3bdfSopenharmony_ci/*		cmd      - remove id only or remove id and detach??           */
126f08c3bdfSopenharmony_ci/*			   0 - remove id dont detach segment.                 */
127f08c3bdfSopenharmony_ci/*			   1 - remove id and detach segment.                  */
128f08c3bdfSopenharmony_ci/*									      */
129f08c3bdfSopenharmony_ci/* Output:	NONE.                                                         */
130f08c3bdfSopenharmony_ci/*									      */
131f08c3bdfSopenharmony_ci/* Return:	exits with -1 on error, 0 on success                          */
132f08c3bdfSopenharmony_ci/*									      */
133f08c3bdfSopenharmony_ci/******************************************************************************/
134f08c3bdfSopenharmony_cistatic int rm_shared_mem(key_t shm_id,	/* id of shared memory segment to be removed  */
135f08c3bdfSopenharmony_ci			 char *shm_addr,	/* address of shared mem seg to be removed    */
136f08c3bdfSopenharmony_ci			 int cmd)
137f08c3bdfSopenharmony_ci{				/* remove id only or remove id and detach seg */
138f08c3bdfSopenharmony_ci	struct shmid *shmbuf = NULL;	/* info about the segment pointed by shmkey   */
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci	dprt("pid[%d]: rm_shared_mem(): shm_id = %d shm_addr = %#x cmd = %d\n",
141f08c3bdfSopenharmony_ci	     getpid(), shm_id, shm_addr, cmd);
142f08c3bdfSopenharmony_ci	if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *)shmbuf) == -1) {
143f08c3bdfSopenharmony_ci		dprt("pid[%d]: rm_shared_mem(): shmctl unable to remove shm_id[%d]\n", getpid(), shm_id);
144f08c3bdfSopenharmony_ci		perror("rm_shared_mem(): shmctl()");
145f08c3bdfSopenharmony_ci		return -1;
146f08c3bdfSopenharmony_ci	}
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_ci	if (cmd) {
149f08c3bdfSopenharmony_ci		if (shmdt((void *)shm_addr) == -1) {
150f08c3bdfSopenharmony_ci			dprt("pid[%d]:rm_shared_mem(): shmdt unable to detach addr = %#x\n", getpid(), shm_addr);
151f08c3bdfSopenharmony_ci			perror("rm_shared_mem(): shmdt()");
152f08c3bdfSopenharmony_ci			return -1;
153f08c3bdfSopenharmony_ci		}
154f08c3bdfSopenharmony_ci	}
155f08c3bdfSopenharmony_ci	return 0;
156f08c3bdfSopenharmony_ci}
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ci/******************************************************************************/
159f08c3bdfSopenharmony_ci/*								 	      */
160f08c3bdfSopenharmony_ci/* Function:	shmat_rd_wr						      */
161f08c3bdfSopenharmony_ci/*									      */
162f08c3bdfSopenharmony_ci/* Description:	This function repeatedly attaches and detaches the memory     */
163f08c3bdfSopenharmony_ci/*		The size of the file is a multiple of page size.              */
164f08c3bdfSopenharmony_ci/*		The function acts as either reader or writer thread depending */
165f08c3bdfSopenharmony_ci/*		on arg[3]. The reader and writer thread use the same key so   */
166f08c3bdfSopenharmony_ci/*		they get access to the same shared memory segment.            */
167f08c3bdfSopenharmony_ci/*									      */
168f08c3bdfSopenharmony_ci/* Input:	The argument pointer contains the following.                  */
169f08c3bdfSopenharmony_ci/*		arg[0] - number of repatetions of the above operation         */
170f08c3bdfSopenharmony_ci/*		arg[1] - shared memory key.				      */
171f08c3bdfSopenharmony_ci/*		arg[2] - size of the memory that is to be attached.           */
172f08c3bdfSopenharmony_ci/*		arg[3] - reader or writer.                                    */
173f08c3bdfSopenharmony_ci/*									      */
174f08c3bdfSopenharmony_ci/* Return:	exits with -1 on error, 0 on success                          */
175f08c3bdfSopenharmony_ci/*									      */
176f08c3bdfSopenharmony_ci/******************************************************************************/
177f08c3bdfSopenharmony_cistatic void *shmat_rd_wr(void *vargs)
178f08c3bdfSopenharmony_ci{				/* arguments to the thread function             */
179f08c3bdfSopenharmony_ci	int shmndx = 0;		/* index to the number of attach and detach   */
180f08c3bdfSopenharmony_ci	int index = 0;		/* index to the number of blocks touched      */
181f08c3bdfSopenharmony_ci	key_t shm_id = 0;	/* shared memory id                           */
182f08c3bdfSopenharmony_ci	struct child_args *args = vargs;
183f08c3bdfSopenharmony_ci	volatile int exit_val = 0;	/* exit value of the pthread                  */
184f08c3bdfSopenharmony_ci	char *read_from_mem;	/* ptr to touch each (4096) block in memory   */
185f08c3bdfSopenharmony_ci	char *write_to_mem;	/* ptr to touch each (4096) block in memory   */
186f08c3bdfSopenharmony_ci	char *shmat_addr;	/* address of the attached memory             */
187f08c3bdfSopenharmony_ci	char buff;		/* temporary buffer                           */
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_ci	while (shmndx++ < args->num_reps) {
190f08c3bdfSopenharmony_ci		dprt("pid[%d]: shmat_rd_wr(): locargs[1] = %#x\n",
191f08c3bdfSopenharmony_ci		     getpid(), args->shmkey);
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ci		/* get shared memory id */
194f08c3bdfSopenharmony_ci		if ((shm_id =
195f08c3bdfSopenharmony_ci		     shmget(args->shmkey, args->map_size, IPC_CREAT | 0666))
196f08c3bdfSopenharmony_ci		    == -1) {
197f08c3bdfSopenharmony_ci			dprt("pid[%d]: shmat_rd_wr(): shmget failed\n",
198f08c3bdfSopenharmony_ci			     getpid());
199f08c3bdfSopenharmony_ci			perror("do_shmat_shmadt(): shmget()");
200f08c3bdfSopenharmony_ci			PTHREAD_EXIT(-1);
201f08c3bdfSopenharmony_ci		}
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_ci		fprintf(stdout, "pid[%d]: shmat_rd_wr(): shmget():"
204f08c3bdfSopenharmony_ci			"success got segment id %d\n", getpid(), shm_id);
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci		/* get shared memory segment */
207f08c3bdfSopenharmony_ci		if ((shmat_addr = shmat(shm_id, NULL, 0)) == (void *)-1) {
208f08c3bdfSopenharmony_ci			rm_shared_mem(shm_id, shmat_addr, 0);
209f08c3bdfSopenharmony_ci			fprintf(stderr,
210f08c3bdfSopenharmony_ci				"pid[%d]: do_shmat_shmadt(): shmat_addr = %#lx\n",
211f08c3bdfSopenharmony_ci				getpid(), (long)shmat_addr);
212f08c3bdfSopenharmony_ci			perror("do_shmat_shmadt(): shmat()");
213f08c3bdfSopenharmony_ci			PTHREAD_EXIT(-1);
214f08c3bdfSopenharmony_ci		}
215f08c3bdfSopenharmony_ci		dprt("pid[%d]: do_shmat_shmadt(): content of memory shmat_addr = %s\n", getpid(), shmat_addr);
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci		fprintf(stdout,
218f08c3bdfSopenharmony_ci			"pid[%d]: do_shmat_shmadt(): got shmat address = %#lx\n",
219f08c3bdfSopenharmony_ci			getpid(), (long)shmat_addr);
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_ci		if (args->is_reader) {
222f08c3bdfSopenharmony_ci			/* write character 'Y' to that memory area */
223f08c3bdfSopenharmony_ci			index = 0;
224f08c3bdfSopenharmony_ci			write_to_mem = shmat_addr;
225f08c3bdfSopenharmony_ci			while (index < args->map_size) {
226f08c3bdfSopenharmony_ci				dprt("pid[%d]: do_shmat_shmatd(): write_to_mem = %#x\n", getpid(), write_to_mem);
227f08c3bdfSopenharmony_ci				*write_to_mem = 'Y';
228f08c3bdfSopenharmony_ci				index++;
229f08c3bdfSopenharmony_ci				write_to_mem++;
230f08c3bdfSopenharmony_ci				sched_yield();
231f08c3bdfSopenharmony_ci			}
232f08c3bdfSopenharmony_ci		} else {
233f08c3bdfSopenharmony_ci			/* read from the memory area */
234f08c3bdfSopenharmony_ci			index = 0;
235f08c3bdfSopenharmony_ci			read_from_mem = shmat_addr;
236f08c3bdfSopenharmony_ci			while (index < args->map_size) {
237f08c3bdfSopenharmony_ci				buff = *read_from_mem;
238f08c3bdfSopenharmony_ci				index++;
239f08c3bdfSopenharmony_ci				read_from_mem++;
240f08c3bdfSopenharmony_ci				sched_yield();
241f08c3bdfSopenharmony_ci			}
242f08c3bdfSopenharmony_ci		}
243f08c3bdfSopenharmony_ci
244f08c3bdfSopenharmony_ci		sched_yield();
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci		/* remove the shared memory */
247f08c3bdfSopenharmony_ci		if (rm_shared_mem(shm_id, shmat_addr, 1) == -1) {
248f08c3bdfSopenharmony_ci			fprintf(stderr,
249f08c3bdfSopenharmony_ci				"pid[%d]: do_shmat_shmatd(): rm_shared_mem(): faild to rm id\n",
250f08c3bdfSopenharmony_ci				getpid());
251f08c3bdfSopenharmony_ci			PTHREAD_EXIT(-1);
252f08c3bdfSopenharmony_ci		}
253f08c3bdfSopenharmony_ci	}
254f08c3bdfSopenharmony_ci
255f08c3bdfSopenharmony_ci	PTHREAD_EXIT(0);
256f08c3bdfSopenharmony_ci}
257f08c3bdfSopenharmony_ci
258f08c3bdfSopenharmony_ci/******************************************************************************/
259f08c3bdfSopenharmony_ci/*								 	      */
260f08c3bdfSopenharmony_ci/* Function:	main							      */
261f08c3bdfSopenharmony_ci/*									      */
262f08c3bdfSopenharmony_ci/* Description:	This is the entry point to the program. This function will    */
263f08c3bdfSopenharmony_ci/*		parse the input arguments and set the values accordingly. If  */
264f08c3bdfSopenharmony_ci/*		no arguments (or desired) are provided default values are used*/
265f08c3bdfSopenharmony_ci/*		refer the usage function for the arguments that this program  */
266f08c3bdfSopenharmony_ci/*		takes. It also creates the threads which do most of the dirty */
267f08c3bdfSopenharmony_ci/*		work. If the threads exits with a value '0' the program exits */
268f08c3bdfSopenharmony_ci/*		with success '0' else it exits with failure '-1'.             */
269f08c3bdfSopenharmony_ci/*									      */
270f08c3bdfSopenharmony_ci/* Return:	-1 on failure						      */
271f08c3bdfSopenharmony_ci/*		 0 on success						      */
272f08c3bdfSopenharmony_ci/*									      */
273f08c3bdfSopenharmony_ci/******************************************************************************/
274f08c3bdfSopenharmony_ciint main(int argc,		/* number of input parameters                 */
275f08c3bdfSopenharmony_ci	 char **argv)
276f08c3bdfSopenharmony_ci{				/* pointer to the command line arguments.     */
277f08c3bdfSopenharmony_ci	int c;			/* command line options                       */
278f08c3bdfSopenharmony_ci	int num_thrd = MAXT;	/* number of threads to create                */
279f08c3bdfSopenharmony_ci	int num_reps = MAXR;	/* number of repatitions the test is run      */
280f08c3bdfSopenharmony_ci	int i;
281f08c3bdfSopenharmony_ci	void *th_status;	/* exit status of LWP's                       */
282f08c3bdfSopenharmony_ci	int map_size;		/* size of the file mapped.                   */
283f08c3bdfSopenharmony_ci	int shmkey = 1969;	/* key used to generate shmid by shmget()     */
284f08c3bdfSopenharmony_ci	struct child_args chld_args[30];	/* arguments to the thread function */
285f08c3bdfSopenharmony_ci	char *map_address = NULL;
286f08c3bdfSopenharmony_ci	/* address in memory of the mapped file       */
287f08c3bdfSopenharmony_ci	extern int optopt;	/* options to the program                     */
288f08c3bdfSopenharmony_ci
289f08c3bdfSopenharmony_ci	while ((c = getopt(argc, argv, "hl:t:")) != -1) {
290f08c3bdfSopenharmony_ci		switch (c) {
291f08c3bdfSopenharmony_ci		case 'h':
292f08c3bdfSopenharmony_ci			usage(argv[0]);
293f08c3bdfSopenharmony_ci			break;
294f08c3bdfSopenharmony_ci		case 'l':	/* how many repetitions of the test to exec   */
295f08c3bdfSopenharmony_ci			if ((num_reps = atoi(optarg)) == 0)
296f08c3bdfSopenharmony_ci				OPT_MISSING(argv[0], optopt);
297f08c3bdfSopenharmony_ci			else if (num_reps < 0) {
298f08c3bdfSopenharmony_ci				fprintf(stdout,
299f08c3bdfSopenharmony_ci					"WARNING: bad argument. Using default\n");
300f08c3bdfSopenharmony_ci				num_reps = MAXR;
301f08c3bdfSopenharmony_ci			}
302f08c3bdfSopenharmony_ci			break;
303f08c3bdfSopenharmony_ci		case 't':
304f08c3bdfSopenharmony_ci			if ((num_thrd = atoi(optarg)) == 0)
305f08c3bdfSopenharmony_ci				OPT_MISSING(argv[0], optopt);
306f08c3bdfSopenharmony_ci			else if (num_thrd < 0 || num_thrd > MAXT) {
307f08c3bdfSopenharmony_ci				fprintf(stdout,
308f08c3bdfSopenharmony_ci					"WARNING: bad argument. Using default\n");
309f08c3bdfSopenharmony_ci				num_thrd = MAXT;
310f08c3bdfSopenharmony_ci			}
311f08c3bdfSopenharmony_ci			break;
312f08c3bdfSopenharmony_ci		default:
313f08c3bdfSopenharmony_ci			usage(argv[0]);
314f08c3bdfSopenharmony_ci			break;
315f08c3bdfSopenharmony_ci		}
316f08c3bdfSopenharmony_ci	}
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci	for (i = 0; i < num_thrd; i += 2) {
319f08c3bdfSopenharmony_ci		srand(time(NULL) % 100);
320f08c3bdfSopenharmony_ci		map_size = (1 + (int)(1000.0 * rand() / (RAND_MAX + 1.0))) * 4096;
321f08c3bdfSopenharmony_ci
322f08c3bdfSopenharmony_ci		dprt("main(): thrd_ndx = %d map_address = %#x map_size = %d\n",
323f08c3bdfSopenharmony_ci		     i, map_address, map_size);
324f08c3bdfSopenharmony_ci
325f08c3bdfSopenharmony_ci		chld_args[i].num_reps = num_reps;
326f08c3bdfSopenharmony_ci		chld_args[i].map_size = map_size;
327f08c3bdfSopenharmony_ci		chld_args[i].shmkey = shmkey++;
328f08c3bdfSopenharmony_ci		chld_args[i].is_reader = 0;
329f08c3bdfSopenharmony_ci		if (pthread_create
330f08c3bdfSopenharmony_ci		    (&chld_args[i].threadid, NULL, shmat_rd_wr, &chld_args[i])) {
331f08c3bdfSopenharmony_ci			perror("shmat_rd_wr(): pthread_create()");
332f08c3bdfSopenharmony_ci			exit(-1);
333f08c3bdfSopenharmony_ci		}
334f08c3bdfSopenharmony_ci
335f08c3bdfSopenharmony_ci		chld_args[i + 1] = chld_args[i];
336f08c3bdfSopenharmony_ci		chld_args[i + 1].is_reader = 1;
337f08c3bdfSopenharmony_ci		if (pthread_create
338f08c3bdfSopenharmony_ci		    (&chld_args[i + 1].threadid, NULL, shmat_rd_wr, &chld_args[i + 1])) {
339f08c3bdfSopenharmony_ci			perror("shmat_rd_wr(): pthread_create()");
340f08c3bdfSopenharmony_ci			exit(-1);
341f08c3bdfSopenharmony_ci		}
342f08c3bdfSopenharmony_ci	}
343f08c3bdfSopenharmony_ci
344f08c3bdfSopenharmony_ci	sync();
345f08c3bdfSopenharmony_ci
346f08c3bdfSopenharmony_ci	for (i = 0; i < num_thrd; i++) {
347f08c3bdfSopenharmony_ci		if (pthread_join(chld_args[i].threadid, &th_status) != 0) {
348f08c3bdfSopenharmony_ci			perror("shmat_rd_wr(): pthread_join()");
349f08c3bdfSopenharmony_ci			exit(-1);
350f08c3bdfSopenharmony_ci		} else {
351f08c3bdfSopenharmony_ci			dprt("WE ARE HERE %d\n", __LINE__);
352f08c3bdfSopenharmony_ci			if (th_status == (void *)-1) {
353f08c3bdfSopenharmony_ci				fprintf(stderr,
354f08c3bdfSopenharmony_ci					"thread [%ld] - process exited with errors\n",
355f08c3bdfSopenharmony_ci					(long)chld_args[i].threadid);
356f08c3bdfSopenharmony_ci				exit(-1);
357f08c3bdfSopenharmony_ci			}
358f08c3bdfSopenharmony_ci		}
359f08c3bdfSopenharmony_ci	}
360f08c3bdfSopenharmony_ci	exit(0);
361f08c3bdfSopenharmony_ci}
362