1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci/*\ 6f08c3bdfSopenharmony_ci * [Description] 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * Test the 13 possible semctl() commands 9f08c3bdfSopenharmony_ci */ 10f08c3bdfSopenharmony_ci 11f08c3bdfSopenharmony_ci#define _GNU_SOURCE 12f08c3bdfSopenharmony_ci#include <stdlib.h> 13f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h" 14f08c3bdfSopenharmony_ci#include "tst_test.h" 15f08c3bdfSopenharmony_ci#include "lapi/sem.h" 16f08c3bdfSopenharmony_ci#include "libnewipc.h" 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#define INCVAL 2 19f08c3bdfSopenharmony_ci#define NEWMODE 066 20f08c3bdfSopenharmony_ci#define NCHILD 5 21f08c3bdfSopenharmony_ci#define SEMUN_CAST (union semun) 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic int sem_id = -1; 24f08c3bdfSopenharmony_cistatic int sem_index; 25f08c3bdfSopenharmony_cistatic struct semid_ds buf; 26f08c3bdfSopenharmony_cistatic struct seminfo ipc_buf; 27f08c3bdfSopenharmony_cistatic unsigned short array[PSEMS]; 28f08c3bdfSopenharmony_cistatic struct sembuf sops; 29f08c3bdfSopenharmony_cistatic int pid_arr[NCHILD]; 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_cistatic void kill_all_children(void) 32f08c3bdfSopenharmony_ci{ 33f08c3bdfSopenharmony_ci int j; 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci for (j = 0; j < NCHILD; j++) 36f08c3bdfSopenharmony_ci SAFE_KILL(pid_arr[j], SIGKILL); 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci for (j = 0; j < NCHILD; j++) 39f08c3bdfSopenharmony_ci SAFE_WAIT(NULL); 40f08c3bdfSopenharmony_ci} 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cistatic void func_stat(void) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci if (buf.sem_nsems == PSEMS && buf.sem_perm.mode == (SEM_RA)) 45f08c3bdfSopenharmony_ci tst_res(TPASS, "buf.sem_nsems and buf.sem_perm.mode are correct"); 46f08c3bdfSopenharmony_ci else 47f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore STAT info is incorrect"); 48f08c3bdfSopenharmony_ci} 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic void set_setup(void) 51f08c3bdfSopenharmony_ci{ 52f08c3bdfSopenharmony_ci buf.sem_perm.mode = SEM_RA | NEWMODE; 53f08c3bdfSopenharmony_ci} 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistatic void func_set(void) 56f08c3bdfSopenharmony_ci{ 57f08c3bdfSopenharmony_ci SAFE_SEMCTL(sem_id, 0, IPC_STAT, (union semun)&buf); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci if (buf.sem_perm.mode == (SEM_RA | NEWMODE)) 60f08c3bdfSopenharmony_ci tst_res(TPASS, "buf.sem_perm.mode is correct"); 61f08c3bdfSopenharmony_ci else 62f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore mode info is incorrect"); 63f08c3bdfSopenharmony_ci} 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cistatic void func_gall(void) 66f08c3bdfSopenharmony_ci{ 67f08c3bdfSopenharmony_ci int i; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci for (i = 0; i < PSEMS; i++) { 70f08c3bdfSopenharmony_ci if (array[i] != 0) { 71f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore %d has unexpected value", i); 72f08c3bdfSopenharmony_ci return; 73f08c3bdfSopenharmony_ci } 74f08c3bdfSopenharmony_ci } 75f08c3bdfSopenharmony_ci tst_res(TPASS, "semaphores have expected values"); 76f08c3bdfSopenharmony_ci} 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_cistatic void child_cnt(void) 79f08c3bdfSopenharmony_ci{ 80f08c3bdfSopenharmony_ci sops.sem_num = 4; 81f08c3bdfSopenharmony_ci sops.sem_flg = 0; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci /* 84f08c3bdfSopenharmony_ci * Do a semop that will cause the child to sleep. 85f08c3bdfSopenharmony_ci * The child process will be killed in the func_ncnt 86f08c3bdfSopenharmony_ci * routine which should cause an error to be return 87f08c3bdfSopenharmony_ci * by the semop() call. 88f08c3bdfSopenharmony_ci */ 89f08c3bdfSopenharmony_ci if (semop(sem_id, &sops, 1) != -1) 90f08c3bdfSopenharmony_ci tst_brk(TBROK, "semop succeeded - cnt_setup"); 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic void cnt_setup(int opval) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci int pid, i; 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci sops.sem_num = 4; 98f08c3bdfSopenharmony_ci sops.sem_flg = 0; 99f08c3bdfSopenharmony_ci /* 100f08c3bdfSopenharmony_ci * if seting up for GETZCNT, the semaphore value needs to be positive 101f08c3bdfSopenharmony_ci */ 102f08c3bdfSopenharmony_ci if (opval == 0) { 103f08c3bdfSopenharmony_ci sops.sem_op = 1; 104f08c3bdfSopenharmony_ci SAFE_SEMOP(sem_id, &sops, 1); 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci sops.sem_op = opval; 108f08c3bdfSopenharmony_ci for (i = 0; i < NCHILD; i++) { 109f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 110f08c3bdfSopenharmony_ci if (pid == 0) { 111f08c3bdfSopenharmony_ci child_cnt(); 112f08c3bdfSopenharmony_ci } else { 113f08c3bdfSopenharmony_ci TST_PROCESS_STATE_WAIT(pid, 'S', 0); 114f08c3bdfSopenharmony_ci pid_arr[i] = pid; 115f08c3bdfSopenharmony_ci } 116f08c3bdfSopenharmony_ci } 117f08c3bdfSopenharmony_ci} 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_cistatic void func_cnt(int rval) 120f08c3bdfSopenharmony_ci{ 121f08c3bdfSopenharmony_ci if (rval == NCHILD) 122f08c3bdfSopenharmony_ci tst_res(TPASS, "number of sleeping processes is correct"); 123f08c3bdfSopenharmony_ci else 124f08c3bdfSopenharmony_ci tst_res(TFAIL, "number of sleeping processes is not correct"); 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_cistatic void child_pid(void) 128f08c3bdfSopenharmony_ci{ 129f08c3bdfSopenharmony_ci sops.sem_num = 2; 130f08c3bdfSopenharmony_ci sops.sem_op = 1; 131f08c3bdfSopenharmony_ci sops.sem_flg = 0; 132f08c3bdfSopenharmony_ci /* 133f08c3bdfSopenharmony_ci * Do a semop that will increment the semaphore. 134f08c3bdfSopenharmony_ci */ 135f08c3bdfSopenharmony_ci SAFE_SEMOP(sem_id, &sops, 1); 136f08c3bdfSopenharmony_ci exit(0); 137f08c3bdfSopenharmony_ci} 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_cistatic void pid_setup(void) 140f08c3bdfSopenharmony_ci{ 141f08c3bdfSopenharmony_ci int pid; 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 144f08c3bdfSopenharmony_ci if (pid == 0) { 145f08c3bdfSopenharmony_ci child_pid(); 146f08c3bdfSopenharmony_ci } else { 147f08c3bdfSopenharmony_ci pid_arr[2] = pid; 148f08c3bdfSopenharmony_ci TST_PROCESS_STATE_WAIT(pid, 'Z', 0); 149f08c3bdfSopenharmony_ci } 150f08c3bdfSopenharmony_ci} 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_cistatic void func_pid(int rval) 153f08c3bdfSopenharmony_ci{ 154f08c3bdfSopenharmony_ci if (rval == pid_arr[2]) 155f08c3bdfSopenharmony_ci tst_res(TPASS, "last pid value is correct"); 156f08c3bdfSopenharmony_ci else 157f08c3bdfSopenharmony_ci tst_res(TFAIL, "last pid value is not correct"); 158f08c3bdfSopenharmony_ci} 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_cistatic void func_gval(int rval) 161f08c3bdfSopenharmony_ci{ 162f08c3bdfSopenharmony_ci /* 163f08c3bdfSopenharmony_ci * This is a simple test. The semaphore value should be equal 164f08c3bdfSopenharmony_ci * to ONE as it was set in the last test (GETPID). 165f08c3bdfSopenharmony_ci */ 166f08c3bdfSopenharmony_ci if (rval == 1) 167f08c3bdfSopenharmony_ci tst_res(TPASS, "semaphore value is correct"); 168f08c3bdfSopenharmony_ci else 169f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore value is not correct"); 170f08c3bdfSopenharmony_ci} 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_cistatic void sall_setup(void) 173f08c3bdfSopenharmony_ci{ 174f08c3bdfSopenharmony_ci int i; 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci for (i = 0; i < PSEMS; i++) { 177f08c3bdfSopenharmony_ci array[i] = 3; 178f08c3bdfSopenharmony_ci } 179f08c3bdfSopenharmony_ci} 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_cistatic void func_sall(void) 182f08c3bdfSopenharmony_ci{ 183f08c3bdfSopenharmony_ci int i; 184f08c3bdfSopenharmony_ci unsigned short rarray[PSEMS]; 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci SAFE_SEMCTL(sem_id, 0, GETALL, (union semun)rarray); 187f08c3bdfSopenharmony_ci for (i = 0; i < PSEMS; i++) { 188f08c3bdfSopenharmony_ci if (array[i] != rarray[i]) { 189f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore values are not correct"); 190f08c3bdfSopenharmony_ci return; 191f08c3bdfSopenharmony_ci } 192f08c3bdfSopenharmony_ci } 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci tst_res(TPASS, "semaphore values are correct"); 195f08c3bdfSopenharmony_ci} 196f08c3bdfSopenharmony_ci 197f08c3bdfSopenharmony_cistatic void func_sval(void) 198f08c3bdfSopenharmony_ci{ 199f08c3bdfSopenharmony_ci int semv = SAFE_SEMCTL(sem_id, 4, GETVAL); 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci if (semv != INCVAL) 202f08c3bdfSopenharmony_ci tst_res(TFAIL, "semaphore value is not what was set"); 203f08c3bdfSopenharmony_ci else 204f08c3bdfSopenharmony_ci tst_res(TPASS, "semaphore value is correct"); 205f08c3bdfSopenharmony_ci} 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_cistatic void func_rmid(void) 208f08c3bdfSopenharmony_ci{ 209f08c3bdfSopenharmony_ci TST_EXP_FAIL(semop(sem_id, &sops, 1), EINVAL, "semaphore appears to be removed"); 210f08c3bdfSopenharmony_ci sem_id = -1; 211f08c3bdfSopenharmony_ci} 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_cistatic void func_iinfo(int hidx) 214f08c3bdfSopenharmony_ci{ 215f08c3bdfSopenharmony_ci if (hidx >= 0) { 216f08c3bdfSopenharmony_ci sem_index = hidx; 217f08c3bdfSopenharmony_ci tst_res(TPASS, "the highest index is correct"); 218f08c3bdfSopenharmony_ci } else { 219f08c3bdfSopenharmony_ci sem_index = 0; 220f08c3bdfSopenharmony_ci tst_res(TFAIL, "the highest index is incorrect"); 221f08c3bdfSopenharmony_ci } 222f08c3bdfSopenharmony_ci} 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_cistatic void func_sinfo(void) 225f08c3bdfSopenharmony_ci{ 226f08c3bdfSopenharmony_ci if (ipc_buf.semusz < 1) 227f08c3bdfSopenharmony_ci tst_res(TFAIL, "number of semaphore sets is incorrect"); 228f08c3bdfSopenharmony_ci else 229f08c3bdfSopenharmony_ci tst_res(TPASS, "number of semaphore sets is correct"); 230f08c3bdfSopenharmony_ci} 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_cistatic void func_sstat(int semidx) 233f08c3bdfSopenharmony_ci{ 234f08c3bdfSopenharmony_ci if (semidx >= 0) 235f08c3bdfSopenharmony_ci tst_res(TPASS, "id of the semaphore set is correct"); 236f08c3bdfSopenharmony_ci else 237f08c3bdfSopenharmony_ci tst_res(TFAIL, "id of the semaphore set is incorrect"); 238f08c3bdfSopenharmony_ci} 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_cistatic struct tcases { 241f08c3bdfSopenharmony_ci int *semid; 242f08c3bdfSopenharmony_ci int semnum; 243f08c3bdfSopenharmony_ci int cmd; 244f08c3bdfSopenharmony_ci void (*func_test) (); 245f08c3bdfSopenharmony_ci union semun arg; 246f08c3bdfSopenharmony_ci void (*func_setup) (); 247f08c3bdfSopenharmony_ci} tests[] = { 248f08c3bdfSopenharmony_ci {&sem_id, 0, IPC_STAT, func_stat, SEMUN_CAST & buf, NULL}, 249f08c3bdfSopenharmony_ci {&sem_id, 0, IPC_SET, func_set, SEMUN_CAST & buf, set_setup}, 250f08c3bdfSopenharmony_ci {&sem_id, 0, GETALL, func_gall, SEMUN_CAST array, NULL}, 251f08c3bdfSopenharmony_ci {&sem_id, 4, GETNCNT, func_cnt, SEMUN_CAST & buf, cnt_setup}, 252f08c3bdfSopenharmony_ci {&sem_id, 2, GETPID, func_pid, SEMUN_CAST & buf, pid_setup}, 253f08c3bdfSopenharmony_ci {&sem_id, 2, GETVAL, func_gval, SEMUN_CAST & buf, NULL}, 254f08c3bdfSopenharmony_ci {&sem_id, 4, GETZCNT, func_cnt, SEMUN_CAST & buf, cnt_setup}, 255f08c3bdfSopenharmony_ci {&sem_id, 0, SETALL, func_sall, SEMUN_CAST array, sall_setup}, 256f08c3bdfSopenharmony_ci {&sem_id, 4, SETVAL, func_sval, SEMUN_CAST INCVAL, NULL}, 257f08c3bdfSopenharmony_ci {&sem_id, 0, IPC_INFO, func_iinfo, SEMUN_CAST & ipc_buf, NULL}, 258f08c3bdfSopenharmony_ci {&sem_id, 0, SEM_INFO, func_sinfo, SEMUN_CAST & ipc_buf, NULL}, 259f08c3bdfSopenharmony_ci {&sem_index, 0, SEM_STAT, func_sstat, SEMUN_CAST & buf, NULL}, 260f08c3bdfSopenharmony_ci {&sem_id, 0, IPC_RMID, func_rmid, SEMUN_CAST & buf, NULL}, 261f08c3bdfSopenharmony_ci}; 262f08c3bdfSopenharmony_ci 263f08c3bdfSopenharmony_cistatic void verify_semctl(unsigned int n) 264f08c3bdfSopenharmony_ci{ 265f08c3bdfSopenharmony_ci struct tcases *tc = &tests[n]; 266f08c3bdfSopenharmony_ci int rval; 267f08c3bdfSopenharmony_ci 268f08c3bdfSopenharmony_ci if (sem_id == -1) 269f08c3bdfSopenharmony_ci sem_id = SAFE_SEMGET(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); 270f08c3bdfSopenharmony_ci if (tc->func_setup) { 271f08c3bdfSopenharmony_ci switch (tc->cmd) { 272f08c3bdfSopenharmony_ci case GETNCNT: 273f08c3bdfSopenharmony_ci tc->func_setup(-1); 274f08c3bdfSopenharmony_ci break; 275f08c3bdfSopenharmony_ci case GETZCNT: 276f08c3bdfSopenharmony_ci tc->func_setup(0); 277f08c3bdfSopenharmony_ci break; 278f08c3bdfSopenharmony_ci default: 279f08c3bdfSopenharmony_ci tc->func_setup(); 280f08c3bdfSopenharmony_ci break; 281f08c3bdfSopenharmony_ci } 282f08c3bdfSopenharmony_ci } 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci rval = SAFE_SEMCTL(*(tc->semid), tc->semnum, tc->cmd, tc->arg); 285f08c3bdfSopenharmony_ci switch (tc->cmd) { 286f08c3bdfSopenharmony_ci case GETNCNT: 287f08c3bdfSopenharmony_ci case GETZCNT: 288f08c3bdfSopenharmony_ci case GETPID: 289f08c3bdfSopenharmony_ci case GETVAL: 290f08c3bdfSopenharmony_ci case IPC_INFO: 291f08c3bdfSopenharmony_ci case SEM_STAT: 292f08c3bdfSopenharmony_ci tc->func_test(rval); 293f08c3bdfSopenharmony_ci break; 294f08c3bdfSopenharmony_ci default: 295f08c3bdfSopenharmony_ci tc->func_test(); 296f08c3bdfSopenharmony_ci break; 297f08c3bdfSopenharmony_ci } 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_ci if (tc->cmd == GETNCNT || tc->cmd == GETZCNT) 300f08c3bdfSopenharmony_ci kill_all_children(); 301f08c3bdfSopenharmony_ci} 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_cistatic void cleanup(void) 304f08c3bdfSopenharmony_ci{ 305f08c3bdfSopenharmony_ci if (sem_id >= 0) 306f08c3bdfSopenharmony_ci SAFE_SEMCTL(sem_id, 0, IPC_RMID); 307f08c3bdfSopenharmony_ci} 308f08c3bdfSopenharmony_ci 309f08c3bdfSopenharmony_cistatic struct tst_test test = { 310f08c3bdfSopenharmony_ci .cleanup = cleanup, 311f08c3bdfSopenharmony_ci .test = verify_semctl, 312f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tests), 313f08c3bdfSopenharmony_ci .forks_child = 1, 314f08c3bdfSopenharmony_ci}; 315