1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * NAME 21 * shmat01.c 22 * 23 * DESCRIPTION 24 * shmat01 - test that shmat() works correctly 25 * 26 * ALGORITHM 27 * create a shared memory resouce with read/write permissions 28 * loop if that option was specified 29 * call shmat() with the TEST() macro using three valid conditions 30 * check the return code 31 * if failure, issue a FAIL message. 32 * otherwise, 33 * if doing functionality testing 34 * check for the correct conditions after the call 35 * if correct, 36 * issue a PASS message 37 * otherwise 38 * issue a FAIL message 39 * call cleanup 40 */ 41 42 #include "ipcshm.h" 43 #include "shmat_common.h" 44 45 #define CASE0 10 46 #define CASE1 20 47 48 char *TCID = "shmat01"; 49 int TST_TOTAL = 4; 50 51 int shm_id_1 = -1; 52 53 /* 54 * By probing this address first, we can make 55 * non-aligned addresses from it for different 56 * architectures without explicitly code it. 57 */ 58 void *base_addr; 59 void *addr; 60 61 static struct test_case_t { 62 int *shmid; 63 int offset; 64 int flags; 65 int getbase; 66 } *TC; 67 68 static void check_functionality(int); 69 70 int main(int argc, char *argv[]) 71 { 72 int lc, i; 73 void *attchaddr; 74 75 tst_parse_opts(argc, argv, NULL, NULL); 76 77 setup(); 78 79 for (lc = 0; TEST_LOOPING(lc); lc++) { 80 81 tst_count = 0; 82 83 for (i = 0; i < TST_TOTAL; i++) { 84 85 if (TC[i].getbase) { 86 base_addr = probe_free_addr(); 87 attchaddr = base_addr + TC[i].offset; 88 } else { 89 attchaddr = NULL; 90 } 91 92 addr = shmat(*(TC[i].shmid), attchaddr, TC[i].flags); 93 94 TEST_ERRNO = errno; 95 if (addr == (void *)-1) { 96 tst_brkm(TFAIL | TTERRNO, cleanup, 97 "shmat call failed"); 98 } else { 99 check_functionality(i); 100 } 101 102 if (shmdt(addr) == -1) 103 tst_brkm(TBROK, cleanup, 104 "Couldn't detach shared memory"); 105 } 106 } 107 108 cleanup(); 109 110 tst_exit(); 111 } 112 113 /* 114 * check_functionality - check various conditions to make sure they 115 * are correct. 116 */ 117 static void check_functionality(int i) 118 { 119 void *orig_add; 120 int *shared; 121 int fail = 0; 122 struct shmid_ds buf; 123 124 shared = (int *)addr; 125 126 /* stat the shared memory ID */ 127 if (shmctl(shm_id_1, IPC_STAT, &buf) == -1) 128 tst_brkm(TBROK, cleanup, "couldn't stat shared memory"); 129 130 /* check the number of attaches */ 131 if (buf.shm_nattch != 1) { 132 tst_resm(TFAIL, "# of attaches is incorrect"); 133 return; 134 } 135 136 /* check the size of the segment */ 137 if (buf.shm_segsz != INT_SIZE) { 138 tst_resm(TFAIL, "segment size is incorrect"); 139 return; 140 } 141 142 /* check for specific conditions depending on the type of attach */ 143 switch (i) { 144 case 0: 145 case 1: 146 /* 147 * Check the functionality of shmat by simply "writing" 148 * a value to the shared memory space. 149 * If this fails the program will get a SIGSEGV, dump 150 * core and exit. 151 */ 152 153 *shared = CASE0; 154 break; 155 case 2: 156 /* 157 * Check the functionality of shmat by writing a value 158 * to the shared memory space and then checking that 159 * the original address given was rounded down as 160 * specified in the man page. 161 */ 162 163 *shared = CASE1; 164 orig_add = addr + ((unsigned long)TC[2].offset % SHMLBA); 165 if (orig_add != base_addr + TC[2].offset) { 166 tst_resm(TFAIL, "shared memory address is not " 167 "correct"); 168 fail = 1; 169 } 170 break; 171 case 3: 172 /* 173 * This time the shared memory is read only. Read the value 174 * and check that it is equal to the value set in last case, 175 * because shared memory is persistent. 176 */ 177 178 if (*shared != CASE1) { 179 tst_resm(TFAIL, "shared memory value isn't correct"); 180 fail = 1; 181 } 182 break; 183 } 184 185 if (!fail) 186 tst_resm(TPASS, "conditions and functionality are correct"); 187 } 188 189 void setup(void) 190 { 191 tst_sig(NOFORK, DEF_HANDLER, cleanup); 192 193 TEST_PAUSE; 194 195 TC = malloc(TST_TOTAL * sizeof(struct test_case_t)); 196 if (TC == NULL) 197 tst_brkm(TFAIL | TERRNO, cleanup, "failed to allocate memory"); 198 199 /* set NULL as attaching address*/ 200 TC[0].shmid = &shm_id_1; 201 TC[0].offset = 0; 202 TC[0].flags = 0; 203 TC[0].getbase = 0; 204 205 /* a straight forward read/write attach */ 206 TC[1].shmid = &shm_id_1; 207 TC[1].offset = 0; 208 TC[1].flags = 0; 209 TC[1].getbase = 1; 210 211 /* an attach using unaligned memory */ 212 TC[2].shmid = &shm_id_1; 213 TC[2].offset = SHMLBA - 1; 214 TC[2].flags = SHM_RND; 215 TC[2].getbase = 1; 216 217 /* a read only attach */ 218 TC[3].shmid = &shm_id_1; 219 TC[3].offset = 0; 220 TC[3].flags = SHM_RDONLY; 221 TC[3].getbase = 1; 222 223 tst_tmpdir(); 224 225 shmkey = getipckey(); 226 227 shm_id_1 = shmget(shmkey++, INT_SIZE, SHM_RW | IPC_CREAT | IPC_EXCL); 228 if (shm_id_1 == -1) 229 tst_brkm(TBROK, cleanup, "Failed to create shared memory " 230 "resource 1 in setup()"); 231 } 232 233 void cleanup(void) 234 { 235 rm_shm(shm_id_1); 236 237 if (TC != NULL) 238 free(TC); 239 240 tst_rmdir(); 241 } 242