Message ID | 20161122132839.26250-10-robert.foss@collabora.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 22 November 2016 at 14:28, <robert.foss@collabora.com> wrote: > From: Robert Foss <robert.foss@collabora.com> > > This subtest verifies the access ordering of multiple consumer threads. > > Signed-off-by: Robert Foss <robert.foss@collabora.com> > Reviewed-by: Eric Engestrom <eric@engestrom.ch> > --- > 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@collabora.com> > */ > > +#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 >
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@collabora.com> */ +#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; + 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"); + + igt_assert_f(thread_ret == 0, "A sync thread reported failure.\n"); +} + 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(); }