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 63char *TCID = "hugeshmat01"; 64int TST_TOTAL = 3; 65 66#define CASE0 10 /* values to write into the shared */ 67#define CASE1 20 /* memory location. */ 68 69static size_t shm_size; 70static int shm_id_1 = -1; 71static void *addr; 72 73static long hugepages = 128; 74static option_t options[] = { 75 {"s:", &sflag, &nr_opt}, 76 {NULL, NULL, NULL} 77}; 78 79struct 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 98static void check_functionality(int i); 99 100int 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 */ 142static 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 207void 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 231void 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