1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) International Business Machines  Corp., 2001
4 * Copyright (C) 2003-2023 Linux Test Project, Inc.
5 * Author: 2001 Paul Larson <plars@us.ibm.com>
6 * Modified: 2001 Manoj Iyer <manjo@ausin.ibm.com>
7 */
8
9/*\
10 * [Description]
11 *
12 * Creates a semaphore and two processes.  The processes
13 * each go through a loop where they semdown, delay for a
14 * random amount of time, and semup, so they will almost
15 * always be fighting for control of the semaphore.
16 */
17
18#include <unistd.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <sys/types.h>
22#include <sys/ipc.h>
23#include "lapi/sem.h"
24#include "tst_test.h"
25#include "tst_safe_sysv_ipc.h"
26
27#define LOOPS 1000
28#define SEED 123
29
30static void semup(int semid)
31{
32	struct sembuf semops;
33
34	semops.sem_num = 0;
35	semops.sem_op = 1;
36	semops.sem_flg = SEM_UNDO;
37
38	SAFE_SEMOP(semid, &semops, 1);
39}
40
41static void semdown(int semid)
42{
43	struct sembuf semops;
44
45	semops.sem_num = 0;
46	semops.sem_op = -1;
47	semops.sem_flg = SEM_UNDO;
48
49	SAFE_SEMOP(semid, &semops, 1);
50}
51
52static void mainloop(int semid)
53{
54	int i;
55
56	for (i = 0; i < LOOPS; i++) {
57		semdown(semid);
58		usleep(1 + ((100.0 * rand()) / RAND_MAX));
59		semup(semid);
60	}
61}
62
63static void run(void)
64{
65	int semid;
66	union semun semunion;
67	pid_t pid;
68
69	/* set up the semaphore */
70	semid = SAFE_SEMGET((key_t) 9142, 1, 0666 | IPC_CREAT);
71
72	semunion.val = 1;
73
74	SAFE_SEMCTL(semid, 0, SETVAL, semunion);
75
76	tst_res(TINFO, "srand seed is %d", SEED);
77	srand(SEED);
78
79	pid = SAFE_FORK();
80
81	if (pid) {
82		mainloop(semid);
83		tst_reap_children();
84		TST_EXP_POSITIVE(semctl(semid, 0, IPC_RMID, semunion));
85	} else {
86		mainloop(semid);
87	}
88}
89
90static struct tst_test test = {
91	.test_all = run,
92	.forks_child = 1,
93};
94