1
+ // SPDX-License-Identifier: GPL-2.0-or-later
1
2
/*
2
3
* Copyright (c) International Business Machines Corp., 2002
3
- *
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.
8
- *
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.
13
- *
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
4
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
17
5
*
18
6
* 06/30/2001 Port to Linux [email protected]
19
7
* 11/06/2002 Port to LTP [email protected]
20
- */
21
-
22
- /*
8
+ * 10/21/2020 Convert to new api [email protected]
9
+ *
23
10
* Get and manipulate a message queue.
24
11
*/
25
12
31
18
#include <stdlib.h>
32
19
#include <stdio.h>
33
20
#include <unistd.h>
34
- #include <values.h>
35
21
#include <sys/types.h>
36
22
#include <sys/wait.h>
37
23
#include <sys/stat.h>
38
24
#include <sys/ipc.h>
39
25
#include <sys/msg.h>
40
- #include "test.h"
41
- #include "ipcmsg.h"
42
- #include "libmsgctl.h"
26
+ #include "tst_test.h"
27
+ #include "libnewipc.h"
28
+ #include "tst_safe_sysv_ipc.h"
29
+ #include "msgstress_common.h"
43
30
44
- char * TCID = "msgstress01" ;
45
- int TST_TOTAL = 1 ;
46
-
47
- #ifndef CONFIG_COLDFIRE
48
- #define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
49
- #else
50
- #define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
51
- #endif
31
+ #define MAXNPROCS 1000000
52
32
#define MAXNREPS 100000
53
33
54
34
static key_t keyarray [MAXNPROCS ];
55
- static int pidarray [MAXNPROCS ];
56
35
static int tid ;
57
36
static int MSGMNI , nprocs , nreps ;
58
- static int procstat ;
59
- static int mykid ;
60
-
61
- void setup (void );
62
- void cleanup (void );
63
-
64
- static int dotest (key_t key , int child_process );
65
- static void sig_handler ();
66
-
67
37
static char * opt_nprocs ;
68
38
static char * opt_nreps ;
39
+ static void cleanup (void );
69
40
70
- static option_t options [] = {
71
- {"n:" , NULL , & opt_nprocs },
72
- {"l:" , NULL , & opt_nreps },
73
- {NULL , NULL , NULL },
41
+ static struct tst_option options [] = {
42
+ {"n:" , & opt_nprocs , "-n N Number of processes" },
43
+ {"l:" , & opt_nreps , "-l N Number of iterations" },
44
+ {NULL , NULL , NULL }
74
45
};
75
46
76
- static void usage (void )
77
- {
78
- printf (" -n Number of processes\n" );
79
- printf (" -l Number of iterations\n" );
80
- }
81
-
82
- int main (int argc , char * * argv )
47
+ static void dotest (key_t key , int child_process )
83
48
{
84
- int i , j , ok , pid ;
85
- int count , status ;
86
- struct sigaction act ;
87
-
88
- tst_parse_opts (argc , argv , options , usage );
89
-
90
- setup ();
49
+ int pid ;
91
50
92
- nreps = MAXNREPS ;
93
- nprocs = MSGMNI ;
51
+ tid = SAFE_MSGGET (key , IPC_CREAT | S_IRUSR | S_IWUSR );
94
52
95
- if (opt_nreps ) {
96
- nreps = atoi (opt_nreps );
97
- if (nreps > MAXNREPS ) {
98
- tst_resm (TINFO ,
99
- "Requested number of iterations too large, "
100
- "setting to Max. of %d" , MAXNREPS );
101
- nreps = MAXNREPS ;
102
- }
53
+ pid = SAFE_FORK ();
54
+ if (pid == 0 ) {
55
+ do_reader (key , tid , 1 , child_process , nreps );
56
+ exit (0 );
103
57
}
104
58
105
- if ( opt_nprocs ) {
106
- nprocs = atoi ( opt_nprocs );
107
- if ( nprocs > MSGMNI ) {
108
- tst_resm ( TINFO ,
109
- "Requested number of processes too large, "
110
- "setting to Max. of %d" , MSGMNI );
111
- nprocs = MSGMNI ;
112
- }
113
- }
59
+ do_writer ( key , tid , 1 , child_process , nreps );
60
+ SAFE_WAIT ( NULL );
61
+ SAFE_MSGCTL ( tid , IPC_RMID , NULL );
62
+ }
63
+
64
+ static void verify_msgstress ( void )
65
+ {
66
+ int i , j , ok , pid ;
67
+ int count ;
114
68
115
69
srand (getpid ());
116
70
tid = -1 ;
117
71
118
- /* Setup signal handling routine */
119
- memset (& act , 0 , sizeof (act ));
120
- act .sa_handler = sig_handler ;
121
- sigemptyset (& act .sa_mask );
122
- sigaddset (& act .sa_mask , SIGTERM );
123
- if (sigaction (SIGTERM , & act , NULL ) < 0 ) {
124
- tst_brkm (TFAIL , NULL , "Sigset SIGTERM failed" );
125
- }
126
- /* Set up array of unique keys for use in allocating message
127
- * queues
128
- */
72
+ /* Set up array of unique keys for use in allocating message queues */
129
73
for (i = 0 ; i < nprocs ; i ++ ) {
130
74
ok = 1 ;
131
75
do {
132
- /* Get random key */
133
76
keyarray [i ] = (key_t ) rand ();
134
77
/* Make sure key is unique and not private */
135
78
if (keyarray [i ] == IPC_PRIVATE ) {
@@ -146,156 +89,83 @@ int main(int argc, char **argv)
146
89
} while (ok == 0 );
147
90
}
148
91
149
- /* Fork a number of processes, each of which will
92
+ /*
93
+ * Fork a number of processes, each of which will
150
94
* create a message queue with one reader/writer
151
95
* pair which will read and write a number (iterations)
152
96
* of random length messages with specific values.
153
97
*/
154
-
155
98
for (i = 0 ; i < nprocs ; i ++ ) {
156
- fflush (stdout );
157
- if ((pid = FORK_OR_VFORK ()) < 0 ) {
158
- tst_brkm (TFAIL ,
159
- NULL ,
160
- "\tFork failed (may be OK if under stress)" );
161
- }
162
- /* Child does this */
99
+ pid = SAFE_FORK ();
163
100
if (pid == 0 ) {
164
- procstat = 1 ;
165
- exit (dotest ( keyarray [ i ], i ) );
101
+ dotest ( keyarray [ i ], i ) ;
102
+ exit (0 );
166
103
}
167
- pidarray [i ] = pid ;
168
104
}
169
105
170
106
count = 0 ;
107
+
171
108
while (1 ) {
172
- if ((wait (& status )) > 0 ) {
173
- if (status >> 8 != 0 ) {
174
- tst_brkm (TFAIL , NULL ,
175
- "Child exit status = %d" ,
176
- status >> 8 );
177
- }
109
+ if (wait (NULL ) > 0 ) {
178
110
count ++ ;
179
111
} else {
180
- if (errno != EINTR ) {
112
+ if (errno != EINTR )
181
113
break ;
182
- }
183
- #ifdef DEBUG
184
- tst_resm (TINFO , "Signal detected during wait" );
185
- #endif
186
114
}
187
115
}
188
- /* Make sure proper number of children exited */
189
- if (count != nprocs ) {
190
- tst_brkm (TFAIL ,
191
- NULL ,
192
- "Wrong number of children exited, Saw %d, Expected %d" ,
193
- count , nprocs );
194
- }
195
116
196
- tst_resm (TPASS , "Test ran successfully!" );
117
+ if (count != nprocs )
118
+ tst_brk (TFAIL , "Wrong number of children exited, Saw %d, Expected %d" ,
119
+ count , nprocs );
197
120
121
+ tst_res (TPASS , "Test ran successfully!" );
198
122
cleanup ();
199
- tst_exit ();
200
- }
201
-
202
- static int dotest (key_t key , int child_process )
203
- {
204
- int id , pid ;
205
- int ret , status ;
206
-
207
- sighold (SIGTERM );
208
- TEST (msgget (key , IPC_CREAT | S_IRUSR | S_IWUSR ));
209
- if (TEST_RETURN < 0 ) {
210
- printf ("msgget() error in child %d: %s\n" ,
211
- child_process , strerror (TEST_ERRNO ));
212
-
213
- return FAIL ;
214
- }
215
- tid = id = TEST_RETURN ;
216
- sigrelse (SIGTERM );
217
-
218
- fflush (stdout );
219
- if ((pid = FORK_OR_VFORK ()) < 0 ) {
220
- printf ("\tFork failed (may be OK if under stress)\n" );
221
- TEST (msgctl (tid , IPC_RMID , 0 ));
222
- if (TEST_RETURN < 0 ) {
223
- printf ("mscgtl() error in cleanup: %s\n" ,
224
- strerror (TEST_ERRNO ));
225
- }
226
- return FAIL ;
227
- }
228
- /* Child does this */
229
- if (pid == 0 )
230
- exit (doreader (key , id , 1 , child_process , nreps ));
231
- /* Parent does this */
232
- mykid = pid ;
233
- procstat = 2 ;
234
- ret = dowriter (key , id , 1 , child_process , nreps );
235
- wait (& status );
236
-
237
- if (ret != PASS )
238
- exit (FAIL );
239
-
240
- if ((!WIFEXITED (status ) || (WEXITSTATUS (status ) != PASS )))
241
- exit (FAIL );
242
-
243
- TEST (msgctl (id , IPC_RMID , 0 ));
244
- if (TEST_RETURN < 0 ) {
245
- printf ("msgctl() errno %d: %s\n" ,
246
- TEST_ERRNO , strerror (TEST_ERRNO ));
247
-
248
- return FAIL ;
249
- }
250
- return PASS ;
251
123
}
252
124
253
- static void sig_handler (void )
254
- {
255
- }
256
-
257
- void setup (void )
125
+ static void setup (void )
258
126
{
259
127
int nr_msgqs ;
260
128
261
- tst_tmpdir ( );
129
+ SAFE_FILE_SCANF ( "/proc/sys/kernel/msgmni" , "%d" , & nr_msgqs );
262
130
263
- tst_sig (FORK , DEF_HANDLER , cleanup );
131
+ nr_msgqs -= GET_USED_QUEUES ();
132
+ if (nr_msgqs <= 0 )
133
+ tst_brk (TCONF , "Max number of message queues already used, "
134
+ "cannot create more." );
264
135
265
- TEST_PAUSE ;
136
+ MSGMNI = min ( nr_msgqs , NR_MSGQUEUES ) ;
266
137
267
- nr_msgqs = get_max_msgqueues ();
268
- if (nr_msgqs < 0 )
269
- cleanup ();
138
+ if (opt_nreps ) {
139
+ nreps = SAFE_STRTOL (opt_nreps , 1 , INT_MAX );
140
+ nreps = min (nreps , MAXNREPS );
141
+ } else {
142
+ nreps = MAXNREPS ;
143
+ }
270
144
271
- nr_msgqs -= get_used_msgqueues ();
272
- if (nr_msgqs <= 0 ) {
273
- tst_resm (TBROK ,
274
- "Max number of message queues already used, cannot create more." );
275
- cleanup ();
145
+ if (opt_nprocs ) {
146
+ nprocs = SAFE_STRTOL (opt_nprocs , 1 , INT_MAX );
147
+ nprocs = min (nprocs , MAXNPROCS );
148
+ nprocs = min (nprocs , MSGMNI );
149
+ } else {
150
+ nprocs = MSGMNI ;
276
151
}
277
152
278
- /*
279
- * Since msgmni scales to the memory size, it may reach huge values
280
- * that are not necessary for this test.
281
- * That's why we define NR_MSGQUEUES as a high boundary for it.
282
- */
283
- MSGMNI = min (nr_msgqs , NR_MSGQUEUES );
153
+ SAFE_SIGNAL (SIGTERM , SIG_IGN );
154
+ tst_res (TINFO , "Number of message queues is %d, process is %d, "
155
+ "iterations is %d" , MSGMNI , nprocs , nreps );
284
156
}
285
157
286
158
void cleanup (void )
287
159
{
288
- int status ;
289
-
290
- #ifdef DEBUG
291
- tst_resm (TINFO , "Removing the message queue" );
292
- #endif
293
- (void )msgctl (tid , IPC_RMID , NULL );
294
- if ((status = msgctl (tid , IPC_STAT , NULL )) != -1 ) {
295
- (void )msgctl (tid , IPC_RMID , NULL );
296
- tst_resm (TFAIL , "msgctl(tid, IPC_RMID) failed" );
297
-
298
- }
299
-
300
- tst_rmdir ();
160
+ if (tid >= 0 )
161
+ SAFE_MSGCTL (tid , IPC_RMID , NULL );
301
162
}
163
+
164
+ static struct tst_test test = {
165
+ .needs_tmpdir = 1 ,
166
+ .options = options ,
167
+ .setup = setup ,
168
+ .cleanup = cleanup ,
169
+ .forks_child = 1 ,
170
+ .test_all = verify_msgstress ,
171
+ };
0 commit comments