blob: beeb16567eae3a5e4e5b24ac530aeaaa365a4fd7 [file] [log] [blame]
subrata_modak5b693742008-02-22 08:33:53 +00001/*
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +04002 * Copyright (c) International Business Machines Corp., 2002
subrata_modak5b693742008-02-22 08:33:53 +00003 *
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +04004 * 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.
subrata_modak5b693742008-02-22 08:33:53 +00008 *
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +04009 * 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.
subrata_modak5b693742008-02-22 08:33:53 +000013 *
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040014 * 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
subrata_modak5b693742008-02-22 08:33:53 +000017 *
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040018 * 06/30/2001 Port to Linux nsharoff@us.ibm.com
19 * 11/11/2002 Port to LTP dbarrera@us.ibm.com
subrata_modak5b693742008-02-22 08:33:53 +000020 */
21
subrata_modak5b693742008-02-22 08:33:53 +000022/*
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040023 * Get and manipulate a message queue.
24 * Same as msgctl09 but gets the actual msgmni value under procfs.
subrata_modak5b693742008-02-22 08:33:53 +000025 */
26
27#define _XOPEN_SOURCE 500
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <sys/ipc.h>
31#include <sys/msg.h>
32#include <sys/wait.h>
33#include <signal.h>
34#include <errno.h>
35#include <stdio.h>
36#include <string.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include "test.h"
subrata_modak5b693742008-02-22 08:33:53 +000040#include "ipcmsg.h"
Peng Haitao1f1e15a2013-12-02 10:30:05 +080041#include "../lib/libmsgctl.h"
subrata_modak5b693742008-02-22 08:33:53 +000042
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040043char *TCID = "msgctl11";
44int TST_TOTAL = 1;
45
subrata_modak5b693742008-02-22 08:33:53 +000046#define MAXNREPS 1000
47#ifndef CONFIG_COLDFIRE
subrata_modak56207ce2009-03-23 13:35:39 +000048#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
subrata_modak5b693742008-02-22 08:33:53 +000049#else
subrata_modak56207ce2009-03-23 13:35:39 +000050#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
subrata_modak5b693742008-02-22 08:33:53 +000051#endif
52#define MAXNKIDS 10
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +040053#define DEFNKIDS 2
subrata_modak5b693742008-02-22 08:33:53 +000054
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040055static int maxnkids = MAXNKIDS; /* Used if pid_max is exceeded */
56static key_t keyarray[MAXNPROCS];
57static int pidarray[MAXNPROCS];
58static int rkidarray[MAXNKIDS];
59static int wkidarray[MAXNKIDS];
60static int tid;
61static int nprocs, nreps, nkids, MSGMNI;
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +040062static int maxnprocs;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040063static int procstat;
subrata_modak5b693742008-02-22 08:33:53 +000064
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040065void setup(void);
66void cleanup(void);
subrata_modak5b693742008-02-22 08:33:53 +000067
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040068static void term(int);
69static int dotest(key_t, int);
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +040070static void dotest_iteration(int off);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040071static void cleanup_msgqueue(int i, int tid);
subrata_modak5b693742008-02-22 08:33:53 +000072
subrata_modak5b693742008-02-22 08:33:53 +000073#ifdef UCLINUX
74static char *argv0;
subrata_modak5b693742008-02-22 08:33:53 +000075static key_t key_uclinux;
76static int i_uclinux;
subrata_modak5b693742008-02-22 08:33:53 +000077static int pid_uclinux;
78static int child_process_uclinux;
subrata_modak5b693742008-02-22 08:33:53 +000079static int rkid_uclinux;
subrata_modak5b693742008-02-22 08:33:53 +000080
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +040081static void do_child_1_uclinux(void);
82static void do_child_2_uclinux(void);
83static void do_child_3_uclinux(void);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040084#endif
85
86int main(int argc, char **argv)
subrata_modak5b693742008-02-22 08:33:53 +000087{
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +040088 int i, j, ok;
subrata_modak5b693742008-02-22 08:33:53 +000089
90#ifdef UCLINUX
Cyril Hrubis74225622014-06-02 17:54:38 +020091 const char *msg;
subrata_modak5b693742008-02-22 08:33:53 +000092
93 argv0 = argv[0];
94
Cyril Hrubis74225622014-06-02 17:54:38 +020095 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080096 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak5b693742008-02-22 08:33:53 +000097
subrata_modak56207ce2009-03-23 13:35:39 +000098 maybe_run_child(&do_child_1_uclinux, "ndd", 1, &key_uclinux,
99 &i_uclinux);
subrata_modak5b693742008-02-22 08:33:53 +0000100 maybe_run_child(&do_child_2_uclinux, "nddd", 2, &key_uclinux,
101 &pid_uclinux, &child_process_uclinux);
102 maybe_run_child(&do_child_3_uclinux, "nddd", 3, &key_uclinux,
103 &rkid_uclinux, &child_process_uclinux);
104#endif
105
106 setup();
107
subrata_modak56207ce2009-03-23 13:35:39 +0000108 if (argc == 1) {
subrata_modak5b693742008-02-22 08:33:53 +0000109 /* Set default parameters */
110 nreps = MAXNREPS;
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400111 nkids = DEFNKIDS;
subrata_modak56207ce2009-03-23 13:35:39 +0000112 } else if (argc == 4) {
113 if (atoi(argv[1]) > MAXNREPS) {
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400114 tst_resm(TINFO,
subrata_modak56207ce2009-03-23 13:35:39 +0000115 "Requested number of iterations too large, setting to Max. of %d",
116 MAXNREPS);
subrata_modak5b693742008-02-22 08:33:53 +0000117 nreps = MAXNREPS;
subrata_modak56207ce2009-03-23 13:35:39 +0000118 } else {
subrata_modak5b693742008-02-22 08:33:53 +0000119 nreps = atoi(argv[1]);
120 }
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400121 if (atoi(argv[2]) > maxnprocs) {
122 tst_resm(TINFO,
subrata_modak56207ce2009-03-23 13:35:39 +0000123 "Requested number of processes too large, setting to Max. of %d",
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400124 maxnprocs);
subrata_modak56207ce2009-03-23 13:35:39 +0000125 } else {
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400126 maxnprocs = atoi(argv[2]);
subrata_modak5b693742008-02-22 08:33:53 +0000127 }
subrata_modak56207ce2009-03-23 13:35:39 +0000128 if (atoi(argv[3]) > maxnkids) {
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400129 tst_resm(TINFO,
subrata_modak56207ce2009-03-23 13:35:39 +0000130 "Requested number of read/write pairs too large; setting to Max. of %d",
131 maxnkids);
subrata_modak8bc4d772009-01-15 10:31:45 +0000132 nkids = maxnkids;
subrata_modak56207ce2009-03-23 13:35:39 +0000133 } else {
subrata_modak5b693742008-02-22 08:33:53 +0000134 nkids = atoi(argv[3]);
135 }
subrata_modak56207ce2009-03-23 13:35:39 +0000136 } else {
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400137 tst_brkm(TCONF, cleanup,
subrata_modak56207ce2009-03-23 13:35:39 +0000138 " Usage: %s [ number of iterations number of processes number of read/write pairs ]",
139 argv[0]);
subrata_modak5b693742008-02-22 08:33:53 +0000140 }
141
142 procstat = 0;
143 srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
144 tid = -1;
145
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400146 /* Setup signal handling routine */
147 if (sigset(SIGTERM, term) == SIG_ERR)
148 tst_brkm(TFAIL, cleanup, "Sigset SIGTERM failed");
149
subrata_modak5b693742008-02-22 08:33:53 +0000150 /* Set up array of unique keys for use in allocating message
151 * queues
152 */
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400153 for (i = 0; i < MSGMNI; i++) {
subrata_modak5b693742008-02-22 08:33:53 +0000154 ok = 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000155 do {
subrata_modak5b693742008-02-22 08:33:53 +0000156 /* Get random key */
subrata_modak56207ce2009-03-23 13:35:39 +0000157 keyarray[i] = (key_t) lrand48();
subrata_modak5b693742008-02-22 08:33:53 +0000158 /* Make sure key is unique and not private */
subrata_modak56207ce2009-03-23 13:35:39 +0000159 if (keyarray[i] == IPC_PRIVATE) {
subrata_modak5b693742008-02-22 08:33:53 +0000160 ok = 0;
161 continue;
162 }
subrata_modak56207ce2009-03-23 13:35:39 +0000163 for (j = 0; j < i; j++) {
164 if (keyarray[j] == keyarray[i]) {
subrata_modak5b693742008-02-22 08:33:53 +0000165 ok = 0;
166 break;
167 }
168 ok = 1;
169 }
170 } while (ok == 0);
171 }
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400172 /* Fork a number of processes, each of which will
subrata_modak5b693742008-02-22 08:33:53 +0000173 * create a message queue with several (nkids) reader/writer
174 * pairs which will read and write a number (iterations)
175 * of random length messages with specific values (keys).
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400176 *
177 * We do not fork more than maxnprocs at a time and
178 * we fork until all the message queues get used.
subrata_modak5b693742008-02-22 08:33:53 +0000179 */
180
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400181 if (MSGMNI <= maxnprocs) {
182 nprocs = MSGMNI;
183 dotest_iteration(0);
184 } else {
185 for (i = 0; i < (MSGMNI / maxnprocs); i++) {
186 nprocs = maxnprocs;
187 dotest_iteration(i*(MSGMNI / maxnprocs));
188 }
189
190 nprocs = MSGMNI % maxnprocs;
191 dotest_iteration(i*(MSGMNI / maxnprocs));
192 }
193
194 tst_resm(TPASS, "msgctl11 ran successfully!");
195
196 cleanup();
197 tst_exit();
198}
199
200static void dotest_iteration(int off)
201{
202 key_t key;
203 int i, count, status;
204 pid_t pid;
205
206 memset(pidarray, 0, sizeof(pidarray));
207
subrata_modak56207ce2009-03-23 13:35:39 +0000208 for (i = 0; i < nprocs; i++) {
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400209 key = keyarray[off + i];
210
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400211 if ((pid = FORK_OR_VFORK()) < 0)
212 tst_brkm(TFAIL, cleanup,
213 "Fork failed (may be OK if under stress)");
214
subrata_modak5b693742008-02-22 08:33:53 +0000215 /* Child does this */
subrata_modak56207ce2009-03-23 13:35:39 +0000216 if (pid == 0) {
subrata_modak5b693742008-02-22 08:33:53 +0000217#ifdef UCLINUX
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400218 if (self_exec(argv0, "ndd", 1, key, i) < 0) {
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400219 printf("\tself_exec failed\n");
220 exit(FAIL);
subrata_modak5b693742008-02-22 08:33:53 +0000221 }
222#else
223 procstat = 1;
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400224 exit(dotest(key, i));
subrata_modak5b693742008-02-22 08:33:53 +0000225#endif
226 }
227 pidarray[i] = pid;
228 }
229
230 count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000231 while (1) {
232 if ((wait(&status)) > 0) {
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400233 if (status >> 8 != PASS)
234 tst_brkm(TFAIL, cleanup,
235 "Child exit status = %d", status >> 8);
subrata_modak5b693742008-02-22 08:33:53 +0000236 count++;
subrata_modak56207ce2009-03-23 13:35:39 +0000237 } else {
238 if (errno != EINTR) {
subrata_modak5b693742008-02-22 08:33:53 +0000239 break;
240 }
241#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000242 tst_resm(TINFO, "Signal detected during wait");
subrata_modak5b693742008-02-22 08:33:53 +0000243#endif
244 }
245 }
246 /* Make sure proper number of children exited */
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400247 if (count != nprocs)
248 tst_brkm(TFAIL, cleanup,
subrata_modak56207ce2009-03-23 13:35:39 +0000249 "Wrong number of children exited, Saw %d, Expected %d",
250 count, nprocs);
subrata_modak5b693742008-02-22 08:33:53 +0000251}
subrata_modak56207ce2009-03-23 13:35:39 +0000252
subrata_modak5b693742008-02-22 08:33:53 +0000253#ifdef UCLINUX
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400254static void do_child_1_uclinux(void)
subrata_modak5b693742008-02-22 08:33:53 +0000255{
256 procstat = 1;
257 exit(dotest(key_uclinux, i_uclinux));
258}
259
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400260static void do_child_2_uclinux(void)
subrata_modak5b693742008-02-22 08:33:53 +0000261{
262 procstat = 2;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400263 exit(doreader(key_uclinux, tid, pid_uclinux,
264 child_process_uclinux, nreps));
subrata_modak5b693742008-02-22 08:33:53 +0000265}
266
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400267static void do_child_3_uclinux(void)
subrata_modak5b693742008-02-22 08:33:53 +0000268{
269 procstat = 2;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400270 exit(dowriter(key_uclinux, tid, rkid_uclinux,
271 child_process_uclinux, nreps));
subrata_modak5b693742008-02-22 08:33:53 +0000272}
273#endif
274
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400275static void cleanup_msgqueue(int i, int tid)
subrata_modak5b693742008-02-22 08:33:53 +0000276{
277 /*
278 * Decrease the value of i by 1 because it
279 * is getting incremented even if the fork
280 * is failing.
281 */
282
283 i--;
284 /*
285 * Kill all children & free message queue.
286 */
287 for (; i >= 0; i--) {
288 (void)kill(rkidarray[i], SIGKILL);
289 (void)kill(wkidarray[i], SIGKILL);
290 }
291
292 if (msgctl(tid, IPC_RMID, 0) < 0) {
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400293 printf("Msgctl error in cleanup_msgqueue %d\n", errno);
294 exit(FAIL);
subrata_modak5b693742008-02-22 08:33:53 +0000295 }
296}
297
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400298static int dotest(key_t key, int child_process)
subrata_modak5b693742008-02-22 08:33:53 +0000299{
300 int id, pid;
301 int i, count, status, exit_status;
302
303 sighold(SIGTERM);
subrata_modak56207ce2009-03-23 13:35:39 +0000304 if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400305 printf("msgget() error in child %d: %s\n",
306 child_process, strerror(errno));
307 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000308 }
309 tid = id;
310 sigrelse(SIGTERM);
311
312 exit_status = PASS;
313
subrata_modak56207ce2009-03-23 13:35:39 +0000314 for (i = 0; i < nkids; i++) {
subrata_modak56207ce2009-03-23 13:35:39 +0000315 if ((pid = FORK_OR_VFORK()) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400316 printf("Fork failure in the first child of child group %d\n",
317 child_process);
subrata_modak5b693742008-02-22 08:33:53 +0000318 cleanup_msgqueue(i, tid);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400319 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000320 }
321 /* First child does this */
subrata_modak56207ce2009-03-23 13:35:39 +0000322 if (pid == 0) {
subrata_modak5b693742008-02-22 08:33:53 +0000323#ifdef UCLINUX
324 if (self_exec(argv0, "nddd", 2, key, getpid(),
subrata_modak56207ce2009-03-23 13:35:39 +0000325 child_process) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400326 printf("self_exec failed\n");
subrata_modak5b693742008-02-22 08:33:53 +0000327 cleanup_msgqueue(i, tid);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400328 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000329 }
330#else
331 procstat = 2;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400332 exit(doreader(key, tid, getpid(),
333 child_process, nreps));
subrata_modak5b693742008-02-22 08:33:53 +0000334#endif
335 }
336 rkidarray[i] = pid;
subrata_modak56207ce2009-03-23 13:35:39 +0000337 if ((pid = FORK_OR_VFORK()) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400338 printf("Fork failure in the second child of child group %d\n",
339 child_process);
subrata_modak5b693742008-02-22 08:33:53 +0000340 /*
341 * Kill the reader child process
342 */
343 (void)kill(rkidarray[i], SIGKILL);
344
345 cleanup_msgqueue(i, tid);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400346 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000347 }
348 /* Second child does this */
subrata_modak56207ce2009-03-23 13:35:39 +0000349 if (pid == 0) {
subrata_modak5b693742008-02-22 08:33:53 +0000350#ifdef UCLINUX
351 if (self_exec(argv0, "nddd", 3, key, rkidarray[i],
subrata_modak56207ce2009-03-23 13:35:39 +0000352 child_process) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400353 printf("\tFork failure in the first child of child group %d\n",
354 child_process);
subrata_modak5b693742008-02-22 08:33:53 +0000355 /*
356 * Kill the reader child process
357 */
358 (void)kill(rkidarray[i], SIGKILL);
359
360 cleanup_msgqueue(i, tid);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400361 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000362 }
363#else
364 procstat = 2;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400365 exit(dowriter(key, tid, rkidarray[i],
366 child_process, nreps));
subrata_modak5b693742008-02-22 08:33:53 +0000367#endif
368 }
369 wkidarray[i] = pid;
370 }
371 /* Parent does this */
372 count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000373 while (1) {
374 if ((wait(&status)) > 0) {
375 if (status >> 8 != PASS) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400376 printf("Child exit status = %d from child group %d\n",
377 status >> 8, child_process);
subrata_modak56207ce2009-03-23 13:35:39 +0000378 for (i = 0; i < nkids; i++) {
subrata_modak5b693742008-02-22 08:33:53 +0000379 kill(rkidarray[i], SIGTERM);
380 kill(wkidarray[i], SIGTERM);
381 }
382 if (msgctl(tid, IPC_RMID, 0) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400383 printf("msgctl() error: %s\n",
384 strerror(errno));
subrata_modak5b693742008-02-22 08:33:53 +0000385 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400386 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000387 }
388 count++;
subrata_modak56207ce2009-03-23 13:35:39 +0000389 } else {
390 if (errno != EINTR) {
subrata_modak5b693742008-02-22 08:33:53 +0000391 break;
392 }
393 }
394 }
395 /* Make sure proper number of children exited */
subrata_modak56207ce2009-03-23 13:35:39 +0000396 if (count != (nkids * 2)) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400397 printf("Wrong number of children exited in child group %d, saw %d, expected %d\n",
398 child_process, count, (nkids * 2));
subrata_modak5b693742008-02-22 08:33:53 +0000399 if (msgctl(tid, IPC_RMID, 0) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400400 printf("msgctl() error: %s\n", strerror(errno));
subrata_modak5b693742008-02-22 08:33:53 +0000401 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400402 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000403 }
subrata_modak56207ce2009-03-23 13:35:39 +0000404 if (msgctl(id, IPC_RMID, 0) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400405 printf("msgctl() failure in child group %d: %s\n",
406 child_process, strerror(errno));
407 return FAIL;
subrata_modak5b693742008-02-22 08:33:53 +0000408 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400409 return exit_status;
subrata_modak5b693742008-02-22 08:33:53 +0000410}
411
412/* ARGSUSED */
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400413static void term(int sig)
subrata_modak5b693742008-02-22 08:33:53 +0000414{
415 int i;
416
subrata_modak56207ce2009-03-23 13:35:39 +0000417 if (procstat == 0) {
subrata_modak5b693742008-02-22 08:33:53 +0000418#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000419 tst_resm(TINFO, "SIGTERM signal received, test killing kids");
subrata_modak5b693742008-02-22 08:33:53 +0000420#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000421 for (i = 0; i < nprocs; i++) {
422 if (pidarray[i] > 0) {
423 if (kill(pidarray[i], SIGTERM) < 0) {
424 tst_resm(TBROK,
425 "Kill failed to kill child %d",
426 i);
subrata_modak5b693742008-02-22 08:33:53 +0000427 exit(FAIL);
428 }
429 }
430 }
431 return;
432 }
433
subrata_modak56207ce2009-03-23 13:35:39 +0000434 if (procstat == 2) {
subrata_modak5b693742008-02-22 08:33:53 +0000435 exit(PASS);
436 }
437
subrata_modak56207ce2009-03-23 13:35:39 +0000438 if (tid == -1) {
subrata_modak5b693742008-02-22 08:33:53 +0000439 exit(FAIL);
440 }
subrata_modak56207ce2009-03-23 13:35:39 +0000441 for (i = 0; i < nkids; i++) {
subrata_modak5b693742008-02-22 08:33:53 +0000442 if (rkidarray[i] > 0)
443 kill(rkidarray[i], SIGTERM);
444 if (wkidarray[i] > 0)
445 kill(wkidarray[i], SIGTERM);
446 }
447}
448
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400449void setup(void)
subrata_modak5b693742008-02-22 08:33:53 +0000450{
subrata_modak8bc4d772009-01-15 10:31:45 +0000451 int nr_msgqs, free_pids;
subrata_modak5b693742008-02-22 08:33:53 +0000452
453 tst_tmpdir();
454 /* You will want to enable some signal handling so you can capture
455 * unexpected signals like SIGSEGV.
456 */
457 tst_sig(FORK, DEF_HANDLER, cleanup);
458
subrata_modak5b693742008-02-22 08:33:53 +0000459 /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to
460 * fork the test with the -c option. You want to make sure you do this
461 * before you create your temporary directory.
462 */
463 TEST_PAUSE;
464
465 nr_msgqs = get_max_msgqueues();
466 if (nr_msgqs < 0)
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400467 tst_brkm(TBROK, cleanup, "get_max_msgqueues() failed");
subrata_modak5b693742008-02-22 08:33:53 +0000468
469 MSGMNI = nr_msgqs - get_used_msgqueues();
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400470 if (MSGMNI <= 0)
471 tst_brkm(TBROK, cleanup,
subrata_modak56207ce2009-03-23 13:35:39 +0000472 "Max number of message queues already used, cannot create more.");
subrata_modakbdbaec52009-02-26 12:14:51 +0000473
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400474 tst_resm(TINFO, "Found %d available message queues", MSGMNI);
475
Stanislav Kholmanskikh502e42f2014-06-30 14:48:23 +0400476 free_pids = tst_get_free_pids(cleanup);
subrata_modak8bc4d772009-01-15 10:31:45 +0000477 if (free_pids < 0) {
Stanislav Kholmanskikh31c09bc2014-02-25 18:40:26 +0400478 tst_brkm(TBROK, cleanup, "Can't obtain free_pid count");
479 } else if (!free_pids) {
480 tst_brkm(TBROK, cleanup, "No free pids");
subrata_modak8bc4d772009-01-15 10:31:45 +0000481 }
482
Stanislav Kholmanskikhd6e9b782014-02-25 18:40:27 +0400483 /* We don't use more than a half of available pids.
484 * For each child we fork up to 2*maxnkids grandchildren. */
485 maxnprocs = (free_pids / 2) / (1 + 2 * maxnkids);
486
487 if (!maxnprocs)
488 tst_brkm(TBROK, cleanup, "Not enough free pids");
subrata_modakbdbaec52009-02-26 12:14:51 +0000489
subrata_modak56207ce2009-03-23 13:35:39 +0000490 tst_resm(TINFO, "Using upto %d pids", free_pids / 2);
subrata_modak5b693742008-02-22 08:33:53 +0000491}
492
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400493void cleanup(void)
subrata_modak5b693742008-02-22 08:33:53 +0000494{
495 int status;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400496
subrata_modak5b693742008-02-22 08:33:53 +0000497 /*
498 * Remove the message queue from the system
499 */
500#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000501 tst_resm(TINFO, "Removing the message queue");
subrata_modak5b693742008-02-22 08:33:53 +0000502#endif
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800503 (void)msgctl(tid, IPC_RMID, NULL);
504 if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
505 (void)msgctl(tid, IPC_RMID, NULL);
subrata_modak5b693742008-02-22 08:33:53 +0000506 tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800507
subrata_modak5b693742008-02-22 08:33:53 +0000508 }
509
subrata_modak5b693742008-02-22 08:33:53 +0000510 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700511}