[v2,1/2] selftests: sync: add test that waits on a destroyed timeline
diff mbox

Message ID 20170907190246.16425-1-gustavo@padovan.org
State New
Headers show

Commit Message

Gustavo Padovan Sept. 7, 2017, 7:02 p.m. UTC
From: Emilio López <emilio.lopez@collabora.co.uk>

If a sw_sync_timeline is destroyed the fences associated to it need
to be signalled. This test checks that.

Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Emilio López <emilio.lopez@collabora.co.uk>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 tools/testing/selftests/sync/sync_test.c |  1 +
 tools/testing/selftests/sync/sync_wait.c | 58 ++++++++++++++++++++++++++++++++
 tools/testing/selftests/sync/synctest.h  |  1 +
 3 files changed, 60 insertions(+)

Comments

Chris Wilson Sept. 7, 2017, 7:09 p.m. UTC | #1
Quoting Gustavo Padovan (2017-09-07 20:02:45)
> From: Emilio López <emilio.lopez@collabora.co.uk>
> 
> If a sw_sync_timeline is destroyed the fences associated to it need
> to be signalled. This test checks that.
> 
> Cc: Shuah Khan <shuah@kernel.org>
> Cc: linux-kselftest@vger.kernel.org
> Signed-off-by: Emilio López <emilio.lopez@collabora.co.uk>
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> ---
>  tools/testing/selftests/sync/sync_test.c |  1 +
>  tools/testing/selftests/sync/sync_wait.c | 58 ++++++++++++++++++++++++++++++++
>  tools/testing/selftests/sync/synctest.h  |  1 +
>  3 files changed, 60 insertions(+)
> 
> diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
> index 62fa666e501a..5d93c9dcc290 100644
> --- a/tools/testing/selftests/sync/sync_test.c
> +++ b/tools/testing/selftests/sync/sync_test.c
> @@ -79,6 +79,7 @@ int main(void)
>         err += RUN_TEST(test_fence_one_timeline_merge);
>         err += RUN_TEST(test_fence_merge_same_fence);
>         err += RUN_TEST(test_fence_multi_timeline_wait);
> +       err += RUN_TEST(test_fence_wait_on_destroyed_timeline);
>         err += RUN_TEST(test_stress_two_threads_shared_timeline);
>         err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
>         err += RUN_TEST(test_merge_stress_random_merge);
> diff --git a/tools/testing/selftests/sync/sync_wait.c b/tools/testing/selftests/sync/sync_wait.c
> index d69b752f6550..82ad9f519959 100644
> --- a/tools/testing/selftests/sync/sync_wait.c
> +++ b/tools/testing/selftests/sync/sync_wait.c
> @@ -25,6 +25,7 @@
>   *  OTHER DEALINGS IN THE SOFTWARE.
>   */
>  
> +#include <pthread.h>
>  #include "sync.h"
>  #include "sw_sync.h"
>  #include "synctest.h"
> @@ -89,3 +90,60 @@ int test_fence_multi_timeline_wait(void)
>  
>         return 0;
>  }
> +
> +struct fds_test {
> +       int timeline;
> +       int fencesig, fencekill;
> +       int result;
> +};
> +
> +static int test_fence_wait_on_destroyed_timeline_thread(void *d)

A horrible cast later just because you didn't want to use s/int/void */
> +{
> +       struct fds_test *data = d;
> +       int ret;
> +
> +       /* in case of errors */
> +       data->result = 1;
> +
> +       ret = sw_sync_timeline_inc(data->timeline, 100);
> +       ASSERT(ret == 0, "Failure advancing timeline\n");

Just return the error, e.g.  return "err string";
Only allow explosions from the main thread.

> +
> +       ret = sync_wait(data->fencekill, -1);
> +       ASSERT(ret == 1, "Failure waiting on fence\n");
> +
> +       /* no errors occurred */
> +       data->result = 0;
> +       return 0;
> +}
> +
> +int test_fence_wait_on_destroyed_timeline(void)
> +{
> +       struct fds_test data;
> +       pthread_t thread;
> +       int valid;
> +
> +       data.timeline = sw_sync_timeline_create();
> +       valid = sw_sync_timeline_is_valid(data.timeline);
> +       ASSERT(valid, "Failure allocating timeline\n");
> +
> +       data.fencesig = sw_sync_fence_create(data.timeline, "allocFence", 100);
> +       data.fencekill = sw_sync_fence_create(data.timeline, "allocFence", 200);
> +
> +       /* Spawn a thread to wait on a fence when the timeline is killed */
> +       pthread_create(&thread, NULL, (void *(*)(void *))
> +                      test_fence_wait_on_destroyed_timeline_thread, &data);
> +
> +       /* Wait for the thread to spool up */
> +       sync_wait(data.fencesig, -1);
> +
> +       /* Kill the timeline */
> +       sw_sync_timeline_destroy(data.timeline);
> +
> +       /* wait for the thread to clean up */
> +       pthread_join(thread, NULL);

So in case of bug, we block forever. That suggests that you want to use a
timeout, 10s?
-Chris

Patch
diff mbox

diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 62fa666e501a..5d93c9dcc290 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -79,6 +79,7 @@  int main(void)
 	err += RUN_TEST(test_fence_one_timeline_merge);
 	err += RUN_TEST(test_fence_merge_same_fence);
 	err += RUN_TEST(test_fence_multi_timeline_wait);
+	err += RUN_TEST(test_fence_wait_on_destroyed_timeline);
 	err += RUN_TEST(test_stress_two_threads_shared_timeline);
 	err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
 	err += RUN_TEST(test_merge_stress_random_merge);
diff --git a/tools/testing/selftests/sync/sync_wait.c b/tools/testing/selftests/sync/sync_wait.c
index d69b752f6550..82ad9f519959 100644
--- a/tools/testing/selftests/sync/sync_wait.c
+++ b/tools/testing/selftests/sync/sync_wait.c
@@ -25,6 +25,7 @@ 
  *  OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <pthread.h>
 #include "sync.h"
 #include "sw_sync.h"
 #include "synctest.h"
@@ -89,3 +90,60 @@  int test_fence_multi_timeline_wait(void)
 
 	return 0;
 }
+
+struct fds_test {
+       int timeline;
+       int fencesig, fencekill;
+       int result;
+};
+
+static int test_fence_wait_on_destroyed_timeline_thread(void *d)
+{
+       struct fds_test *data = d;
+       int ret;
+
+       /* in case of errors */
+       data->result = 1;
+
+       ret = sw_sync_timeline_inc(data->timeline, 100);
+       ASSERT(ret == 0, "Failure advancing timeline\n");
+
+       ret = sync_wait(data->fencekill, -1);
+       ASSERT(ret == 1, "Failure waiting on fence\n");
+
+       /* no errors occurred */
+       data->result = 0;
+       return 0;
+}
+
+int test_fence_wait_on_destroyed_timeline(void)
+{
+       struct fds_test data;
+       pthread_t thread;
+       int valid;
+
+       data.timeline = sw_sync_timeline_create();
+       valid = sw_sync_timeline_is_valid(data.timeline);
+       ASSERT(valid, "Failure allocating timeline\n");
+
+       data.fencesig = sw_sync_fence_create(data.timeline, "allocFence", 100);
+       data.fencekill = sw_sync_fence_create(data.timeline, "allocFence", 200);
+
+       /* Spawn a thread to wait on a fence when the timeline is killed */
+       pthread_create(&thread, NULL, (void *(*)(void *))
+                      test_fence_wait_on_destroyed_timeline_thread, &data);
+
+       /* Wait for the thread to spool up */
+       sync_wait(data.fencesig, -1);
+
+       /* Kill the timeline */
+       sw_sync_timeline_destroy(data.timeline);
+
+       /* wait for the thread to clean up */
+       pthread_join(thread, NULL);
+
+       sw_sync_fence_destroy(data.fencesig);
+       sw_sync_fence_destroy(data.fencekill);
+
+       return data.result;
+}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index e7d1d57dba7a..1cbe1e3658b3 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -53,6 +53,7 @@  int test_fence_merge_same_fence(void);
 
 /* Fence wait tests */
 int test_fence_multi_timeline_wait(void);
+int test_fence_wait_on_destroyed_timeline(void);
 
 /* Stress test - parallelism */
 int test_stress_two_threads_shared_timeline(void);