blob: 08cd02cf21bdb7684db4f0c1e05a66eb48aa842c [file] [log] [blame]
robbiew577ff1a2002-12-05 20:12:28 +00001/*
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +04002 * Copyright (c) International Business Machines Corp., 2002
robbiew577ff1a2002-12-05 20:12:28 +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.
robbiew577ff1a2002-12-05 20:12:28 +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.
robbiew577ff1a2002-12-05 20:12:28 +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
robbiew577ff1a2002-12-05 20:12:28 +000017 *
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040018 * 06/30/2001 Port to Linux nsharoff@us.ibm.com
19 * 11/06/2002 Port to LTP dbarrera@us.ibm.com
robbiew577ff1a2002-12-05 20:12:28 +000020 */
21
robbiew577ff1a2002-12-05 20:12:28 +000022/*
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040023 * Get and manipulate a message queue.
robbiew577ff1a2002-12-05 20:12:28 +000024 */
25
26#define _XOPEN_SOURCE 500
27#include <signal.h>
28#include <errno.h>
29#include <string.h>
30#include <fcntl.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <unistd.h>
robbiewef4118b2003-01-17 18:56:04 +000034#include <values.h>
robbiew577ff1a2002-12-05 20:12:28 +000035#include <sys/types.h>
36#include <sys/wait.h>
37#include <sys/stat.h>
38#include <sys/ipc.h>
39#include <sys/msg.h>
40#include "test.h"
subrata_modak440341b2008-02-20 09:40:48 +000041#include "ipcmsg.h"
Peng Haitao1f1e15a2013-12-02 10:30:05 +080042#include "../lib/libmsgctl.h"
robbiew577ff1a2002-12-05 20:12:28 +000043
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040044char *TCID = "msgctl08";
45int TST_TOTAL = 1;
robbiew577ff1a2002-12-05 20:12:28 +000046
robbiew6eaecb22005-12-22 20:18:22 +000047#ifndef CONFIG_COLDFIRE
subrata_modak56207ce2009-03-23 13:35:39 +000048#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
robbiew6eaecb22005-12-22 20:18:22 +000049#else
subrata_modak56207ce2009-03-23 13:35:39 +000050#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
robbiew6eaecb22005-12-22 20:18:22 +000051#endif
robbiew577ff1a2002-12-05 20:12:28 +000052#define MAXNREPS 100000
robbiew577ff1a2002-12-05 20:12:28 +000053
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040054static key_t keyarray[MAXNPROCS];
55static int pidarray[MAXNPROCS];
56static int tid;
57static int MSGMNI, nprocs, nreps;
58static int procstat;
59static int mykid;
robbiew577ff1a2002-12-05 20:12:28 +000060
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040061void setup(void);
62void cleanup(void);
robbiew577ff1a2002-12-05 20:12:28 +000063
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040064static int dotest(key_t key, int child_process);
65static void sig_handler();
66
robbiewd34d5812005-07-11 22:28:09 +000067#ifdef UCLINUX
68static char *argv0;
robbiewd34d5812005-07-11 22:28:09 +000069static key_t key_uclinux;
70static int i_uclinux;
robbiewd34d5812005-07-11 22:28:09 +000071static int id_uclinux;
72static int child_process_uclinux;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040073
74static void do_child_1_uclinux(void);
75static void do_child_2_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000076#endif
robbiew577ff1a2002-12-05 20:12:28 +000077
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040078int main(int argc, char **argv)
robbiew577ff1a2002-12-05 20:12:28 +000079{
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +040080 int i, j, ok, pid;
robbiew577ff1a2002-12-05 20:12:28 +000081 int count, status;
robbiewd16a7932005-02-24 17:02:44 +000082 struct sigaction act;
robbiew577ff1a2002-12-05 20:12:28 +000083
robbiewd34d5812005-07-11 22:28:09 +000084#ifdef UCLINUX
Cyril Hrubis74225622014-06-02 17:54:38 +020085 const char *msg;
robbiewd34d5812005-07-11 22:28:09 +000086
87 argv0 = argv[0];
88
Cyril Hrubis74225622014-06-02 17:54:38 +020089 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080090 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modakbdbaec52009-02-26 12:14:51 +000091
subrata_modak56207ce2009-03-23 13:35:39 +000092 maybe_run_child(&do_child_1_uclinux, "ndd", 1, &key_uclinux,
93 &i_uclinux);
94 maybe_run_child(&do_child_2_uclinux, "nddd", 2, &id_uclinux,
95 &key_uclinux, &child_process_uclinux);
robbiewd34d5812005-07-11 22:28:09 +000096#endif
97
robbiew577ff1a2002-12-05 20:12:28 +000098 setup();
subrata_modakbdbaec52009-02-26 12:14:51 +000099
subrata_modak56207ce2009-03-23 13:35:39 +0000100 if (argc == 1) {
robbiew577ff1a2002-12-05 20:12:28 +0000101 /* Set default parameters */
102 nreps = MAXNREPS;
robbiewef4118b2003-01-17 18:56:04 +0000103 nprocs = MSGMNI;
subrata_modak56207ce2009-03-23 13:35:39 +0000104 } else if (argc == 3) {
105 if (atoi(argv[1]) > MAXNREPS) {
106 tst_resm(TCONF,
107 "Requested number of iterations too large, setting to Max. of %d",
108 MAXNREPS);
robbiew577ff1a2002-12-05 20:12:28 +0000109 nreps = MAXNREPS;
subrata_modak56207ce2009-03-23 13:35:39 +0000110 } else {
robbiew577ff1a2002-12-05 20:12:28 +0000111 nreps = atoi(argv[1]);
112 }
subrata_modak56207ce2009-03-23 13:35:39 +0000113 if (atoi(argv[2]) > MSGMNI) {
114 tst_resm(TCONF,
115 "Requested number of processes too large, setting to Max. of %d",
116 MSGMNI);
robbiewef4118b2003-01-17 18:56:04 +0000117 nprocs = MSGMNI;
subrata_modak56207ce2009-03-23 13:35:39 +0000118 } else {
robbiew577ff1a2002-12-05 20:12:28 +0000119 nprocs = atoi(argv[2]);
120 }
subrata_modak56207ce2009-03-23 13:35:39 +0000121 } else {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100122 tst_brkm(TCONF,
123 NULL,
subrata_modak56207ce2009-03-23 13:35:39 +0000124 " Usage: %s [ number of iterations number of processes ]",
125 argv[0]);
robbiew577ff1a2002-12-05 20:12:28 +0000126 }
127
128 srand(getpid());
129 tid = -1;
130
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400131 /* Setup signal handling routine */
robbiewd16a7932005-02-24 17:02:44 +0000132 memset(&act, 0, sizeof(act));
133 act.sa_handler = sig_handler;
134 sigemptyset(&act.sa_mask);
135 sigaddset(&act.sa_mask, SIGTERM);
subrata_modak56207ce2009-03-23 13:35:39 +0000136 if (sigaction(SIGTERM, &act, NULL) < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100137 tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
robbiew577ff1a2002-12-05 20:12:28 +0000138 }
139 /* Set up array of unique keys for use in allocating message
140 * queues
141 */
subrata_modak56207ce2009-03-23 13:35:39 +0000142 for (i = 0; i < nprocs; i++) {
robbiew577ff1a2002-12-05 20:12:28 +0000143 ok = 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000144 do {
robbiew577ff1a2002-12-05 20:12:28 +0000145 /* Get random key */
subrata_modak56207ce2009-03-23 13:35:39 +0000146 keyarray[i] = (key_t) rand();
robbiew577ff1a2002-12-05 20:12:28 +0000147 /* Make sure key is unique and not private */
subrata_modak56207ce2009-03-23 13:35:39 +0000148 if (keyarray[i] == IPC_PRIVATE) {
robbiew577ff1a2002-12-05 20:12:28 +0000149 ok = 0;
150 continue;
151 }
subrata_modak56207ce2009-03-23 13:35:39 +0000152 for (j = 0; j < i; j++) {
153 if (keyarray[j] == keyarray[i]) {
robbiew577ff1a2002-12-05 20:12:28 +0000154 ok = 0;
155 break;
156 }
157 ok = 1;
158 }
159 } while (ok == 0);
160 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000161
robbiew577ff1a2002-12-05 20:12:28 +0000162 /* Fork a number of processes, each of which will
163 * create a message queue with one reader/writer
164 * pair which will read and write a number (iterations)
165 * of random length messages with specific values.
166 */
167
subrata_modak56207ce2009-03-23 13:35:39 +0000168 for (i = 0; i < nprocs; i++) {
robbiew577ff1a2002-12-05 20:12:28 +0000169 fflush(stdout);
subrata_modak56207ce2009-03-23 13:35:39 +0000170 if ((pid = FORK_OR_VFORK()) < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100171 tst_brkm(TFAIL,
172 NULL,
subrata_modak56207ce2009-03-23 13:35:39 +0000173 "\tFork failed (may be OK if under stress)");
robbiew577ff1a2002-12-05 20:12:28 +0000174 }
175 /* Child does this */
subrata_modak56207ce2009-03-23 13:35:39 +0000176 if (pid == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000177#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000178 if (self_exec(argv[0], "ndd", 1, keyarray[i], i) < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100179 tst_brkm(TFAIL, NULL, "\tself_exec failed");
robbiewd34d5812005-07-11 22:28:09 +0000180 }
181#else
robbiew577ff1a2002-12-05 20:12:28 +0000182 procstat = 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000183 exit(dotest(keyarray[i], i));
robbiewd34d5812005-07-11 22:28:09 +0000184#endif
robbiew577ff1a2002-12-05 20:12:28 +0000185 }
186 pidarray[i] = pid;
187 }
188
189 count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000190 while (1) {
191 if ((wait(&status)) > 0) {
192 if (status >> 8 != 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100193 tst_brkm(TFAIL, NULL,
194 "Child exit status = %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000195 status >> 8);
robbiew577ff1a2002-12-05 20:12:28 +0000196 }
197 count++;
subrata_modak56207ce2009-03-23 13:35:39 +0000198 } else {
199 if (errno != EINTR) {
robbiew577ff1a2002-12-05 20:12:28 +0000200 break;
201 }
202#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000203 tst_resm(TINFO, "Signal detected during wait");
robbiew577ff1a2002-12-05 20:12:28 +0000204#endif
205 }
206 }
207 /* Make sure proper number of children exited */
subrata_modak56207ce2009-03-23 13:35:39 +0000208 if (count != nprocs) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100209 tst_brkm(TFAIL,
210 NULL,
subrata_modak56207ce2009-03-23 13:35:39 +0000211 "Wrong number of children exited, Saw %d, Expected %d",
212 count, nprocs);
robbiew577ff1a2002-12-05 20:12:28 +0000213 }
214
subrata_modak56207ce2009-03-23 13:35:39 +0000215 tst_resm(TPASS, "msgctl08 ran successfully!");
subrata_modakbdbaec52009-02-26 12:14:51 +0000216
robbiew577ff1a2002-12-05 20:12:28 +0000217 cleanup();
Cyril Hrubis4dff8542014-09-23 12:11:59 +0200218 tst_exit();
robbiew577ff1a2002-12-05 20:12:28 +0000219}
subrata_modak56207ce2009-03-23 13:35:39 +0000220
robbiewd34d5812005-07-11 22:28:09 +0000221#ifdef UCLINUX
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400222static void do_child_1_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000223{
224 procstat = 1;
225 exit(dotest(key_uclinux, i_uclinux));
226}
227
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400228static void do_child_2_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000229{
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400230 exit(doreader(key_uclinux, id_uclinux, 1,
231 child_process_uclinux, nreps));
robbiewd34d5812005-07-11 22:28:09 +0000232}
233#endif
234
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400235static int dotest(key_t key, int child_process)
robbiew577ff1a2002-12-05 20:12:28 +0000236{
237 int id, pid;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400238 int ret, status;
robbiew577ff1a2002-12-05 20:12:28 +0000239
240 sighold(SIGTERM);
subrata_modak56207ce2009-03-23 13:35:39 +0000241 TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
242 if (TEST_RETURN < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400243 printf("msgget() error in child %d: %s\n",
244 child_process, strerror(TEST_ERRNO));
245
246 return FAIL;
robbiew577ff1a2002-12-05 20:12:28 +0000247 }
248 tid = id = TEST_RETURN;
249 sigrelse(SIGTERM);
250
251 fflush(stdout);
subrata_modak56207ce2009-03-23 13:35:39 +0000252 if ((pid = FORK_OR_VFORK()) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400253 printf("\tFork failed (may be OK if under stress)\n");
robbiew577ff1a2002-12-05 20:12:28 +0000254 TEST(msgctl(tid, IPC_RMID, 0));
subrata_modak56207ce2009-03-23 13:35:39 +0000255 if (TEST_RETURN < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400256 printf("mscgtl() error in cleanup: %s\n",
257 strerror(TEST_ERRNO));
robbiew577ff1a2002-12-05 20:12:28 +0000258 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400259 return FAIL;
robbiew577ff1a2002-12-05 20:12:28 +0000260 }
261 /* Child does this */
subrata_modak56207ce2009-03-23 13:35:39 +0000262 if (pid == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000263#ifdef UCLINUX
264 if (self_exec(argv0, "nddd", 2, id, key, child_process) < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400265 printf("self_exec failed\n");
robbiewd34d5812005-07-11 22:28:09 +0000266 TEST(msgctl(tid, IPC_RMID, 0));
subrata_modak56207ce2009-03-23 13:35:39 +0000267 if (TEST_RETURN < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400268 printf("msgctl() error in cleanup: %s\n",
269 strerror(errno));
robbiewd34d5812005-07-11 22:28:09 +0000270 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400271 return FAIL;
robbiewd34d5812005-07-11 22:28:09 +0000272 }
273#else
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400274 exit(doreader(key, id, 1, child_process, nreps));
robbiewd34d5812005-07-11 22:28:09 +0000275#endif
robbiew577ff1a2002-12-05 20:12:28 +0000276 }
277 /* Parent does this */
278 mykid = pid;
279 procstat = 2;
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400280 ret = dowriter(key, id, 1, child_process, nreps);
281 wait(&status);
282
283 if (ret != PASS)
284 exit(FAIL);
285
286 if ((!WIFEXITED(status) || (WEXITSTATUS(status) != PASS)))
287 exit(FAIL);
288
robbiew577ff1a2002-12-05 20:12:28 +0000289 TEST(msgctl(id, IPC_RMID, 0));
subrata_modak56207ce2009-03-23 13:35:39 +0000290 if (TEST_RETURN < 0) {
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400291 printf("msgctl() errno %d: %s\n",
292 TEST_ERRNO, strerror(TEST_ERRNO));
293
294 return FAIL;
robbiew577ff1a2002-12-05 20:12:28 +0000295 }
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400296 return PASS;
robbiew577ff1a2002-12-05 20:12:28 +0000297}
298
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400299static void sig_handler(void)
robbiew577ff1a2002-12-05 20:12:28 +0000300{
301}
302
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400303void setup(void)
robbiew577ff1a2002-12-05 20:12:28 +0000304{
subrata_modak5b693742008-02-22 08:33:53 +0000305 int nr_msgqs;
306
robbiewf6e92cd2003-01-17 21:06:36 +0000307 tst_tmpdir();
subrata_modak4bb656a2009-02-26 12:02:09 +0000308
subrata_modak56207ce2009-03-23 13:35:39 +0000309 tst_sig(FORK, DEF_HANDLER, cleanup);
subrata_modak4bb656a2009-02-26 12:02:09 +0000310
subrata_modak56207ce2009-03-23 13:35:39 +0000311 TEST_PAUSE;
robbiewef4118b2003-01-17 18:56:04 +0000312
subrata_modak5b693742008-02-22 08:33:53 +0000313 nr_msgqs = get_max_msgqueues();
314 if (nr_msgqs < 0)
315 cleanup();
316
317 nr_msgqs -= get_used_msgqueues();
subrata_modak56207ce2009-03-23 13:35:39 +0000318 if (nr_msgqs <= 0) {
319 tst_resm(TBROK,
320 "Max number of message queues already used, cannot create more.");
subrata_modak4bb656a2009-02-26 12:02:09 +0000321 cleanup();
subrata_modakbdbaec52009-02-26 12:14:51 +0000322 }
subrata_modak5b693742008-02-22 08:33:53 +0000323
324 /*
325 * Since msgmni scales to the memory size, it may reach huge values
326 * that are not necessary for this test.
327 * That's why we define NR_MSGQUEUES as a high boundary for it.
328 */
329 MSGMNI = min(nr_msgqs, NR_MSGQUEUES);
robbiew577ff1a2002-12-05 20:12:28 +0000330}
331
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400332void cleanup(void)
robbiew577ff1a2002-12-05 20:12:28 +0000333{
334 int status;
Cyril Hrubis9e4b1172014-09-23 13:10:52 +0200335
robbiew577ff1a2002-12-05 20:12:28 +0000336#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000337 tst_resm(TINFO, "Removing the message queue");
robbiew577ff1a2002-12-05 20:12:28 +0000338#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000339 fflush(stdout);
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800340 (void)msgctl(tid, IPC_RMID, NULL);
341 if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
342 (void)msgctl(tid, IPC_RMID, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000343 tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800344
subrata_modak56207ce2009-03-23 13:35:39 +0000345 }
robbiew577ff1a2002-12-05 20:12:28 +0000346
subrata_modak56207ce2009-03-23 13:35:39 +0000347 fflush(stdout);
Stanislav Kholmanskikh119cf4a2013-11-08 16:16:18 +0400348
robbiewf6e92cd2003-01-17 21:06:36 +0000349 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700350}