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:	July - 16 - 2001 Created by Manoj Iyer, IBM Austin TX.	      */
24f08c3bdfSopenharmony_ci/*			         email:manjo@austin.ibm.com		      */
25f08c3bdfSopenharmony_ci/*                                                                            */
26f08c3bdfSopenharmony_ci/*		July - 30 - 2001 Modified - Added function write_to_mem.      */
27f08c3bdfSopenharmony_ci/*							                      */
28f08c3bdfSopenharmony_ci/*              Aug  - 14 - 2001 Modified - Added code to remove the shared   */
29f08c3bdfSopenharmony_ci/*			         memory segment ids.                          */
30f08c3bdfSopenharmony_ci/*							                      */
31f08c3bdfSopenharmony_ci/*              Aug  - 15 - 2001 Modified - Added for loop to run the test    */
32f08c3bdfSopenharmony_ci/*			         repeatedly.                                  */
33f08c3bdfSopenharmony_ci/*                                                                            */
34f08c3bdfSopenharmony_ci/*		Oct  - 22 - 2001 Modified - Fixed bad code in main().         */
35f08c3bdfSopenharmony_ci/*				 removed stray code and options. Pthread_join */
36f08c3bdfSopenharmony_ci/*			         part fixed, older version was completely bad */
37f08c3bdfSopenharmony_ci/*                                                                            */
38f08c3bdfSopenharmony_ci/*		Nov  - 09 - 2001 Modified - Removed compile errors	      */
39f08c3bdfSopenharmony_ci/*				 - added missing header file string.h         */
40f08c3bdfSopenharmony_ci/*				 - removed unused variables.                  */
41f08c3bdfSopenharmony_ci/*				 - made read_ndx and write_ndx static variable*/
42f08c3bdfSopenharmony_ci/*                                                                            */
43f08c3bdfSopenharmony_ci/*		Nov - 91 - 2001	Modified - Changed scope of status variable   */
44f08c3bdfSopenharmony_ci/*				 - change the status of status variable from  */
45f08c3bdfSopenharmony_ci/*				   int *status to int status[1]               */
46f08c3bdfSopenharmony_ci/*                                                                            */
47f08c3bdfSopenharmony_ci/* File:	shmat1.c						      */
48f08c3bdfSopenharmony_ci/*			         					      */
49f08c3bdfSopenharmony_ci/* Description: Test the LINUX memory manager. The program is aimed at        */
50f08c3bdfSopenharmony_ci/*              stressing the memory manager by repeaded shmat/write/read/    */
51f08c3bdfSopenharmony_ci/*		shmatd of file/memory of random size (maximum 1000 * 4096)    */
52f08c3bdfSopenharmony_ci/*		done by multiple processes.				      */
53f08c3bdfSopenharmony_ci/*			         					      */
54f08c3bdfSopenharmony_ci/*		Create a file of random size upto 1000 times 4096. 	      */
55f08c3bdfSopenharmony_ci/*		process X shmats and un-shmats this file in memory.	      */
56f08c3bdfSopenharmony_ci/*		process Y changes content of the file to Y, ie writes to it.  */
57f08c3bdfSopenharmony_ci/*		process Z reads from this memory location, and varifies the   */
58f08c3bdfSopenharmony_ci/*		the content of the file.			              */
59f08c3bdfSopenharmony_ci/*			         					      */
60f08c3bdfSopenharmony_ci/******************************************************************************/
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci/* Include Files							      */
63f08c3bdfSopenharmony_ci#include <stdio.h>		/* definitions for standard I/O               */
64f08c3bdfSopenharmony_ci#include <unistd.h>		/* required by usleep()                       */
65f08c3bdfSopenharmony_ci#include <errno.h>		/* definitions for errno                      */
66f08c3bdfSopenharmony_ci#include <sched.h>		/* definitions for sched_yield()              */
67f08c3bdfSopenharmony_ci#include <stdlib.h>		/* definitions for WEXIT macros               */
68f08c3bdfSopenharmony_ci#include <signal.h>		/* required by sigaction & sig handling fncs  */
69f08c3bdfSopenharmony_ci#include <sys/time.h>		/* definitions of settimer()                  */
70f08c3bdfSopenharmony_ci#include <sys/wait.h>		/* definitions of itimer structure            */
71f08c3bdfSopenharmony_ci#include <pthread.h>		/* definitions for pthread_create etc         */
72f08c3bdfSopenharmony_ci#include <setjmp.h>		/* required by setjmp longjmp                 */
73f08c3bdfSopenharmony_ci#include <sys/ucontext.h>	/* required by the signal handler             */
74f08c3bdfSopenharmony_ci#include <sys/ipc.h>		/* required by shmat shmget etc               */
75f08c3bdfSopenharmony_ci#include <sys/shm.h>		/* required by shmat shmget etc               */
76f08c3bdfSopenharmony_ci#include <string.h>		/* required by strncmp                        */
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci/* Defines								      */
79f08c3bdfSopenharmony_ci#ifndef TRUE
80f08c3bdfSopenharmony_ci#define TRUE 1
81f08c3bdfSopenharmony_ci#endif
82f08c3bdfSopenharmony_ci#ifndef FALSE
83f08c3bdfSopenharmony_ci#define FALSE 0
84f08c3bdfSopenharmony_ci#endif
85f08c3bdfSopenharmony_ci#define prtln() printf(" I AM HERE ==> %s %d\n", __FILE__, __LINE__);
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci#define STR_SHMAT  "  "
88f08c3bdfSopenharmony_ci#define STR_WRITER "    "
89f08c3bdfSopenharmony_ci#define STR_READER "      "
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci/* Global Variables						              */
92f08c3bdfSopenharmony_civoid *map_address;		/* pointer to file in memory                  */
93f08c3bdfSopenharmony_cisigjmp_buf jmpbuf;		/* argument to setjmp and longjmp             */
94f08c3bdfSopenharmony_ciint fsize;			/* size of the file to be created.            */
95f08c3bdfSopenharmony_ciint done_shmat = 0;		/* disallow read and writes before shmat      */
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci/******************************************************************************/
98f08c3bdfSopenharmony_ci/*									      */
99f08c3bdfSopenharmony_ci/* Function:	sig_handler						      */
100f08c3bdfSopenharmony_ci/*									      */
101f08c3bdfSopenharmony_ci/* Description:	handle SIGALRM raised by set_timer(), SIGALRM is raised when  */
102f08c3bdfSopenharmony_ci/*		the timer expires. If any other signal is received exit the   */
103f08c3bdfSopenharmony_ci/*		test.							      */
104f08c3bdfSopenharmony_ci/*									      */
105f08c3bdfSopenharmony_ci/* Input:	signal - signal number, intrested in SIGALRM!		      */
106f08c3bdfSopenharmony_ci/*									      */
107f08c3bdfSopenharmony_ci/* Return:	exit -1 if unexpected signal is received		      */
108f08c3bdfSopenharmony_ci/*		exit 0 if SIGALRM is received			              */
109f08c3bdfSopenharmony_ci/*									      */
110f08c3bdfSopenharmony_ci/******************************************************************************/
111f08c3bdfSopenharmony_cistatic void sig_handler(int signal,	/* signal number, set to handle SIGALRM       */
112f08c3bdfSopenharmony_ci			int code, ucontext_t *ut)
113f08c3bdfSopenharmony_ci{				/* contains pointer to sigcontext structure   */
114f08c3bdfSopenharmony_ci#ifdef __i386__
115f08c3bdfSopenharmony_ci	unsigned long except;	/* exception type.                            */
116f08c3bdfSopenharmony_ci	int ret = 0;		/* exit code from signal handler.             */
117f08c3bdfSopenharmony_ci	struct sigcontext *scp =	/* pointer to sigcontext structure            */
118f08c3bdfSopenharmony_ci	    (struct sigcontext *)&ut->uc_mcontext;
119f08c3bdfSopenharmony_ci#endif
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci	if (signal == SIGALRM) {
122f08c3bdfSopenharmony_ci		fprintf(stdout, "Test ended, success\n");
123f08c3bdfSopenharmony_ci		exit(0);
124f08c3bdfSopenharmony_ci	}
125f08c3bdfSopenharmony_ci#ifdef __i386__
126f08c3bdfSopenharmony_ci	else {
127f08c3bdfSopenharmony_ci		except = scp->trapno;
128f08c3bdfSopenharmony_ci		fprintf(stderr, "signal caught - [%d] ", signal);
129f08c3bdfSopenharmony_ci	}
130f08c3bdfSopenharmony_ci
131f08c3bdfSopenharmony_ci	switch (except) {
132f08c3bdfSopenharmony_ci	case 10:
133f08c3bdfSopenharmony_ci		fprintf(stderr,
134f08c3bdfSopenharmony_ci			"Exception - invalid TSS, exception #[%ld]\n", except);
135f08c3bdfSopenharmony_ci		break;
136f08c3bdfSopenharmony_ci	case 11:
137f08c3bdfSopenharmony_ci		fprintf(stderr,
138f08c3bdfSopenharmony_ci			"Exception - segment not present, exception #[%ld]\n",
139f08c3bdfSopenharmony_ci			except);
140f08c3bdfSopenharmony_ci		break;
141f08c3bdfSopenharmony_ci	case 12:
142f08c3bdfSopenharmony_ci		fprintf(stderr,
143f08c3bdfSopenharmony_ci			"Exception - stack segment not present, exception #[%ld]\n",
144f08c3bdfSopenharmony_ci			except);
145f08c3bdfSopenharmony_ci		break;
146f08c3bdfSopenharmony_ci	case 13:
147f08c3bdfSopenharmony_ci		fprintf(stderr,
148f08c3bdfSopenharmony_ci			"Exception - general protection, exception #[%ld]\n",
149f08c3bdfSopenharmony_ci			except);
150f08c3bdfSopenharmony_ci		break;
151f08c3bdfSopenharmony_ci	case 14:
152f08c3bdfSopenharmony_ci		fprintf(stderr,
153f08c3bdfSopenharmony_ci			"Exception - page fault, exception #[%ld]\n", except);
154f08c3bdfSopenharmony_ci		ret = 1;
155f08c3bdfSopenharmony_ci		break;
156f08c3bdfSopenharmony_ci	default:
157f08c3bdfSopenharmony_ci		fprintf(stderr,
158f08c3bdfSopenharmony_ci			"Exception type not handled... unknown exception #[%ld]\n",
159f08c3bdfSopenharmony_ci			except);
160f08c3bdfSopenharmony_ci		break;
161f08c3bdfSopenharmony_ci	}
162f08c3bdfSopenharmony_ci
163f08c3bdfSopenharmony_ci	if (ret) {
164f08c3bdfSopenharmony_ci		if (scp->edi == (int)map_address) {
165f08c3bdfSopenharmony_ci			fprintf(stdout,
166f08c3bdfSopenharmony_ci				"page fault at [%#lx] - ignore\n", scp->edi);
167f08c3bdfSopenharmony_ci			siglongjmp(jmpbuf, 1);
168f08c3bdfSopenharmony_ci		} else if (scp->esi == (int)map_address) {
169f08c3bdfSopenharmony_ci			fprintf(stdout,
170f08c3bdfSopenharmony_ci				"page fault at [%#lx] - ignore\n", scp->esi);
171f08c3bdfSopenharmony_ci			siglongjmp(jmpbuf, 1);
172f08c3bdfSopenharmony_ci		} else {
173f08c3bdfSopenharmony_ci			fprintf(stderr,
174f08c3bdfSopenharmony_ci				"address at which sigfault occured: [%lx]\n"
175f08c3bdfSopenharmony_ci				"address at which sigfault occured: [%lx]\n"
176f08c3bdfSopenharmony_ci				"address at which memory was shmat: [%p]\n",
177f08c3bdfSopenharmony_ci				(unsigned long)scp->edi,
178f08c3bdfSopenharmony_ci				(unsigned long)scp->esi, map_address);
179f08c3bdfSopenharmony_ci			fprintf(stderr, "bad page fault exit test\n");
180f08c3bdfSopenharmony_ci			exit(-1);
181f08c3bdfSopenharmony_ci		}
182f08c3bdfSopenharmony_ci	} else
183f08c3bdfSopenharmony_ci		exit(-1);
184f08c3bdfSopenharmony_ci#else
185f08c3bdfSopenharmony_ci	fprintf(stderr, "caught signal %d -- exiting.\n", signal);
186f08c3bdfSopenharmony_ci	exit(-1);
187f08c3bdfSopenharmony_ci#endif
188f08c3bdfSopenharmony_ci}
189f08c3bdfSopenharmony_ci
190f08c3bdfSopenharmony_ci										/******************************************************************************//*                                                                            */
191f08c3bdfSopenharmony_ci/* Function:	usage							      */
192f08c3bdfSopenharmony_ci/*									      */
193f08c3bdfSopenharmony_ci/* Description:	Print the usage message.				      */
194f08c3bdfSopenharmony_ci/*									      */
195f08c3bdfSopenharmony_ci/* Return:	exits with -1						      */
196f08c3bdfSopenharmony_ci/*									      */
197f08c3bdfSopenharmony_ci/******************************************************************************/
198f08c3bdfSopenharmony_cistatic void usage(char *progname)
199f08c3bdfSopenharmony_ci{				/* name of this program                       */
200f08c3bdfSopenharmony_ci	fprintf(stderr,
201f08c3bdfSopenharmony_ci		"Usage: %s -h -l -x\n"
202f08c3bdfSopenharmony_ci		"\t -h help, usage message.\n"
203f08c3bdfSopenharmony_ci		"\t -l number of map - write - unmap.    default: 1000\n"
204f08c3bdfSopenharmony_ci		"\t -x time for which test is to be run. default: 24 Hrs\n",
205f08c3bdfSopenharmony_ci		progname);
206f08c3bdfSopenharmony_ci	exit(-1);
207f08c3bdfSopenharmony_ci}
208f08c3bdfSopenharmony_ci
209f08c3bdfSopenharmony_ci/******************************************************************************/
210f08c3bdfSopenharmony_ci/*									      */
211f08c3bdfSopenharmony_ci/* Function:	shmat_shmdt						      */
212f08c3bdfSopenharmony_ci/*									      */
213f08c3bdfSopenharmony_ci/* Description:	Thread X function.					      */
214f08c3bdfSopenharmony_ci/*		shmat a random size file and shm-detach this file, this is    */
215f08c3bdfSopenharmony_ci/*		done for user defined number of times.			      */
216f08c3bdfSopenharmony_ci/*									      */
217f08c3bdfSopenharmony_ci/* Input:	arg[0]		   number of times shmat shmdt is done        */
218f08c3bdfSopenharmony_ci/*									      */
219f08c3bdfSopenharmony_ci/* Return:	-1 on error.				                      */
220f08c3bdfSopenharmony_ci/*               0 on errorless completion of the loop.                       */
221f08c3bdfSopenharmony_ci/*									      */
222f08c3bdfSopenharmony_ci/******************************************************************************/
223f08c3bdfSopenharmony_civoid *shmat_shmdt(void *args)
224f08c3bdfSopenharmony_ci{				/* arguments to the thread X function.          */
225f08c3bdfSopenharmony_ci	int shm_ndx = 0;	/* index to number of shmat/shmdt             */
226f08c3bdfSopenharmony_ci	key_t shmkey = 0;	/* IPC_PRIVATE (key for shmget)               */
227f08c3bdfSopenharmony_ci	int shmid;		/* shared memory id                           */
228f08c3bdfSopenharmony_ci	long *locargs =		/* local pointer to arguments                 */
229f08c3bdfSopenharmony_ci	    (long *)args;
230f08c3bdfSopenharmony_ci
231f08c3bdfSopenharmony_ci	while (shm_ndx++ < (int)locargs[0]) {
232f08c3bdfSopenharmony_ci		/* put the reader and writer threads to sleep                         */
233f08c3bdfSopenharmony_ci		done_shmat = 0;
234f08c3bdfSopenharmony_ci
235f08c3bdfSopenharmony_ci		/* generate a random size, we will ask for this amount of shared mem  */
236f08c3bdfSopenharmony_ci		srand(time(NULL) % 100);
237f08c3bdfSopenharmony_ci		fsize = (1 + (int)(1000.0 * rand() / (RAND_MAX + 1.0))) * 4096;
238f08c3bdfSopenharmony_ci
239f08c3bdfSopenharmony_ci		if ((shmid = shmget(shmkey, fsize, IPC_CREAT | 0666)) == -1) {
240f08c3bdfSopenharmony_ci			perror("shmat_shmdt(): shmget()");
241f08c3bdfSopenharmony_ci			pthread_exit((void *)-1);
242f08c3bdfSopenharmony_ci		} else {
243f08c3bdfSopenharmony_ci			fprintf(stdout,
244f08c3bdfSopenharmony_ci				"%s[%#lx]: shmget(): success, got segment of size %d\n",
245f08c3bdfSopenharmony_ci				STR_SHMAT, pthread_self(), fsize);
246f08c3bdfSopenharmony_ci		}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci		if ((map_address = shmat(shmid, NULL, 0))
249f08c3bdfSopenharmony_ci		    == (void *)-1) {
250f08c3bdfSopenharmony_ci			fprintf(stderr, "shmat_shmat(): map address = %p\n",
251f08c3bdfSopenharmony_ci				map_address);
252f08c3bdfSopenharmony_ci			perror("shmat_shmdt(): shmat()");
253f08c3bdfSopenharmony_ci			pthread_exit((void *)-1);
254f08c3bdfSopenharmony_ci		} else {
255f08c3bdfSopenharmony_ci			/* Wake up the reader and writer threads.                             */
256f08c3bdfSopenharmony_ci			/* Write 'X' into map_address. We are not sure about
257f08c3bdfSopenharmony_ci			   reader/writer interleaving. So the reader may expect
258f08c3bdfSopenharmony_ci			   to find 'X' or 'Y'
259f08c3bdfSopenharmony_ci			 */
260f08c3bdfSopenharmony_ci			memset(map_address, 'X', 1);
261f08c3bdfSopenharmony_ci			done_shmat = 1;
262f08c3bdfSopenharmony_ci			usleep(0);
263f08c3bdfSopenharmony_ci		}
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci		fprintf(stdout, "%s[%#lx]: Map address = %p\n",
266f08c3bdfSopenharmony_ci			STR_SHMAT, pthread_self(), map_address);
267f08c3bdfSopenharmony_ci		fprintf(stdout,
268f08c3bdfSopenharmony_ci			"%s[%#lx]: Num iter: [%d] Total Num Iter: [%d]\n",
269f08c3bdfSopenharmony_ci			STR_SHMAT, pthread_self(), shm_ndx, (int)locargs[0]);
270f08c3bdfSopenharmony_ci		usleep(0);
271f08c3bdfSopenharmony_ci		sched_yield();
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci		/* put the threads to sleep before un-shmatting                       */
274f08c3bdfSopenharmony_ci		done_shmat = 0;
275f08c3bdfSopenharmony_ci		if (shmdt((void *)map_address) == -1) {
276f08c3bdfSopenharmony_ci			perror("shmat_shmdt(): shmdt()");
277f08c3bdfSopenharmony_ci			pthread_exit((void *)-1);
278f08c3bdfSopenharmony_ci		}
279f08c3bdfSopenharmony_ci		if (shmctl(shmid, IPC_RMID, NULL)) {
280f08c3bdfSopenharmony_ci			perror("shmat_shmdt(): shmctl()");
281f08c3bdfSopenharmony_ci			pthread_exit((void *)-1);
282f08c3bdfSopenharmony_ci		}
283f08c3bdfSopenharmony_ci	}
284f08c3bdfSopenharmony_ci	pthread_exit(NULL);
285f08c3bdfSopenharmony_ci}
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci/******************************************************************************/
288f08c3bdfSopenharmony_ci/*									      */
289f08c3bdfSopenharmony_ci/* Function:	write_to_mem						      */
290f08c3bdfSopenharmony_ci/*									      */
291f08c3bdfSopenharmony_ci/* Description:	Thread Y function.					      */
292f08c3bdfSopenharmony_ci/*		Writes 'Y' to the memory location shmat by process X.         */
293f08c3bdfSopenharmony_ci/*									      */
294f08c3bdfSopenharmony_ci/* Input:	arg[0]		   number of times write is performed         */
295f08c3bdfSopenharmony_ci/*									      */
296f08c3bdfSopenharmony_ci/* Return:	-1 on error.				                      */
297f08c3bdfSopenharmony_ci/*               0 on errorless completion of the loop.                       */
298f08c3bdfSopenharmony_ci/*									      */
299f08c3bdfSopenharmony_ci/******************************************************************************/
300f08c3bdfSopenharmony_civoid *write_to_mem(void *args)
301f08c3bdfSopenharmony_ci{
302f08c3bdfSopenharmony_ci	static int write_ndx = 0;	/* index to the number of writes to perform   */
303f08c3bdfSopenharmony_ci	long *locargs =		/* local pointer to the arguments             */
304f08c3bdfSopenharmony_ci	    (long *)args;
305f08c3bdfSopenharmony_ci
306f08c3bdfSopenharmony_ci	while (write_ndx++ < (int)locargs[0]) {
307f08c3bdfSopenharmony_ci		/* wait for the thread to shmat, and dont sleep on the processor. */
308f08c3bdfSopenharmony_ci		while (!done_shmat)
309f08c3bdfSopenharmony_ci			usleep(0);
310f08c3bdfSopenharmony_ci
311f08c3bdfSopenharmony_ci		if (sigsetjmp(jmpbuf, 1) == 1) {
312f08c3bdfSopenharmony_ci			fprintf(stdout,
313f08c3bdfSopenharmony_ci				"page fault ocurred due a write after an shmdt from [%p]\n",
314f08c3bdfSopenharmony_ci				map_address);
315f08c3bdfSopenharmony_ci		}
316f08c3bdfSopenharmony_ci
317f08c3bdfSopenharmony_ci		fprintf(stdout,
318f08c3bdfSopenharmony_ci			"%s[%#lx]: write_to_mem(): memory address: [%p]\n",
319f08c3bdfSopenharmony_ci			STR_WRITER, pthread_self(), map_address);
320f08c3bdfSopenharmony_ci		memset(map_address, 'Y', 1);
321f08c3bdfSopenharmony_ci		usleep(1);
322f08c3bdfSopenharmony_ci		sched_yield();
323f08c3bdfSopenharmony_ci	}
324f08c3bdfSopenharmony_ci	pthread_exit(NULL);
325f08c3bdfSopenharmony_ci}
326f08c3bdfSopenharmony_ci
327f08c3bdfSopenharmony_ci/******************************************************************************/
328f08c3bdfSopenharmony_ci/*									      */
329f08c3bdfSopenharmony_ci/* Function:	read_from_mem						      */
330f08c3bdfSopenharmony_ci/*									      */
331f08c3bdfSopenharmony_ci/* Description:	Thread Z function.					      */
332f08c3bdfSopenharmony_ci/*		reads from the memory location shmat by process X.            */
333f08c3bdfSopenharmony_ci/*									      */
334f08c3bdfSopenharmony_ci/* Input:	arg[0]		   number of times read is performed          */
335f08c3bdfSopenharmony_ci/*									      */
336f08c3bdfSopenharmony_ci/* Return:	-1 on error.				                      */
337f08c3bdfSopenharmony_ci/*               0 on errorless completion of the loop.                       */
338f08c3bdfSopenharmony_ci/*									      */
339f08c3bdfSopenharmony_ci/******************************************************************************/
340f08c3bdfSopenharmony_civoid *read_from_mem(void *args)
341f08c3bdfSopenharmony_ci{
342f08c3bdfSopenharmony_ci	static int read_ndx = 0;	/* index to the number of writes to perform   */
343f08c3bdfSopenharmony_ci	long *locargs =		/* local pointer to the arguments             */
344f08c3bdfSopenharmony_ci	    (long *)args;
345f08c3bdfSopenharmony_ci
346f08c3bdfSopenharmony_ci	while (read_ndx++ < (int)locargs[0]) {
347f08c3bdfSopenharmony_ci		/* wait for the shmat to happen */
348f08c3bdfSopenharmony_ci		while (!done_shmat)
349f08c3bdfSopenharmony_ci			usleep(0);
350f08c3bdfSopenharmony_ci
351f08c3bdfSopenharmony_ci		fprintf(stdout,
352f08c3bdfSopenharmony_ci			"%s[%#lx]: read_from_mem():  memory address: [%p]\n",
353f08c3bdfSopenharmony_ci			STR_READER, pthread_self(), map_address);
354f08c3bdfSopenharmony_ci		if (sigsetjmp(jmpbuf, 1) == 1) {
355f08c3bdfSopenharmony_ci			fprintf(stdout,
356f08c3bdfSopenharmony_ci				"page fault ocurred due a read after an shmdt from %p\n",
357f08c3bdfSopenharmony_ci				map_address);
358f08c3bdfSopenharmony_ci		}
359f08c3bdfSopenharmony_ci
360f08c3bdfSopenharmony_ci		fprintf(stdout, "%s[%#lx]: read_mem(): content of memory: %s\n",
361f08c3bdfSopenharmony_ci			STR_READER, pthread_self(), (char *)map_address);
362f08c3bdfSopenharmony_ci
363f08c3bdfSopenharmony_ci		if (strncmp(map_address, "Y", 1) != 0) {
364f08c3bdfSopenharmony_ci			if (strncmp(map_address, "X", 1) != 0) {
365f08c3bdfSopenharmony_ci				pthread_exit((void *)-1);
366f08c3bdfSopenharmony_ci			}
367f08c3bdfSopenharmony_ci		}
368f08c3bdfSopenharmony_ci		usleep(1);
369f08c3bdfSopenharmony_ci		sched_yield();
370f08c3bdfSopenharmony_ci	}
371f08c3bdfSopenharmony_ci	pthread_exit(NULL);
372f08c3bdfSopenharmony_ci}
373f08c3bdfSopenharmony_ci
374f08c3bdfSopenharmony_ci/******************************************************************************/
375f08c3bdfSopenharmony_ci/*                                                                            */
376f08c3bdfSopenharmony_ci/* Function:    main                                                          */
377f08c3bdfSopenharmony_ci/*                                                                            */
378f08c3bdfSopenharmony_ci/* Descrption:	Create a large file of size up to a  Giga Bytes.  write to it */
379f08c3bdfSopenharmony_ci/*		lower case alphabet 'a'. Map the file and change the contents */
380f08c3bdfSopenharmony_ci/*		to 'A's (upper case alphabet), write the contents to the file,*/
381f08c3bdfSopenharmony_ci/*		and unmap the file from memory. Spwan a certian number of     */
382f08c3bdfSopenharmony_ci/*		LWP's that will do the above.                                 */
383f08c3bdfSopenharmony_ci/*                                                                            */
384f08c3bdfSopenharmony_ci/* Return:	exits with -1 on error					      */
385f08c3bdfSopenharmony_ci/*		exits with a 0 on success.				      */
386f08c3bdfSopenharmony_ci/*                                                                            */
387f08c3bdfSopenharmony_ci/******************************************************************************/
388f08c3bdfSopenharmony_ciint main(int argc,		/* number of input parameters.                        */
389f08c3bdfSopenharmony_ci	 char **argv)
390f08c3bdfSopenharmony_ci{				/* pointer to the command line arguments.       */
391f08c3bdfSopenharmony_ci	int c;			/* command line options                       */
392f08c3bdfSopenharmony_ci	int num_iter;		/* number of iteration to perform             */
393f08c3bdfSopenharmony_ci	int thrd_ndx;		/* index into the array of threads.           */
394f08c3bdfSopenharmony_ci	double exec_time;	/* period for which the test is executed      */
395f08c3bdfSopenharmony_ci	void *status;		/* exit status for light weight process       */
396f08c3bdfSopenharmony_ci	int sig_ndx;		/* index into signal handler structure.       */
397f08c3bdfSopenharmony_ci	pthread_t thid[1000];	/* pids of process that will map/write/unmap  */
398f08c3bdfSopenharmony_ci	long chld_args[3];	/* arguments to funcs execed by child process */
399f08c3bdfSopenharmony_ci	extern char *optarg;	/* arguments passed to each option            */
400f08c3bdfSopenharmony_ci	struct sigaction sigptr;	/* set up signal, for interval timer          */
401f08c3bdfSopenharmony_ci
402f08c3bdfSopenharmony_ci	static struct signal_info {
403f08c3bdfSopenharmony_ci		int signum;	/* signal number that hasto be handled                */
404f08c3bdfSopenharmony_ci		char *signame;	/* name of the signal to be handled.                  */
405f08c3bdfSopenharmony_ci	} sig_info[] = {
406f08c3bdfSopenharmony_ci		{
407f08c3bdfSopenharmony_ci		SIGHUP, "SIGHUP"}, {
408f08c3bdfSopenharmony_ci		SIGINT, "SIGINT"}, {
409f08c3bdfSopenharmony_ci		SIGQUIT, "SIGQUIT"}, {
410f08c3bdfSopenharmony_ci		SIGABRT, "SIGABRT"}, {
411f08c3bdfSopenharmony_ci		SIGBUS, "SIGBUS"}, {
412f08c3bdfSopenharmony_ci		SIGSEGV, "SIGSEGV"}, {
413f08c3bdfSopenharmony_ci		SIGALRM, "SIGALRM"}, {
414f08c3bdfSopenharmony_ci		SIGUSR1, "SIGUSR1"}, {
415f08c3bdfSopenharmony_ci		SIGUSR2, "SIGUSR2"}, {
416f08c3bdfSopenharmony_ci		-1, "ENDSIG"}
417f08c3bdfSopenharmony_ci	};
418f08c3bdfSopenharmony_ci
419f08c3bdfSopenharmony_ci	/* set up the default values */
420f08c3bdfSopenharmony_ci	num_iter = 1000;	/* repeate map - write - unmap operation 1000 times   */
421f08c3bdfSopenharmony_ci	exec_time = 24.0;	/* minimum time period for which to run the tests     */
422f08c3bdfSopenharmony_ci
423f08c3bdfSopenharmony_ci	while ((c = getopt(argc, argv, "h:l:x:")) != -1) {
424f08c3bdfSopenharmony_ci		switch (c) {
425f08c3bdfSopenharmony_ci		case 'h':
426f08c3bdfSopenharmony_ci			usage(argv[0]);
427f08c3bdfSopenharmony_ci			break;
428f08c3bdfSopenharmony_ci		case 'l':	/* number of times to loop in the thread function     */
429f08c3bdfSopenharmony_ci			if ((num_iter = atoi(optarg)) == 0)
430f08c3bdfSopenharmony_ci				num_iter = 1000;
431f08c3bdfSopenharmony_ci			break;
432f08c3bdfSopenharmony_ci		case 'x':	/* time in hrs to run this test.                      */
433f08c3bdfSopenharmony_ci			if ((exec_time = atof(optarg)) == 0)
434f08c3bdfSopenharmony_ci				exec_time = 24;
435f08c3bdfSopenharmony_ci			break;
436f08c3bdfSopenharmony_ci		default:
437f08c3bdfSopenharmony_ci			usage(argv[0]);
438f08c3bdfSopenharmony_ci			break;
439f08c3bdfSopenharmony_ci		}
440f08c3bdfSopenharmony_ci	}
441f08c3bdfSopenharmony_ci
442f08c3bdfSopenharmony_ci	fprintf(stdout,
443f08c3bdfSopenharmony_ci		"\n\n\nTest is set to run with the following parameters:\n"
444f08c3bdfSopenharmony_ci		"\tDuration of test: [%f]hrs\n"
445f08c3bdfSopenharmony_ci		"\tnumber of shmat  shm detach: [%d]\n", exec_time, num_iter);
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_ci	/* set up signals */
448f08c3bdfSopenharmony_ci	sigptr.sa_handler = (void (*)(int signal))sig_handler;
449f08c3bdfSopenharmony_ci	sigfillset(&sigptr.sa_mask);
450f08c3bdfSopenharmony_ci	sigptr.sa_flags = SA_SIGINFO;
451f08c3bdfSopenharmony_ci	for (sig_ndx = 0; sig_info[sig_ndx].signum != -1; sig_ndx++) {
452f08c3bdfSopenharmony_ci		sigaddset(&sigptr.sa_mask, sig_info[sig_ndx].signum);
453f08c3bdfSopenharmony_ci		if (sigaction(sig_info[sig_ndx].signum, &sigptr,
454f08c3bdfSopenharmony_ci			      NULL) == -1) {
455f08c3bdfSopenharmony_ci			perror("man(): sigaction()");
456f08c3bdfSopenharmony_ci			fprintf(stderr,
457f08c3bdfSopenharmony_ci				"could not set handler for SIGALRM, errno = %d\n",
458f08c3bdfSopenharmony_ci				errno);
459f08c3bdfSopenharmony_ci			exit(-1);
460f08c3bdfSopenharmony_ci		}
461f08c3bdfSopenharmony_ci	}
462f08c3bdfSopenharmony_ci
463f08c3bdfSopenharmony_ci	chld_args[0] = num_iter;
464f08c3bdfSopenharmony_ci	alarm(exec_time * 3600.00);
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci	for (;;) {
467f08c3bdfSopenharmony_ci		/* create 3 threads */
468f08c3bdfSopenharmony_ci		if (pthread_create(&thid[0], NULL, shmat_shmdt, chld_args)) {
469f08c3bdfSopenharmony_ci			perror("main(): pthread_create()");
470f08c3bdfSopenharmony_ci			exit(-1);
471f08c3bdfSopenharmony_ci		} else {
472f08c3bdfSopenharmony_ci			fprintf(stdout,
473f08c3bdfSopenharmony_ci				"created thread id[%#lx], execs fn shmat_shmdt()\n",
474f08c3bdfSopenharmony_ci				thid[0]);
475f08c3bdfSopenharmony_ci		}
476f08c3bdfSopenharmony_ci		sched_yield();
477f08c3bdfSopenharmony_ci
478f08c3bdfSopenharmony_ci		if (pthread_create(&thid[1], NULL, write_to_mem, chld_args)) {
479f08c3bdfSopenharmony_ci			perror("main(): pthread_create()");
480f08c3bdfSopenharmony_ci			exit(-1);
481f08c3bdfSopenharmony_ci		} else {
482f08c3bdfSopenharmony_ci			fprintf(stdout,
483f08c3bdfSopenharmony_ci				"created thread id[%#lx], execs fn write_to_mem()\n",
484f08c3bdfSopenharmony_ci				thid[1]);
485f08c3bdfSopenharmony_ci		}
486f08c3bdfSopenharmony_ci		sched_yield();
487f08c3bdfSopenharmony_ci
488f08c3bdfSopenharmony_ci		if (pthread_create(&thid[2], NULL, read_from_mem, chld_args)) {
489f08c3bdfSopenharmony_ci			perror("main(): pthread_create()");
490f08c3bdfSopenharmony_ci			exit(-1);
491f08c3bdfSopenharmony_ci		} else {
492f08c3bdfSopenharmony_ci			fprintf(stdout,
493f08c3bdfSopenharmony_ci				"created thread id[%#lx], execs fn read_from_mem()\n",
494f08c3bdfSopenharmony_ci				thid[2]);
495f08c3bdfSopenharmony_ci		}
496f08c3bdfSopenharmony_ci		sched_yield();
497f08c3bdfSopenharmony_ci
498f08c3bdfSopenharmony_ci		/* wait for the children to terminate */
499f08c3bdfSopenharmony_ci		for (thrd_ndx = 0; thrd_ndx < 3; thrd_ndx++) {
500f08c3bdfSopenharmony_ci			if (pthread_join(thid[thrd_ndx], &status)) {
501f08c3bdfSopenharmony_ci				perror("main(): pthread_create()");
502f08c3bdfSopenharmony_ci				exit(-1);
503f08c3bdfSopenharmony_ci			}
504f08c3bdfSopenharmony_ci			if (status == (void *)-1) {
505f08c3bdfSopenharmony_ci				fprintf(stderr,
506f08c3bdfSopenharmony_ci					"thread [%#lx] - process exited with errors %ld\n",
507f08c3bdfSopenharmony_ci					thid[thrd_ndx], (long)status);
508f08c3bdfSopenharmony_ci				exit(-1);
509f08c3bdfSopenharmony_ci			}
510f08c3bdfSopenharmony_ci		}
511f08c3bdfSopenharmony_ci	}
512f08c3bdfSopenharmony_ci	fprintf(stdout, "TEST PASSED\n");
513f08c3bdfSopenharmony_ci	return 0;
514f08c3bdfSopenharmony_ci}
515