• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
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 /*
21  * NAME
22  *	hugeshmat01.c
23  *
24  * DESCRIPTION
25  *	hugeshmat01 - test that shmat() works correctly
26  *
27  * ALGORITHM
28  *	create a large shared memory resouce with read/write permissions
29  *	loop if that option was specified
30  *	call shmat() with the TEST() macro using three valid conditions
31  *	check the return code
32  *	  if failure, issue a FAIL message.
33  *	otherwise,
34  *	  if doing functionality testing
35  *		check for the correct conditions after the call
36  *		if correct,
37  *			issue a PASS message
38  *		otherwise
39  *			issue a FAIL message
40  *	call cleanup
41  *
42  * USAGE:  <for command-line>
43  *  hugeshmat01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
44  *     where,  -c n : Run n copies concurrently.
45  *             -f   : Turn off functionality Testing.
46  *	       -i n : Execute test n times.
47  *	       -I x : Execute test for x seconds.
48  *	       -P x : Pause for x seconds between iterations.
49  *	       -t   : Turn on syscall timing.
50  *
51  * HISTORY
52  *	03/2001 - Written by Wayne Boyer
53  *	04/2004 - Updated by Robbie Williamson
54  *
55  * RESTRICTIONS
56  *	none
57  */
58 
59 #include "hugetlb.h"
60 #include "safe_macros.h"
61 #include "mem.h"
62 
63 char *TCID = "hugeshmat01";
64 int TST_TOTAL = 3;
65 
66 #define CASE0		10	/* values to write into the shared */
67 #define CASE1		20	/* memory location.                */
68 
69 static size_t shm_size;
70 static int shm_id_1 = -1;
71 static void *addr;
72 
73 static long hugepages = 128;
74 static option_t options[] = {
75 	{"s:", &sflag, &nr_opt},
76 	{NULL, NULL, NULL}
77 };
78 
79 struct test_case_t {
80 	int *shmid;
81 	void *addr;
82 	int flags;
83 } TC[] = {
84 	/* a straight forward read/write attach */
85 	{
86 	&shm_id_1, 0, 0},
87 	    /*
88 	     * an attach using non aligned memory
89 	     * -1 will be replaced with an unaligned addr
90 	     */
91 	{
92 	&shm_id_1, (void *)-1, SHM_RND},
93 	    /* a read only attach */
94 	{
95 	&shm_id_1, 0, SHM_RDONLY}
96 };
97 
98 static void check_functionality(int i);
99 
main(int ac,char ** av)100 int main(int ac, char **av)
101 {
102 	int lc, i;
103 
104 	tst_parse_opts(ac, av, options, NULL);
105 
106 	if (sflag)
107 		hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX);
108 
109 	setup();
110 
111 	for (lc = 0; TEST_LOOPING(lc); lc++) {
112 		tst_count = 0;
113 
114 		for (i = 0; i < TST_TOTAL; i++) {
115 			addr = shmat(*(TC[i].shmid), TC[i].addr, TC[i].flags);
116 			if (addr == (void *)-1) {
117 				tst_brkm(TFAIL | TERRNO, cleanup, "shmat");
118 			} else {
119 				check_functionality(i);
120 			}
121 
122 			/*
123 			 * addr in TC[0] will be used to generate an unaligned
124 			 * address for TC[1]
125 			 */
126 			if (i == 0 && addr != (void *)-1)
127 				TC[1].addr = (void *)(((unsigned long)addr &
128 						       ~(SHMLBA - 1)) + SHMLBA -
129 						      1);
130 			if (shmdt(addr) == -1)
131 				tst_brkm(TBROK | TERRNO, cleanup, "shmdt");
132 		}
133 	}
134 	cleanup();
135 	tst_exit();
136 }
137 
138 /*
139  * check_functionality - check various conditions to make sure they
140  *			 are correct.
141  */
check_functionality(int i)142 static void check_functionality(int i)
143 {
144 	void *orig_add;
145 	int *shared;
146 	struct shmid_ds buf;
147 
148 	shared = (int *)addr;
149 
150 	/* stat the shared memory ID */
151 	if (shmctl(shm_id_1, IPC_STAT, &buf) == -1)
152 		tst_brkm(TBROK | TERRNO, cleanup, "shmctl");
153 
154 	/* check the number of attaches */
155 	if (buf.shm_nattch != 1) {
156 		tst_resm(TFAIL, "# of attaches is incorrect");
157 		return;
158 	}
159 
160 	/* check the size of the segment */
161 	if (buf.shm_segsz != shm_size) {
162 		tst_resm(TFAIL, "segment size is incorrect");
163 		return;
164 	}
165 
166 	/* check for specific conditions depending on the type of attach */
167 	switch (i) {
168 	case 0:
169 		/*
170 		 * Check the functionality of the first call by simply
171 		 * "writing" a value to the shared memory space.
172 		 * If this fails the program will get a SIGSEGV, dump
173 		 * core and exit.
174 		 */
175 		*shared = CASE0;
176 		break;
177 	case 1:
178 		/*
179 		 * Check the functionality of the second call by writing
180 		 * a value to the shared memory space and then checking
181 		 * that the original address given was rounded down as
182 		 * specified in the man page.
183 		 */
184 		*shared = CASE1;
185 		orig_add = addr + ((unsigned long)TC[i].addr % SHMLBA);
186 		if (orig_add != TC[i].addr) {
187 			tst_resm(TFAIL, "shared memory address is not "
188 				 "correct");
189 			return;
190 		}
191 		break;
192 	case 2:
193 		/*
194 		 * This time the shared memory is read only.  Read the value
195 		 * and check that it is equal to the value set in case #2,
196 		 * because shared memory is persistent.
197 		 */
198 		if (*shared != CASE1) {
199 			tst_resm(TFAIL, "shared memory value isn't correct");
200 			return;
201 		}
202 		break;
203 	}
204 	tst_resm(TPASS, "conditions and functionality are correct");
205 }
206 
setup(void)207 void setup(void)
208 {
209 	long hpage_size;
210 
211 	tst_require_root();
212 	check_hugepage();
213 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
214 	tst_tmpdir();
215 
216 	orig_hugepages = get_sys_tune("nr_hugepages");
217 	set_sys_tune("nr_hugepages", hugepages, 1);
218 	hpage_size = read_meminfo("Hugepagesize:") * 1024;
219 
220 	shm_size = hpage_size * hugepages / 2;
221 	update_shm_size(&shm_size);
222 	shmkey = getipckey(cleanup);
223 	shm_id_1 = shmget(shmkey++, shm_size,
224 			  SHM_HUGETLB | SHM_RW | IPC_CREAT | IPC_EXCL);
225 	if (shm_id_1 == -1)
226 		tst_brkm(TBROK | TERRNO, cleanup, "shmget");
227 
228 	TEST_PAUSE;
229 }
230 
cleanup(void)231 void cleanup(void)
232 {
233 	rm_shm(shm_id_1);
234 
235 	set_sys_tune("nr_hugepages", orig_hugepages, 0);
236 
237 	tst_rmdir();
238 }
239