@@ -39,10 +39,12 @@ struct child_data {
3939
4040static int epoll_fd ;
4141static struct child_data * children ;
42+ static struct epoll_event * evs ;
43+ static int tests ;
4244static int num_children ;
4345static bool terminate ;
4446
45- static void drain_output ( bool flush ) ;
47+ static int startup_pipe [ 2 ] ;
4648
4749static int num_processors (void )
4850{
@@ -81,13 +83,37 @@ static void child_start(struct child_data *child, const char *program)
8183 exit (EXIT_FAILURE );
8284 }
8385
86+ /*
87+ * Duplicate the read side of the startup pipe to
88+ * FD 3 so we can close everything else.
89+ */
90+ ret = dup2 (startup_pipe [0 ], 3 );
91+ if (ret == -1 ) {
92+ fprintf (stderr , "dup2() %d\n" , errno );
93+ exit (EXIT_FAILURE );
94+ }
95+
8496 /*
8597 * Very dumb mechanism to clean open FDs other than
8698 * stdio. We don't want O_CLOEXEC for the pipes...
8799 */
88- for (i = 3 ; i < 8192 ; i ++ )
100+ for (i = 4 ; i < 8192 ; i ++ )
89101 close (i );
90102
103+ /*
104+ * Read from the startup pipe, there should be no data
105+ * and we should block until it is closed. We just
106+ * carry on on error since this isn't super critical.
107+ */
108+ ret = read (3 , & i , sizeof (i ));
109+ if (ret < 0 )
110+ fprintf (stderr , "read(startp pipe) failed: %s (%d)\n" ,
111+ strerror (errno ), errno );
112+ if (ret > 0 )
113+ fprintf (stderr , "%d bytes of data on startup pipe\n" ,
114+ ret );
115+ close (3 );
116+
91117 ret = execl (program , program , NULL );
92118 fprintf (stderr , "execl(%s) failed: %d (%s)\n" ,
93119 program , errno , strerror (errno ));
@@ -112,12 +138,6 @@ static void child_start(struct child_data *child, const char *program)
112138 ksft_exit_fail_msg ("%s EPOLL_CTL_ADD failed: %s (%d)\n" ,
113139 child -> name , strerror (errno ), errno );
114140 }
115-
116- /*
117- * Keep output flowing during child startup so logs
118- * are more timely, can help debugging.
119- */
120- drain_output (false);
121141 }
122142}
123143
@@ -290,12 +310,12 @@ static void start_fpsimd(struct child_data *child, int cpu, int copy)
290310{
291311 int ret ;
292312
293- child_start (child , "./fpsimd-test" );
294-
295313 ret = asprintf (& child -> name , "FPSIMD-%d-%d" , cpu , copy );
296314 if (ret == -1 )
297315 ksft_exit_fail_msg ("asprintf() failed\n" );
298316
317+ child_start (child , "./fpsimd-test" );
318+
299319 ksft_print_msg ("Started %s\n" , child -> name );
300320}
301321
@@ -307,29 +327,29 @@ static void start_sve(struct child_data *child, int vl, int cpu)
307327 if (ret < 0 )
308328 ksft_exit_fail_msg ("Failed to set SVE VL %d\n" , vl );
309329
310- child_start (child , "./sve-test" );
311-
312330 ret = asprintf (& child -> name , "SVE-VL-%d-%d" , vl , cpu );
313331 if (ret == -1 )
314332 ksft_exit_fail_msg ("asprintf() failed\n" );
315333
334+ child_start (child , "./sve-test" );
335+
316336 ksft_print_msg ("Started %s\n" , child -> name );
317337}
318338
319339static void start_ssve (struct child_data * child , int vl , int cpu )
320340{
321341 int ret ;
322342
343+ ret = asprintf (& child -> name , "SSVE-VL-%d-%d" , vl , cpu );
344+ if (ret == -1 )
345+ ksft_exit_fail_msg ("asprintf() failed\n" );
346+
323347 ret = prctl (PR_SME_SET_VL , vl | PR_SME_VL_INHERIT );
324348 if (ret < 0 )
325349 ksft_exit_fail_msg ("Failed to set SME VL %d\n" , ret );
326350
327351 child_start (child , "./ssve-test" );
328352
329- ret = asprintf (& child -> name , "SSVE-VL-%d-%d" , vl , cpu );
330- if (ret == -1 )
331- ksft_exit_fail_msg ("asprintf() failed\n" );
332-
333353 ksft_print_msg ("Started %s\n" , child -> name );
334354}
335355
@@ -341,12 +361,12 @@ static void start_za(struct child_data *child, int vl, int cpu)
341361 if (ret < 0 )
342362 ksft_exit_fail_msg ("Failed to set SME VL %d\n" , ret );
343363
344- child_start (child , "./za-test" );
345-
346364 ret = asprintf (& child -> name , "ZA-VL-%d-%d" , vl , cpu );
347365 if (ret == -1 )
348366 ksft_exit_fail_msg ("asprintf() failed\n" );
349367
368+ child_start (child , "./za-test" );
369+
350370 ksft_print_msg ("Started %s\n" , child -> name );
351371}
352372
@@ -375,20 +395,20 @@ static void probe_vls(int vls[], int *vl_count, int set_vl)
375395/* Handle any pending output without blocking */
376396static void drain_output (bool flush )
377397{
378- struct epoll_event ev ;
379398 int ret = 1 ;
399+ int i ;
380400
381401 while (ret > 0 ) {
382- ret = epoll_wait (epoll_fd , & ev , 1 , 0 );
402+ ret = epoll_wait (epoll_fd , evs , tests , 0 );
383403 if (ret < 0 ) {
384404 if (errno == EINTR )
385405 continue ;
386406 ksft_print_msg ("epoll_wait() failed: %s (%d)\n" ,
387407 strerror (errno ), errno );
388408 }
389409
390- if ( ret == 1 )
391- child_output (ev .data .ptr , ev .events , flush );
410+ for ( i = 0 ; i < ret ; i ++ )
411+ child_output (evs [ i ] .data .ptr , evs [ i ] .events , flush );
392412 }
393413}
394414
@@ -401,10 +421,11 @@ int main(int argc, char **argv)
401421{
402422 int ret ;
403423 int timeout = 10 ;
404- int cpus , tests , i , j , c ;
424+ int cpus , i , j , c ;
405425 int sve_vl_count , sme_vl_count , fpsimd_per_cpu ;
426+ bool all_children_started = false;
427+ int seen_children ;
406428 int sve_vls [MAX_VLS ], sme_vls [MAX_VLS ];
407- struct epoll_event ev ;
408429 struct sigaction sa ;
409430
410431 while ((c = getopt_long (argc , argv , "t:" , options , NULL )) != -1 ) {
@@ -465,6 +486,12 @@ int main(int argc, char **argv)
465486 strerror (errno ), ret );
466487 epoll_fd = ret ;
467488
489+ /* Create a pipe which children will block on before execing */
490+ ret = pipe (startup_pipe );
491+ if (ret != 0 )
492+ ksft_exit_fail_msg ("Failed to create startup pipe: %s (%d)\n" ,
493+ strerror (errno ), errno );
494+
468495 /* Get signal handers ready before we start any children */
469496 memset (& sa , 0 , sizeof (sa ));
470497 sa .sa_sigaction = handle_exit_signal ;
@@ -484,6 +511,11 @@ int main(int argc, char **argv)
484511 ksft_print_msg ("Failed to install SIGCHLD handler: %s (%d)\n" ,
485512 strerror (errno ), errno );
486513
514+ evs = calloc (tests , sizeof (* evs ));
515+ if (!evs )
516+ ksft_exit_fail_msg ("Failed to allocated %d epoll events\n" ,
517+ tests );
518+
487519 for (i = 0 ; i < cpus ; i ++ ) {
488520 for (j = 0 ; j < fpsimd_per_cpu ; j ++ )
489521 start_fpsimd (& children [num_children ++ ], i , j );
@@ -497,6 +529,13 @@ int main(int argc, char **argv)
497529 }
498530 }
499531
532+ /*
533+ * All children started, close the startup pipe and let them
534+ * run.
535+ */
536+ close (startup_pipe [0 ]);
537+ close (startup_pipe [1 ]);
538+
500539 for (;;) {
501540 /* Did we get a signal asking us to exit? */
502541 if (terminate )
@@ -510,7 +549,7 @@ int main(int argc, char **argv)
510549 * useful in emulation where we will both be slow and
511550 * likely to have a large set of VLs.
512551 */
513- ret = epoll_wait (epoll_fd , & ev , 1 , 1000 );
552+ ret = epoll_wait (epoll_fd , evs , tests , 1000 );
514553 if (ret < 0 ) {
515554 if (errno == EINTR )
516555 continue ;
@@ -519,13 +558,40 @@ int main(int argc, char **argv)
519558 }
520559
521560 /* Output? */
522- if (ret == 1 ) {
523- child_output (ev .data .ptr , ev .events , false);
561+ if (ret > 0 ) {
562+ for (i = 0 ; i < ret ; i ++ ) {
563+ child_output (evs [i ].data .ptr , evs [i ].events ,
564+ false);
565+ }
524566 continue ;
525567 }
526568
527569 /* Otherwise epoll_wait() timed out */
528570
571+ /*
572+ * If the child processes have not produced output they
573+ * aren't actually running the tests yet .
574+ */
575+ if (!all_children_started ) {
576+ seen_children = 0 ;
577+
578+ for (i = 0 ; i < num_children ; i ++ )
579+ if (children [i ].output_seen ||
580+ children [i ].exited )
581+ seen_children ++ ;
582+
583+ if (seen_children != num_children ) {
584+ ksft_print_msg ("Waiting for %d children\n" ,
585+ num_children - seen_children );
586+ continue ;
587+ }
588+
589+ all_children_started = true;
590+ }
591+
592+ ksft_print_msg ("Sending signals, timeout remaining: %d\n" ,
593+ timeout );
594+
529595 for (i = 0 ; i < num_children ; i ++ )
530596 child_tickle (& children [i ]);
531597
0 commit comments