1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2002 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 * NAME 22f08c3bdfSopenharmony_ci * semctl06 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * CALLS 25f08c3bdfSopenharmony_ci * semctl(2) semget(2) semop(2) 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * ALGORITHM 28f08c3bdfSopenharmony_ci * Get and manipulate a set of semaphores. 29f08c3bdfSopenharmony_ci * 30f08c3bdfSopenharmony_ci * RESTRICTIONS 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * WARNING 33f08c3bdfSopenharmony_ci * If this test fail, it may be necessary to use the ipcs and ipcrm 34f08c3bdfSopenharmony_ci * commands to remove any semaphores left in the system due to a 35f08c3bdfSopenharmony_ci * premature exit of this test. 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * HISTORY 38f08c3bdfSopenharmony_ci * 06/30/2001 Port to Linux nsharoff@us.ibm.com 39f08c3bdfSopenharmony_ci * 10/30/2002 Port to LTP dbarrera@us.ibm.com 40f08c3bdfSopenharmony_ci * 12/03/2008 Matthieu Fertré (Matthieu.Fertre@irisa.fr) 41f08c3bdfSopenharmony_ci * - Fix concurrency issue. The IPC keys used for this test could 42f08c3bdfSopenharmony_ci * conflict with keys from another task. 43f08c3bdfSopenharmony_ci */ 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#define DEBUG 0 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci#ifdef UCLINUX 48f08c3bdfSopenharmony_ci#define _GNU_SOURCE 49f08c3bdfSopenharmony_ci#include <stdio.h> 50f08c3bdfSopenharmony_ci#endif 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci#include <sys/types.h> 53f08c3bdfSopenharmony_ci#include <sys/ipc.h> 54f08c3bdfSopenharmony_ci#include <sys/sem.h> 55f08c3bdfSopenharmony_ci#include <unistd.h> 56f08c3bdfSopenharmony_ci#include <errno.h> 57f08c3bdfSopenharmony_ci#include <stdlib.h> 58f08c3bdfSopenharmony_ci#include <signal.h> 59f08c3bdfSopenharmony_ci#include "test.h" 60f08c3bdfSopenharmony_ci#include <sys/wait.h> 61f08c3bdfSopenharmony_ci#include "ipcsem.h" 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ciint local_flag = 1; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci#define NREPS 500 66f08c3bdfSopenharmony_ci#define NPROCS 3 67f08c3bdfSopenharmony_ci#define NKIDS 5 68f08c3bdfSopenharmony_ci#define NSEMS 5 69f08c3bdfSopenharmony_ci#define HVAL 1000 70f08c3bdfSopenharmony_ci#define LVAL 100 71f08c3bdfSopenharmony_ci#define FAILED 0 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_civoid setup(); 74f08c3bdfSopenharmony_civoid cleanup(); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_cistatic key_t keyarray[NPROCS]; 77f08c3bdfSopenharmony_cistatic struct sembuf semops[NSEMS]; 78f08c3bdfSopenharmony_cistatic short maxsemvals[NSEMS]; 79f08c3bdfSopenharmony_cistatic int pidarray[NPROCS]; 80f08c3bdfSopenharmony_cistatic int kidarray[NKIDS]; 81f08c3bdfSopenharmony_cistatic int tid; 82f08c3bdfSopenharmony_cistatic int procstat; 83f08c3bdfSopenharmony_cistatic char *prog; 84f08c3bdfSopenharmony_cistatic unsigned short semvals[NSEMS]; 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_cichar *TCID = "semctl06"; 87f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_cistatic void term(int sig); 90f08c3bdfSopenharmony_cistatic void dosemas(int id); 91f08c3bdfSopenharmony_cistatic void dotest(key_t key); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ciint main(int argc, char **argv) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci register int i, pid; 96f08c3bdfSopenharmony_ci int count, child, status, nwait; 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci tst_parse_opts(argc, argv, NULL, NULL); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci prog = argv[0]; 101f08c3bdfSopenharmony_ci nwait = 0; 102f08c3bdfSopenharmony_ci setup(); 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci tid = -1; 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci for (i = 0; i < NPROCS; i++) 107f08c3bdfSopenharmony_ci keyarray[i] = getipckey(); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci if ((signal(SIGTERM, term)) == SIG_ERR) { 110f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsignal failed. errno = %d", errno); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci } 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci for (i = 0; i < NPROCS; i++) { 115f08c3bdfSopenharmony_ci if ((pid = FORK_OR_VFORK()) < 0) { 116f08c3bdfSopenharmony_ci tst_resm(TFAIL, 117f08c3bdfSopenharmony_ci "\tFork failed (may be OK if under stress)"); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci } 120f08c3bdfSopenharmony_ci if (pid == 0) { 121f08c3bdfSopenharmony_ci procstat = 1; 122f08c3bdfSopenharmony_ci dotest(keyarray[i]); 123f08c3bdfSopenharmony_ci exit(0); 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci pidarray[i] = pid; 126f08c3bdfSopenharmony_ci nwait++; 127f08c3bdfSopenharmony_ci } 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci /* 130f08c3bdfSopenharmony_ci * Wait for children to finish. 131f08c3bdfSopenharmony_ci */ 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci count = 0; 134f08c3bdfSopenharmony_ci while ((child = wait(&status)) > 0) { 135f08c3bdfSopenharmony_ci if (status) { 136f08c3bdfSopenharmony_ci tst_resm(TFAIL, "%s[%d] Test failed. exit=0x%x", prog, 137f08c3bdfSopenharmony_ci child, status); 138f08c3bdfSopenharmony_ci local_flag = FAILED; 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci ++count; 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci /* 144f08c3bdfSopenharmony_ci * Should have collected all children. 145f08c3bdfSopenharmony_ci */ 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci if (count != nwait) { 148f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tWrong # children waited on, count = %d", 149f08c3bdfSopenharmony_ci count); 150f08c3bdfSopenharmony_ci local_flag = FAILED; 151f08c3bdfSopenharmony_ci } 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci if (local_flag != FAILED) 154f08c3bdfSopenharmony_ci tst_resm(TPASS, "semctl06 ran successfully!"); 155f08c3bdfSopenharmony_ci else 156f08c3bdfSopenharmony_ci tst_resm(TFAIL, "semctl06 failed"); 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci cleanup(); 160f08c3bdfSopenharmony_ci tst_exit(); 161f08c3bdfSopenharmony_ci} 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_cistatic void dotest(key_t key) 164f08c3bdfSopenharmony_ci{ 165f08c3bdfSopenharmony_ci int id, pid, status; 166f08c3bdfSopenharmony_ci int count, child, nwait; 167f08c3bdfSopenharmony_ci short i; 168f08c3bdfSopenharmony_ci union semun get_arr; 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci nwait = 0; 171f08c3bdfSopenharmony_ci srand(getpid()); 172f08c3bdfSopenharmony_ci if ((id = semget(key, NSEMS, IPC_CREAT | IPC_EXCL)) < 0) { 173f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsemget() failed errno %d", errno); 174f08c3bdfSopenharmony_ci exit(1); 175f08c3bdfSopenharmony_ci } 176f08c3bdfSopenharmony_ci tid = id; 177f08c3bdfSopenharmony_ci for (i = 0; i < NSEMS; i++) { 178f08c3bdfSopenharmony_ci do { 179f08c3bdfSopenharmony_ci maxsemvals[i] = (short) (rand() % HVAL); 180f08c3bdfSopenharmony_ci } while (maxsemvals[i] < LVAL); 181f08c3bdfSopenharmony_ci semops[i].sem_num = i; 182f08c3bdfSopenharmony_ci semops[i].sem_op = maxsemvals[i]; 183f08c3bdfSopenharmony_ci semops[i].sem_flg = SEM_UNDO; 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci if (semop(id, semops, NSEMS) < 0) { 186f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tfirst semop() failed errno %d", errno); 187f08c3bdfSopenharmony_ci exit(1); 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci for (i = 0; i < NKIDS; i++) { 191f08c3bdfSopenharmony_ci if ((pid = FORK_OR_VFORK()) < 0) { 192f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tfork failed"); 193f08c3bdfSopenharmony_ci } 194f08c3bdfSopenharmony_ci if (pid == 0) 195f08c3bdfSopenharmony_ci dosemas(id); 196f08c3bdfSopenharmony_ci if (pid > 0) { 197f08c3bdfSopenharmony_ci kidarray[i] = pid; 198f08c3bdfSopenharmony_ci nwait++; 199f08c3bdfSopenharmony_ci } 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ci procstat = 2; 203f08c3bdfSopenharmony_ci /* 204f08c3bdfSopenharmony_ci * Wait for children to finish. 205f08c3bdfSopenharmony_ci */ 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci count = 0; 208f08c3bdfSopenharmony_ci while ((child = wait(&status)) > 0) { 209f08c3bdfSopenharmony_ci if (status) { 210f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\t%s:dotest[%d] exited status = 0x%x", 211f08c3bdfSopenharmony_ci prog, child, status); 212f08c3bdfSopenharmony_ci local_flag = FAILED; 213f08c3bdfSopenharmony_ci } 214f08c3bdfSopenharmony_ci ++count; 215f08c3bdfSopenharmony_ci } 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci /* 218f08c3bdfSopenharmony_ci * Should have collected all children. 219f08c3bdfSopenharmony_ci */ 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci if (count != nwait) { 222f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tWrong # children waited on, count = %d", 223f08c3bdfSopenharmony_ci count); 224f08c3bdfSopenharmony_ci local_flag = FAILED; 225f08c3bdfSopenharmony_ci } 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_ci get_arr.array = semvals; 228f08c3bdfSopenharmony_ci if (semctl(id, 0, GETALL, get_arr) < 0) { 229f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\terror on GETALL"); 230f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsemctl() failed errno %d", errno); 231f08c3bdfSopenharmony_ci } 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_ci if (DEBUG) 234f08c3bdfSopenharmony_ci tst_resm(TINFO, "\tchecking maxvals"); 235f08c3bdfSopenharmony_ci for (i = 0; i < NSEMS; i++) { 236f08c3bdfSopenharmony_ci if (semvals[i] != maxsemvals[i]) { 237f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\terror on i %d orig %d final %d", i, 238f08c3bdfSopenharmony_ci semvals[i], maxsemvals[i]); 239f08c3bdfSopenharmony_ci local_flag = FAILED; 240f08c3bdfSopenharmony_ci } 241f08c3bdfSopenharmony_ci } 242f08c3bdfSopenharmony_ci if (DEBUG) 243f08c3bdfSopenharmony_ci tst_resm(TINFO, "\tmaxvals checked"); 244f08c3bdfSopenharmony_ci 245f08c3bdfSopenharmony_ci /* 4th arg must either be missing, or must be of type 'union semun'. 246f08c3bdfSopenharmony_ci * CANNOT just be an int, else it crashes on ppc. 247f08c3bdfSopenharmony_ci */ 248f08c3bdfSopenharmony_ci get_arr.val = 0; 249f08c3bdfSopenharmony_ci if (semctl(id, 0, IPC_RMID, get_arr) < 0) { 250f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsemctl(IPC_RMID) failed errno %d", errno); 251f08c3bdfSopenharmony_ci local_flag = FAILED; 252f08c3bdfSopenharmony_ci } 253f08c3bdfSopenharmony_ci if (local_flag == FAILED) 254f08c3bdfSopenharmony_ci exit(1); 255f08c3bdfSopenharmony_ci} 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_cistatic void dosemas(int id) 258f08c3bdfSopenharmony_ci{ 259f08c3bdfSopenharmony_ci int i, j; 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_ci srand(getpid()); 262f08c3bdfSopenharmony_ci for (i = 0; i < NREPS; i++) { 263f08c3bdfSopenharmony_ci for (j = 0; j < NSEMS; j++) { 264f08c3bdfSopenharmony_ci semops[j].sem_num = j; 265f08c3bdfSopenharmony_ci semops[j].sem_flg = SEM_UNDO; 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci do { 268f08c3bdfSopenharmony_ci semops[j].sem_op = 269f08c3bdfSopenharmony_ci (-(short) (rand() % 270f08c3bdfSopenharmony_ci (maxsemvals[j] / 2))); 271f08c3bdfSopenharmony_ci } while (semops[j].sem_op == 0); 272f08c3bdfSopenharmony_ci } 273f08c3bdfSopenharmony_ci if (semop(id, semops, NSEMS) < 0) { 274f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsemop1 failed errno %d", errno); 275f08c3bdfSopenharmony_ci exit(1); 276f08c3bdfSopenharmony_ci } 277f08c3bdfSopenharmony_ci for (j = 0; j < NSEMS; j++) { 278f08c3bdfSopenharmony_ci semops[j].sem_op = (-semops[j].sem_op); 279f08c3bdfSopenharmony_ci } 280f08c3bdfSopenharmony_ci if (semop(id, semops, NSEMS) < 0) { 281f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsemop2 failed errno %d", errno); 282f08c3bdfSopenharmony_ci exit(1); 283f08c3bdfSopenharmony_ci } 284f08c3bdfSopenharmony_ci } 285f08c3bdfSopenharmony_ci exit(0); 286f08c3bdfSopenharmony_ci} 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_cistatic void term(int sig) 289f08c3bdfSopenharmony_ci{ 290f08c3bdfSopenharmony_ci int i; 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci if ((signal(SIGTERM, term)) == SIG_ERR) { 293f08c3bdfSopenharmony_ci tst_resm(TFAIL, "\tsignal failed. errno %d", errno); 294f08c3bdfSopenharmony_ci exit(1); 295f08c3bdfSopenharmony_ci } 296f08c3bdfSopenharmony_ci if (procstat == 0) { 297f08c3bdfSopenharmony_ci if (DEBUG) 298f08c3bdfSopenharmony_ci tst_resm(TINFO, "\ttest killing kids"); 299f08c3bdfSopenharmony_ci for (i = 0; i < NPROCS; i++) { 300f08c3bdfSopenharmony_ci if (kill(pidarray[i], SIGTERM) != 0) { 301f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Kill error pid = %d :", 302f08c3bdfSopenharmony_ci pidarray[1]); 303f08c3bdfSopenharmony_ci } 304f08c3bdfSopenharmony_ci } 305f08c3bdfSopenharmony_ci if (DEBUG) 306f08c3bdfSopenharmony_ci tst_resm(TINFO, "\ttest kids killed"); 307f08c3bdfSopenharmony_ci return; 308f08c3bdfSopenharmony_ci } 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci if (procstat == 1) { 311f08c3bdfSopenharmony_ci /* 4th arg must either be missing, or must be of type 'union semun'. 312f08c3bdfSopenharmony_ci * CANNOT just be an int, else it crashes on ppc. 313f08c3bdfSopenharmony_ci */ 314f08c3bdfSopenharmony_ci union semun arg; 315f08c3bdfSopenharmony_ci arg.val = 0; 316f08c3bdfSopenharmony_ci (void)semctl(tid, 0, IPC_RMID, arg); 317f08c3bdfSopenharmony_ci exit(1); 318f08c3bdfSopenharmony_ci } 319f08c3bdfSopenharmony_ci 320f08c3bdfSopenharmony_ci if (tid == -1) { 321f08c3bdfSopenharmony_ci exit(1); 322f08c3bdfSopenharmony_ci } 323f08c3bdfSopenharmony_ci for (i = 0; i < NKIDS; i++) { 324f08c3bdfSopenharmony_ci if (kill(kidarray[i], SIGTERM) != 0) { 325f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Kill error kid id = %d :", 326f08c3bdfSopenharmony_ci kidarray[1]); 327f08c3bdfSopenharmony_ci } 328f08c3bdfSopenharmony_ci } 329f08c3bdfSopenharmony_ci} 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_civoid setup(void) 332f08c3bdfSopenharmony_ci{ 333f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 334f08c3bdfSopenharmony_ci 335f08c3bdfSopenharmony_ci TEST_PAUSE; 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci tst_tmpdir(); 338f08c3bdfSopenharmony_ci} 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_civoid cleanup(void) 341f08c3bdfSopenharmony_ci{ 342f08c3bdfSopenharmony_ci tst_rmdir(); 343f08c3bdfSopenharmony_ci} 344