subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 1 | /* |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 2 | * Copyright (c) International Business Machines Corp., 2002 |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 3 | * |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 4 | * 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 8 | * |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 9 | * 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 13 | * |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 14 | * 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 17 | * |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 18 | * 06/30/2001 Port to Linux nsharoff@us.ibm.com |
| 19 | * 11/11/2002 Port to LTP dbarrera@us.ibm.com |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 20 | */ |
| 21 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 22 | /* |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 23 | * Get and manipulate a message queue. |
| 24 | * Same as msgctl09 but gets the actual msgmni value under procfs. |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 25 | */ |
| 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 40 | #include "ipcmsg.h" |
Peng Haitao | 1f1e15a | 2013-12-02 10:30:05 +0800 | [diff] [blame] | 41 | #include "../lib/libmsgctl.h" |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 42 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 43 | char *TCID = "msgctl11"; |
| 44 | int TST_TOTAL = 1; |
| 45 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 46 | #define MAXNREPS 1000 |
| 47 | #ifndef CONFIG_COLDFIRE |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 48 | #define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */ |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 49 | #else |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 50 | #define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */ |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 51 | #endif |
| 52 | #define MAXNKIDS 10 |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 53 | #define DEFNKIDS 2 |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 54 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 55 | static int maxnkids = MAXNKIDS; /* Used if pid_max is exceeded */ |
| 56 | static key_t keyarray[MAXNPROCS]; |
| 57 | static int pidarray[MAXNPROCS]; |
| 58 | static int rkidarray[MAXNKIDS]; |
| 59 | static int wkidarray[MAXNKIDS]; |
| 60 | static int tid; |
| 61 | static int nprocs, nreps, nkids, MSGMNI; |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 62 | static int maxnprocs; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 63 | static int procstat; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 64 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 65 | void setup(void); |
| 66 | void cleanup(void); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 67 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 68 | static void term(int); |
| 69 | static int dotest(key_t, int); |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 70 | static void dotest_iteration(int off); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 71 | static void cleanup_msgqueue(int i, int tid); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 72 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 73 | #ifdef UCLINUX |
| 74 | static char *argv0; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 75 | static key_t key_uclinux; |
| 76 | static int i_uclinux; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 77 | static int pid_uclinux; |
| 78 | static int child_process_uclinux; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 79 | static int rkid_uclinux; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 80 | |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 81 | static void do_child_1_uclinux(void); |
| 82 | static void do_child_2_uclinux(void); |
| 83 | static void do_child_3_uclinux(void); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 84 | #endif |
| 85 | |
| 86 | int main(int argc, char **argv) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 87 | { |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 88 | int i, j, ok; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 89 | |
| 90 | #ifdef UCLINUX |
Cyril Hrubis | 7422562 | 2014-06-02 17:54:38 +0200 | [diff] [blame] | 91 | const char *msg; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 92 | |
| 93 | argv0 = argv[0]; |
| 94 | |
Cyril Hrubis | 7422562 | 2014-06-02 17:54:38 +0200 | [diff] [blame] | 95 | if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL) |
Garrett Cooper | 60fa801 | 2010-11-22 13:50:58 -0800 | [diff] [blame] | 96 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 97 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 98 | maybe_run_child(&do_child_1_uclinux, "ndd", 1, &key_uclinux, |
| 99 | &i_uclinux); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 100 | 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_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 108 | if (argc == 1) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 109 | /* Set default parameters */ |
| 110 | nreps = MAXNREPS; |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 111 | nkids = DEFNKIDS; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 112 | } else if (argc == 4) { |
| 113 | if (atoi(argv[1]) > MAXNREPS) { |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 114 | tst_resm(TINFO, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 115 | "Requested number of iterations too large, setting to Max. of %d", |
| 116 | MAXNREPS); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 117 | nreps = MAXNREPS; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 118 | } else { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 119 | nreps = atoi(argv[1]); |
| 120 | } |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 121 | if (atoi(argv[2]) > maxnprocs) { |
| 122 | tst_resm(TINFO, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 123 | "Requested number of processes too large, setting to Max. of %d", |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 124 | maxnprocs); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 125 | } else { |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 126 | maxnprocs = atoi(argv[2]); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 127 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 128 | if (atoi(argv[3]) > maxnkids) { |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 129 | tst_resm(TINFO, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 130 | "Requested number of read/write pairs too large; setting to Max. of %d", |
| 131 | maxnkids); |
subrata_modak | 8bc4d77 | 2009-01-15 10:31:45 +0000 | [diff] [blame] | 132 | nkids = maxnkids; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 133 | } else { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 134 | nkids = atoi(argv[3]); |
| 135 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 136 | } else { |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 137 | tst_brkm(TCONF, cleanup, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 138 | " Usage: %s [ number of iterations number of processes number of read/write pairs ]", |
| 139 | argv[0]); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | procstat = 0; |
| 143 | srand48((unsigned)getpid() + (unsigned)(getppid() << 16)); |
| 144 | tid = -1; |
| 145 | |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 146 | /* Setup signal handling routine */ |
| 147 | if (sigset(SIGTERM, term) == SIG_ERR) |
| 148 | tst_brkm(TFAIL, cleanup, "Sigset SIGTERM failed"); |
| 149 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 150 | /* Set up array of unique keys for use in allocating message |
| 151 | * queues |
| 152 | */ |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 153 | for (i = 0; i < MSGMNI; i++) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 154 | ok = 1; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 155 | do { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 156 | /* Get random key */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 157 | keyarray[i] = (key_t) lrand48(); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 158 | /* Make sure key is unique and not private */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 159 | if (keyarray[i] == IPC_PRIVATE) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 160 | ok = 0; |
| 161 | continue; |
| 162 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 163 | for (j = 0; j < i; j++) { |
| 164 | if (keyarray[j] == keyarray[i]) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 165 | ok = 0; |
| 166 | break; |
| 167 | } |
| 168 | ok = 1; |
| 169 | } |
| 170 | } while (ok == 0); |
| 171 | } |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 172 | /* Fork a number of processes, each of which will |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 173 | * 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 Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 176 | * |
| 177 | * We do not fork more than maxnprocs at a time and |
| 178 | * we fork until all the message queues get used. |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 179 | */ |
| 180 | |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 181 | 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 | |
| 200 | static 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_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 208 | for (i = 0; i < nprocs; i++) { |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 209 | key = keyarray[off + i]; |
| 210 | |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 211 | if ((pid = FORK_OR_VFORK()) < 0) |
| 212 | tst_brkm(TFAIL, cleanup, |
| 213 | "Fork failed (may be OK if under stress)"); |
| 214 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 215 | /* Child does this */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 216 | if (pid == 0) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 217 | #ifdef UCLINUX |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 218 | if (self_exec(argv0, "ndd", 1, key, i) < 0) { |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 219 | printf("\tself_exec failed\n"); |
| 220 | exit(FAIL); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 221 | } |
| 222 | #else |
| 223 | procstat = 1; |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 224 | exit(dotest(key, i)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 225 | #endif |
| 226 | } |
| 227 | pidarray[i] = pid; |
| 228 | } |
| 229 | |
| 230 | count = 0; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 231 | while (1) { |
| 232 | if ((wait(&status)) > 0) { |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 233 | if (status >> 8 != PASS) |
| 234 | tst_brkm(TFAIL, cleanup, |
| 235 | "Child exit status = %d", status >> 8); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 236 | count++; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 237 | } else { |
| 238 | if (errno != EINTR) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 239 | break; |
| 240 | } |
| 241 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 242 | tst_resm(TINFO, "Signal detected during wait"); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 243 | #endif |
| 244 | } |
| 245 | } |
| 246 | /* Make sure proper number of children exited */ |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 247 | if (count != nprocs) |
| 248 | tst_brkm(TFAIL, cleanup, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 249 | "Wrong number of children exited, Saw %d, Expected %d", |
| 250 | count, nprocs); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 251 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 252 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 253 | #ifdef UCLINUX |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 254 | static void do_child_1_uclinux(void) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 255 | { |
| 256 | procstat = 1; |
| 257 | exit(dotest(key_uclinux, i_uclinux)); |
| 258 | } |
| 259 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 260 | static void do_child_2_uclinux(void) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 261 | { |
| 262 | procstat = 2; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 263 | exit(doreader(key_uclinux, tid, pid_uclinux, |
| 264 | child_process_uclinux, nreps)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 265 | } |
| 266 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 267 | static void do_child_3_uclinux(void) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 268 | { |
| 269 | procstat = 2; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 270 | exit(dowriter(key_uclinux, tid, rkid_uclinux, |
| 271 | child_process_uclinux, nreps)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 272 | } |
| 273 | #endif |
| 274 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 275 | static void cleanup_msgqueue(int i, int tid) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 276 | { |
| 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 Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 293 | printf("Msgctl error in cleanup_msgqueue %d\n", errno); |
| 294 | exit(FAIL); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 295 | } |
| 296 | } |
| 297 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 298 | static int dotest(key_t key, int child_process) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 299 | { |
| 300 | int id, pid; |
| 301 | int i, count, status, exit_status; |
| 302 | |
| 303 | sighold(SIGTERM); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 304 | if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 305 | printf("msgget() error in child %d: %s\n", |
| 306 | child_process, strerror(errno)); |
| 307 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 308 | } |
| 309 | tid = id; |
| 310 | sigrelse(SIGTERM); |
| 311 | |
| 312 | exit_status = PASS; |
| 313 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 314 | for (i = 0; i < nkids; i++) { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 315 | if ((pid = FORK_OR_VFORK()) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 316 | printf("Fork failure in the first child of child group %d\n", |
| 317 | child_process); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 318 | cleanup_msgqueue(i, tid); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 319 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 320 | } |
| 321 | /* First child does this */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 322 | if (pid == 0) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 323 | #ifdef UCLINUX |
| 324 | if (self_exec(argv0, "nddd", 2, key, getpid(), |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 325 | child_process) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 326 | printf("self_exec failed\n"); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 327 | cleanup_msgqueue(i, tid); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 328 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 329 | } |
| 330 | #else |
| 331 | procstat = 2; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 332 | exit(doreader(key, tid, getpid(), |
| 333 | child_process, nreps)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 334 | #endif |
| 335 | } |
| 336 | rkidarray[i] = pid; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 337 | if ((pid = FORK_OR_VFORK()) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 338 | printf("Fork failure in the second child of child group %d\n", |
| 339 | child_process); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 340 | /* |
| 341 | * Kill the reader child process |
| 342 | */ |
| 343 | (void)kill(rkidarray[i], SIGKILL); |
| 344 | |
| 345 | cleanup_msgqueue(i, tid); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 346 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 347 | } |
| 348 | /* Second child does this */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 349 | if (pid == 0) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 350 | #ifdef UCLINUX |
| 351 | if (self_exec(argv0, "nddd", 3, key, rkidarray[i], |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 352 | child_process) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 353 | printf("\tFork failure in the first child of child group %d\n", |
| 354 | child_process); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 355 | /* |
| 356 | * Kill the reader child process |
| 357 | */ |
| 358 | (void)kill(rkidarray[i], SIGKILL); |
| 359 | |
| 360 | cleanup_msgqueue(i, tid); |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 361 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 362 | } |
| 363 | #else |
| 364 | procstat = 2; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 365 | exit(dowriter(key, tid, rkidarray[i], |
| 366 | child_process, nreps)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 367 | #endif |
| 368 | } |
| 369 | wkidarray[i] = pid; |
| 370 | } |
| 371 | /* Parent does this */ |
| 372 | count = 0; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 373 | while (1) { |
| 374 | if ((wait(&status)) > 0) { |
| 375 | if (status >> 8 != PASS) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 376 | printf("Child exit status = %d from child group %d\n", |
| 377 | status >> 8, child_process); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 378 | for (i = 0; i < nkids; i++) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 379 | kill(rkidarray[i], SIGTERM); |
| 380 | kill(wkidarray[i], SIGTERM); |
| 381 | } |
| 382 | if (msgctl(tid, IPC_RMID, 0) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 383 | printf("msgctl() error: %s\n", |
| 384 | strerror(errno)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 385 | } |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 386 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 387 | } |
| 388 | count++; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 389 | } else { |
| 390 | if (errno != EINTR) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 391 | break; |
| 392 | } |
| 393 | } |
| 394 | } |
| 395 | /* Make sure proper number of children exited */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 396 | if (count != (nkids * 2)) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 397 | printf("Wrong number of children exited in child group %d, saw %d, expected %d\n", |
| 398 | child_process, count, (nkids * 2)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 399 | if (msgctl(tid, IPC_RMID, 0) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 400 | printf("msgctl() error: %s\n", strerror(errno)); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 401 | } |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 402 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 403 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 404 | if (msgctl(id, IPC_RMID, 0) < 0) { |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 405 | printf("msgctl() failure in child group %d: %s\n", |
| 406 | child_process, strerror(errno)); |
| 407 | return FAIL; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 408 | } |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 409 | return exit_status; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 410 | } |
| 411 | |
| 412 | /* ARGSUSED */ |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 413 | static void term(int sig) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 414 | { |
| 415 | int i; |
| 416 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 417 | if (procstat == 0) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 418 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 419 | tst_resm(TINFO, "SIGTERM signal received, test killing kids"); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 420 | #endif |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 421 | 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 427 | exit(FAIL); |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | return; |
| 432 | } |
| 433 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 434 | if (procstat == 2) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 435 | exit(PASS); |
| 436 | } |
| 437 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 438 | if (tid == -1) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 439 | exit(FAIL); |
| 440 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 441 | for (i = 0; i < nkids; i++) { |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 442 | if (rkidarray[i] > 0) |
| 443 | kill(rkidarray[i], SIGTERM); |
| 444 | if (wkidarray[i] > 0) |
| 445 | kill(wkidarray[i], SIGTERM); |
| 446 | } |
| 447 | } |
| 448 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 449 | void setup(void) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 450 | { |
subrata_modak | 8bc4d77 | 2009-01-15 10:31:45 +0000 | [diff] [blame] | 451 | int nr_msgqs, free_pids; |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 452 | |
| 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_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 459 | /* 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 Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 467 | tst_brkm(TBROK, cleanup, "get_max_msgqueues() failed"); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 468 | |
| 469 | MSGMNI = nr_msgqs - get_used_msgqueues(); |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 470 | if (MSGMNI <= 0) |
| 471 | tst_brkm(TBROK, cleanup, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 472 | "Max number of message queues already used, cannot create more."); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 473 | |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 474 | tst_resm(TINFO, "Found %d available message queues", MSGMNI); |
| 475 | |
Stanislav Kholmanskikh | 502e42f | 2014-06-30 14:48:23 +0400 | [diff] [blame] | 476 | free_pids = tst_get_free_pids(cleanup); |
subrata_modak | 8bc4d77 | 2009-01-15 10:31:45 +0000 | [diff] [blame] | 477 | if (free_pids < 0) { |
Stanislav Kholmanskikh | 31c09bc | 2014-02-25 18:40:26 +0400 | [diff] [blame] | 478 | tst_brkm(TBROK, cleanup, "Can't obtain free_pid count"); |
| 479 | } else if (!free_pids) { |
| 480 | tst_brkm(TBROK, cleanup, "No free pids"); |
subrata_modak | 8bc4d77 | 2009-01-15 10:31:45 +0000 | [diff] [blame] | 481 | } |
| 482 | |
Stanislav Kholmanskikh | d6e9b78 | 2014-02-25 18:40:27 +0400 | [diff] [blame] | 483 | /* 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_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 489 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 490 | tst_resm(TINFO, "Using upto %d pids", free_pids / 2); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 491 | } |
| 492 | |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 493 | void cleanup(void) |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 494 | { |
| 495 | int status; |
Stanislav Kholmanskikh | 119cf4a | 2013-11-08 16:16:18 +0400 | [diff] [blame] | 496 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 497 | /* |
| 498 | * Remove the message queue from the system |
| 499 | */ |
| 500 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 501 | tst_resm(TINFO, "Removing the message queue"); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 502 | #endif |
Garrett Cooper | df3eb16 | 2010-11-28 22:44:32 -0800 | [diff] [blame] | 503 | (void)msgctl(tid, IPC_RMID, NULL); |
| 504 | if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) { |
| 505 | (void)msgctl(tid, IPC_RMID, NULL); |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 506 | tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed"); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 507 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 508 | } |
| 509 | |
subrata_modak | 5b69374 | 2008-02-22 08:33:53 +0000 | [diff] [blame] | 510 | tst_rmdir(); |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 511 | } |