@@ -39,10 +39,12 @@ struct child_data {
39
39
40
40
static int epoll_fd ;
41
41
static struct child_data * children ;
42
+ static struct epoll_event * evs ;
43
+ static int tests ;
42
44
static int num_children ;
43
45
static bool terminate ;
44
46
45
- static void drain_output ( bool flush ) ;
47
+ static int startup_pipe [ 2 ] ;
46
48
47
49
static int num_processors (void )
48
50
{
@@ -81,13 +83,37 @@ static void child_start(struct child_data *child, const char *program)
81
83
exit (EXIT_FAILURE );
82
84
}
83
85
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
+
84
96
/*
85
97
* Very dumb mechanism to clean open FDs other than
86
98
* stdio. We don't want O_CLOEXEC for the pipes...
87
99
*/
88
- for (i = 3 ; i < 8192 ; i ++ )
100
+ for (i = 4 ; i < 8192 ; i ++ )
89
101
close (i );
90
102
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
+
91
117
ret = execl (program , program , NULL );
92
118
fprintf (stderr , "execl(%s) failed: %d (%s)\n" ,
93
119
program , errno , strerror (errno ));
@@ -112,12 +138,6 @@ static void child_start(struct child_data *child, const char *program)
112
138
ksft_exit_fail_msg ("%s EPOLL_CTL_ADD failed: %s (%d)\n" ,
113
139
child -> name , strerror (errno ), errno );
114
140
}
115
-
116
- /*
117
- * Keep output flowing during child startup so logs
118
- * are more timely, can help debugging.
119
- */
120
- drain_output (false);
121
141
}
122
142
}
123
143
@@ -290,12 +310,12 @@ static void start_fpsimd(struct child_data *child, int cpu, int copy)
290
310
{
291
311
int ret ;
292
312
293
- child_start (child , "./fpsimd-test" );
294
-
295
313
ret = asprintf (& child -> name , "FPSIMD-%d-%d" , cpu , copy );
296
314
if (ret == -1 )
297
315
ksft_exit_fail_msg ("asprintf() failed\n" );
298
316
317
+ child_start (child , "./fpsimd-test" );
318
+
299
319
ksft_print_msg ("Started %s\n" , child -> name );
300
320
}
301
321
@@ -307,29 +327,29 @@ static void start_sve(struct child_data *child, int vl, int cpu)
307
327
if (ret < 0 )
308
328
ksft_exit_fail_msg ("Failed to set SVE VL %d\n" , vl );
309
329
310
- child_start (child , "./sve-test" );
311
-
312
330
ret = asprintf (& child -> name , "SVE-VL-%d-%d" , vl , cpu );
313
331
if (ret == -1 )
314
332
ksft_exit_fail_msg ("asprintf() failed\n" );
315
333
334
+ child_start (child , "./sve-test" );
335
+
316
336
ksft_print_msg ("Started %s\n" , child -> name );
317
337
}
318
338
319
339
static void start_ssve (struct child_data * child , int vl , int cpu )
320
340
{
321
341
int ret ;
322
342
343
+ ret = asprintf (& child -> name , "SSVE-VL-%d-%d" , vl , cpu );
344
+ if (ret == -1 )
345
+ ksft_exit_fail_msg ("asprintf() failed\n" );
346
+
323
347
ret = prctl (PR_SME_SET_VL , vl | PR_SME_VL_INHERIT );
324
348
if (ret < 0 )
325
349
ksft_exit_fail_msg ("Failed to set SME VL %d\n" , ret );
326
350
327
351
child_start (child , "./ssve-test" );
328
352
329
- ret = asprintf (& child -> name , "SSVE-VL-%d-%d" , vl , cpu );
330
- if (ret == -1 )
331
- ksft_exit_fail_msg ("asprintf() failed\n" );
332
-
333
353
ksft_print_msg ("Started %s\n" , child -> name );
334
354
}
335
355
@@ -341,12 +361,12 @@ static void start_za(struct child_data *child, int vl, int cpu)
341
361
if (ret < 0 )
342
362
ksft_exit_fail_msg ("Failed to set SME VL %d\n" , ret );
343
363
344
- child_start (child , "./za-test" );
345
-
346
364
ret = asprintf (& child -> name , "ZA-VL-%d-%d" , vl , cpu );
347
365
if (ret == -1 )
348
366
ksft_exit_fail_msg ("asprintf() failed\n" );
349
367
368
+ child_start (child , "./za-test" );
369
+
350
370
ksft_print_msg ("Started %s\n" , child -> name );
351
371
}
352
372
@@ -375,20 +395,20 @@ static void probe_vls(int vls[], int *vl_count, int set_vl)
375
395
/* Handle any pending output without blocking */
376
396
static void drain_output (bool flush )
377
397
{
378
- struct epoll_event ev ;
379
398
int ret = 1 ;
399
+ int i ;
380
400
381
401
while (ret > 0 ) {
382
- ret = epoll_wait (epoll_fd , & ev , 1 , 0 );
402
+ ret = epoll_wait (epoll_fd , evs , tests , 0 );
383
403
if (ret < 0 ) {
384
404
if (errno == EINTR )
385
405
continue ;
386
406
ksft_print_msg ("epoll_wait() failed: %s (%d)\n" ,
387
407
strerror (errno ), errno );
388
408
}
389
409
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 );
392
412
}
393
413
}
394
414
@@ -401,10 +421,11 @@ int main(int argc, char **argv)
401
421
{
402
422
int ret ;
403
423
int timeout = 10 ;
404
- int cpus , tests , i , j , c ;
424
+ int cpus , i , j , c ;
405
425
int sve_vl_count , sme_vl_count , fpsimd_per_cpu ;
426
+ bool all_children_started = false;
427
+ int seen_children ;
406
428
int sve_vls [MAX_VLS ], sme_vls [MAX_VLS ];
407
- struct epoll_event ev ;
408
429
struct sigaction sa ;
409
430
410
431
while ((c = getopt_long (argc , argv , "t:" , options , NULL )) != -1 ) {
@@ -465,6 +486,12 @@ int main(int argc, char **argv)
465
486
strerror (errno ), ret );
466
487
epoll_fd = ret ;
467
488
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
+
468
495
/* Get signal handers ready before we start any children */
469
496
memset (& sa , 0 , sizeof (sa ));
470
497
sa .sa_sigaction = handle_exit_signal ;
@@ -484,6 +511,11 @@ int main(int argc, char **argv)
484
511
ksft_print_msg ("Failed to install SIGCHLD handler: %s (%d)\n" ,
485
512
strerror (errno ), errno );
486
513
514
+ evs = calloc (tests , sizeof (* evs ));
515
+ if (!evs )
516
+ ksft_exit_fail_msg ("Failed to allocated %d epoll events\n" ,
517
+ tests );
518
+
487
519
for (i = 0 ; i < cpus ; i ++ ) {
488
520
for (j = 0 ; j < fpsimd_per_cpu ; j ++ )
489
521
start_fpsimd (& children [num_children ++ ], i , j );
@@ -497,6 +529,13 @@ int main(int argc, char **argv)
497
529
}
498
530
}
499
531
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
+
500
539
for (;;) {
501
540
/* Did we get a signal asking us to exit? */
502
541
if (terminate )
@@ -510,7 +549,7 @@ int main(int argc, char **argv)
510
549
* useful in emulation where we will both be slow and
511
550
* likely to have a large set of VLs.
512
551
*/
513
- ret = epoll_wait (epoll_fd , & ev , 1 , 1000 );
552
+ ret = epoll_wait (epoll_fd , evs , tests , 1000 );
514
553
if (ret < 0 ) {
515
554
if (errno == EINTR )
516
555
continue ;
@@ -519,13 +558,40 @@ int main(int argc, char **argv)
519
558
}
520
559
521
560
/* 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
+ }
524
566
continue ;
525
567
}
526
568
527
569
/* Otherwise epoll_wait() timed out */
528
570
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
+
529
595
for (i = 0 ; i < num_children ; i ++ )
530
596
child_tickle (& children [i ]);
531
597
0 commit comments