On 22 November 2016 at 14:28, <robert.foss@xxxxxxxxxxxxx> wrote: > From: Robert Foss <robert.foss@xxxxxxxxxxxxx> > > This subtest verifies the access ordering of multiple consumer threads. > > Signed-off-by: Robert Foss <robert.foss@xxxxxxxxxxxxx> > Reviewed-by: Eric Engestrom <eric@xxxxxxxxxxxx> > --- > tests/sw_sync.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 103 insertions(+) > > diff --git a/tests/sw_sync.c b/tests/sw_sync.c > index ada1243..cd0c588 100644 > --- a/tests/sw_sync.c > +++ b/tests/sw_sync.c > @@ -27,6 +27,8 @@ > * Robert Foss <robert.foss@xxxxxxxxxxxxx> > */ > > +#include <pthread.h> > +#include <semaphore.h> > #include <stdint.h> > #include <unistd.h> > > @@ -39,6 +41,15 @@ > > IGT_TEST_DESCRIPTION("Test SW Sync Framework"); > > +typedef struct { > + int timeline; > + uint32_t thread_id; > + uint32_t nbr_threads; > + uint32_t nbr_iterations; Any reason why these two cannot be just defines? > + volatile uint32_t * volatile counter; > + sem_t *sem; > +} data_t; > + > static void test_alloc_timeline(void) > { > int timeline; > @@ -219,6 +230,95 @@ static void test_sync_merge_same(void) > close(timeline); > } > > +static void * test_sync_multi_consumer_thread(void *arg) > +{ > + data_t *data = arg; > + int thread_id = data->thread_id; > + int nbr_threads = data->nbr_threads; > + int timeline = data->timeline; > + int iterations = data->nbr_iterations; > + int ret, i; > + > + for (i = 0; i < iterations; i++) { > + int next_point = i * nbr_threads + thread_id; > + int fence = sw_sync_fence_create(timeline, next_point); > + > + ret = sync_wait(fence, 1000); > + if (ret == -1) > + { > + return (void *) 1; > + } > + > + if (*(data->counter) != next_point) > + { > + return (void *) 1; > + } > + > + sem_post(data->sem); > + close(fence); > + } > + return NULL; > +} > + > +static void test_sync_multi_consumer(void) > +{ > + const uint32_t nbr_threads = 8; > + const uint32_t nbr_iterations = 1 << 14; > + data_t data_arr[nbr_threads]; > + pthread_t thread_arr[nbr_threads]; > + sem_t sem; > + int timeline; > + volatile uint32_t counter = 0; > + uintptr_t thread_ret = 0; > + data_t data; > + int i, ret; > + > + sem_init(&sem, 0, 0); > + timeline = sw_sync_timeline_create(); > + > + data.nbr_iterations = nbr_iterations; > + data.nbr_threads = nbr_threads; > + data.counter = &counter; > + data.timeline = timeline; > + data.sem = &sem; > + > + /* Start sync threads. */ > + for (i = 0; i < nbr_threads; i++) > + { > + data_arr[i] = data; > + data_arr[i].thread_id = i; > + ret = pthread_create(&thread_arr[i], NULL, > + test_sync_multi_consumer_thread, > + (void *) &(data_arr[i])); > + igt_assert_eq(ret, 0); > + } > + > + /* Produce 'content'. */ > + for (i = 0; i < nbr_threads * nbr_iterations; i++) > + { > + sem_wait(&sem); > + > + counter++; > + sw_sync_timeline_inc(timeline, 1); > + } > + > + /* Wait for threads to complete. */ > + for (i = 0; i < nbr_threads; i++) > + { > + uintptr_t local_thread_ret; > + pthread_join(thread_arr[i], (void **)&local_thread_ret); > + thread_ret |= local_thread_ret; > + } > + > + close(timeline); > + sem_destroy(&sem); > + > + igt_assert_f(counter == nbr_threads * nbr_iterations, > + "Counter has unexpected value.\n"); In this case I think igt_assert_eq would be more useful. > + igt_assert_f(thread_ret == 0, "A sync thread reported failure.\n"); Here probably as well, unless the message can be improved. > +} > + > igt_main > { > igt_subtest("alloc_timeline") > @@ -241,5 +341,8 @@ igt_main > > igt_subtest("sync_merge_same") > test_sync_merge_same(); > + > + igt_subtest("sync_multi_consumer") > + test_sync_multi_consumer(); > } > > -- > 2.10.2 > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx