1+ // SPDX-License-Identifier: GPL-2.0-or-later
12/*
23 * 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.
175 *
186 * 06/30/2001 Port to Linux [email protected] 197 * 11/06/2002 Port to LTP [email protected] 20- */
21-
22- /*
8+ * 10/21/2020 Convert to new api [email protected] 9+ *
2310 * Get and manipulate a message queue.
2411 */
2512
3118#include <stdlib.h>
3219#include <stdio.h>
3320#include <unistd.h>
34- #include <values.h>
3521#include <sys/types.h>
3622#include <sys/wait.h>
3723#include <sys/stat.h>
3824#include <sys/ipc.h>
3925#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"
4330
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
5232#define MAXNREPS 100000
5333
5434static key_t keyarray [MAXNPROCS ];
55- static int pidarray [MAXNPROCS ];
5635static int tid ;
5736static 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-
6737static char * opt_nprocs ;
6838static char * opt_nreps ;
39+ static void cleanup (void );
6940
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 }
7445};
7546
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 )
8348{
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 ;
9150
92- nreps = MAXNREPS ;
93- nprocs = MSGMNI ;
51+ tid = SAFE_MSGGET (key , IPC_CREAT | S_IRUSR | S_IWUSR );
9452
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 );
10357 }
10458
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 ;
11468
11569 srand (getpid ());
11670 tid = -1 ;
11771
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 */
12973 for (i = 0 ; i < nprocs ; i ++ ) {
13074 ok = 1 ;
13175 do {
132- /* Get random key */
13376 keyarray [i ] = (key_t ) rand ();
13477 /* Make sure key is unique and not private */
13578 if (keyarray [i ] == IPC_PRIVATE ) {
@@ -146,156 +89,83 @@ int main(int argc, char **argv)
14689 } while (ok == 0 );
14790 }
14891
149- /* Fork a number of processes, each of which will
92+ /*
93+ * Fork a number of processes, each of which will
15094 * create a message queue with one reader/writer
15195 * pair which will read and write a number (iterations)
15296 * of random length messages with specific values.
15397 */
154-
15598 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 ();
163100 if (pid == 0 ) {
164- procstat = 1 ;
165- exit (dotest ( keyarray [ i ], i ) );
101+ dotest ( keyarray [ i ], i ) ;
102+ exit (0 );
166103 }
167- pidarray [i ] = pid ;
168104 }
169105
170106 count = 0 ;
107+
171108 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 ) {
178110 count ++ ;
179111 } else {
180- if (errno != EINTR ) {
112+ if (errno != EINTR )
181113 break ;
182- }
183- #ifdef DEBUG
184- tst_resm (TINFO , "Signal detected during wait" );
185- #endif
186114 }
187115 }
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- }
195116
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 );
197120
121+ tst_res (TPASS , "Test ran successfully!" );
198122 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 ;
251123}
252124
253- static void sig_handler (void )
254- {
255- }
256-
257- void setup (void )
125+ static void setup (void )
258126{
259127 int nr_msgqs ;
260128
261- tst_tmpdir ( );
129+ SAFE_FILE_SCANF ( "/proc/sys/kernel/msgmni" , "%d" , & nr_msgqs );
262130
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." );
264135
265- TEST_PAUSE ;
136+ MSGMNI = min ( nr_msgqs , NR_MSGQUEUES ) ;
266137
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+ }
270144
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 ;
276151 }
277152
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 );
284156}
285157
286158void cleanup (void )
287159{
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 );
301162}
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