Skip to content

Commit 69218b5

Browse files
broonietiwai
authored andcommitted
kselftest/alsa: Run PCM tests for multiple cards in parallel
With each test taking 4 seconds the runtime of pcm-test can add up. Since generally each card in the system is physically independent and will be unaffected by what's going on with other cards we can mitigate this by testing each card in parallel. Make a list of cards as we enumerate the system and then start a thread for each, then join the threads to ensure they have all finished. The threads each run the same tests we currently run for each PCM on the card before exiting. The list of PCMs is kept global since it helps with global operations like working out our planned number of tests and identifying missing PCMs and it seemed neater to check for PCMs on the right card in the card thread than make every PCM loop iterate over cards as well. We don't run per-PCM tests in parallel since in embedded systems it can be the case that resources are shared between the PCMs and operations on one PCM on a card may constrain what can be done on another PCM on the same card leading to potentially unstable results. We use a mutex to ensure that the reporting of results is serialised and we don't have issues with anything like the current test number, we could do this in the kselftest framework but it seems like this might cause problems for other tests that are doing lower level testing and building in constrained environments such as nolibc so this seems more sensible. Note that the ordering of the tests can't be guaranteed as things stand, this does not seem like a major problem since the numbering of tests often changes as test programs are changed so results parsers are expected to rely on the test name rather than the test numbers. We also now prefix the machine generated test name when printing the description of the test since this is logged before streaming starts. On my two card desktop system this reduces the overall runtime by a third. Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 0d9eb7e commit 69218b5

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

tools/testing/selftests/alsa/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LDLIBS += -lasound
88
endif
99
CFLAGS += -L$(OUTPUT) -Wl,-rpath=./
1010

11+
LDLIBS+=-lpthread
12+
1113
OVERRIDE_TARGETS = 1
1214

1315
TEST_GEN_PROGS := mixer-test pcm-test

tools/testing/selftests/alsa/pcm-test.c

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,21 @@
1515
#include <stdbool.h>
1616
#include <errno.h>
1717
#include <assert.h>
18+
#include <pthread.h>
1819

1920
#include "../kselftest.h"
2021
#include "alsa-local.h"
2122

2223
typedef struct timespec timestamp_t;
2324

25+
struct card_data {
26+
int card;
27+
pthread_t thread;
28+
struct card_data *next;
29+
};
30+
31+
struct card_data *card_list = NULL;
32+
2433
struct pcm_data {
2534
snd_pcm_t *handle;
2635
int card;
@@ -36,6 +45,11 @@ struct pcm_data *pcm_list = NULL;
3645
int num_missing = 0;
3746
struct pcm_data *pcm_missing = NULL;
3847

48+
snd_config_t *default_pcm_config;
49+
50+
/* Lock while reporting results since kselftest doesn't */
51+
pthread_mutex_t results_lock = PTHREAD_MUTEX_INITIALIZER;
52+
3953
enum test_class {
4054
TEST_CLASS_DEFAULT,
4155
TEST_CLASS_SYSTEM,
@@ -141,6 +155,7 @@ static void find_pcms(void)
141155
snd_ctl_t *handle;
142156
snd_pcm_info_t *pcm_info;
143157
snd_config_t *config, *card_config, *pcm_config;
158+
struct card_data *card_data;
144159

145160
snd_pcm_info_alloca(&pcm_info);
146161

@@ -162,6 +177,13 @@ static void find_pcms(void)
162177

163178
card_config = conf_by_card(card);
164179

180+
card_data = calloc(1, sizeof(*card_data));
181+
if (!card_data)
182+
ksft_exit_fail_msg("Out of memory\n");
183+
card_data->card = card;
184+
card_data->next = card_list;
185+
card_list = card_data;
186+
165187
dev = -1;
166188
while (1) {
167189
if (snd_ctl_pcm_next_device(handle, &dev) < 0)
@@ -246,10 +268,6 @@ static void test_pcm_time(struct pcm_data *data, enum test_class class,
246268
bool skip = true;
247269
const char *desc;
248270

249-
desc = conf_get_string(pcm_cfg, "description", NULL, NULL);
250-
if (desc)
251-
ksft_print_msg("%s\n", desc);
252-
253271
switch (class) {
254272
case TEST_CLASS_DEFAULT:
255273
test_class_name = "default";
@@ -262,6 +280,15 @@ static void test_pcm_time(struct pcm_data *data, enum test_class class,
262280
break;
263281
}
264282

283+
desc = conf_get_string(pcm_cfg, "description", NULL, NULL);
284+
if (desc)
285+
ksft_print_msg("%s.%s.%d.%d.%d.%s - %s\n",
286+
test_class_name, test_name,
287+
data->card, data->device, data->subdevice,
288+
snd_pcm_stream_name(data->stream),
289+
desc);
290+
291+
265292
snd_pcm_hw_params_alloca(&hw_params);
266293
snd_pcm_sw_params_alloca(&sw_params);
267294

@@ -443,6 +470,8 @@ static void test_pcm_time(struct pcm_data *data, enum test_class class,
443470
msg[0] = '\0';
444471
pass = true;
445472
__close:
473+
pthread_mutex_lock(&results_lock);
474+
446475
switch (class) {
447476
case TEST_CLASS_SYSTEM:
448477
test_class_name = "system";
@@ -471,6 +500,9 @@ static void test_pcm_time(struct pcm_data *data, enum test_class class,
471500
data->card, data->device, data->subdevice,
472501
snd_pcm_stream_name(data->stream),
473502
msg[0] ? " " : "", msg);
503+
504+
pthread_mutex_unlock(&results_lock);
505+
474506
free(samples);
475507
if (handle)
476508
snd_pcm_close(handle);
@@ -502,11 +534,30 @@ void run_time_tests(struct pcm_data *pcm, enum test_class class,
502534
}
503535
}
504536

537+
void *card_thread(void *data)
538+
{
539+
struct card_data *card = data;
540+
struct pcm_data *pcm;
541+
542+
for (pcm = pcm_list; pcm != NULL; pcm = pcm->next) {
543+
if (pcm->card != card->card)
544+
continue;
545+
546+
run_time_tests(pcm, TEST_CLASS_DEFAULT, default_pcm_config);
547+
run_time_tests(pcm, TEST_CLASS_SYSTEM, pcm->pcm_config);
548+
}
549+
550+
return 0;
551+
}
552+
505553
int main(void)
506554
{
555+
struct card_data *card;
507556
struct pcm_data *pcm;
508-
snd_config_t *global_config, *default_pcm_config, *cfg, *pcm_cfg;
557+
snd_config_t *global_config, *cfg, *pcm_cfg;
509558
int num_pcm_tests = 0, num_tests, num_std_pcm_tests;
559+
int ret;
560+
void *thread_ret;
510561

511562
ksft_print_header();
512563

@@ -540,9 +591,22 @@ int main(void)
540591
snd_pcm_stream_name(pcm->stream));
541592
}
542593

543-
for (pcm = pcm_list; pcm != NULL; pcm = pcm->next) {
544-
run_time_tests(pcm, TEST_CLASS_DEFAULT, default_pcm_config);
545-
run_time_tests(pcm, TEST_CLASS_SYSTEM, pcm->pcm_config);
594+
for (card = card_list; card != NULL; card = card->next) {
595+
ret = pthread_create(&card->thread, NULL, card_thread, card);
596+
if (ret != 0) {
597+
ksft_exit_fail_msg("Failed to create card %d thread: %d (%s)\n",
598+
card->card, ret,
599+
strerror(errno));
600+
}
601+
}
602+
603+
for (card = card_list; card != NULL; card = card->next) {
604+
ret = pthread_join(card->thread, &thread_ret);
605+
if (ret != 0) {
606+
ksft_exit_fail_msg("Failed to join card %d thread: %d (%s)\n",
607+
card->card, ret,
608+
strerror(errno));
609+
}
546610
}
547611

548612
snd_config_delete(global_config);

0 commit comments

Comments
 (0)