2016-10-19 14:13:10

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 0/7] Tests for sync infrastructure

Hello everyone,

This is a series of tests to exercise the sync kernel infrastructure. It is
meant to be a test suite for the work Gustavo has been doing to destage it.

These tests were originally part of a battery of tests shipping with
Android's libsync that were rewritten to use the new userspace interfaces.

This is the second iteration of the test suite. Main changes over v1 are
a reworked Makefile and small code style fixes.

If you are testing this on v4.9-rc1, do note that the last test will
currently fail due to a regression[0].

As usual, all comments are welcome.

Cheers!
Emilio

[0] https://patchwork.kernel.org/patch/9343347/

Emilio López (7):
selftest: sync: basic tests for sw_sync framework
selftest: sync: fence tests for sw_sync framework
selftest: sync: merge tests for sw_sync framework
selftest: sync: wait tests for sw_sync framework
selftest: sync: stress test for parallelism
selftest: sync: stress consumer/producer test
selftest: sync: stress test for merges

tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/sync/.gitignore | 1 +
tools/testing/selftests/sync/Makefile | 24 +++
tools/testing/selftests/sync/sw_sync.h | 46 +++++
tools/testing/selftests/sync/sync.c | 221 +++++++++++++++++++++
tools/testing/selftests/sync/sync.h | 40 ++++
tools/testing/selftests/sync/sync_alloc.c | 74 +++++++
tools/testing/selftests/sync/sync_fence.c | 132 ++++++++++++
tools/testing/selftests/sync/sync_merge.c | 60 ++++++
.../testing/selftests/sync/sync_stress_consumer.c | 185 +++++++++++++++++
tools/testing/selftests/sync/sync_stress_merge.c | 115 +++++++++++
.../selftests/sync/sync_stress_parallelism.c | 111 +++++++++++
tools/testing/selftests/sync/sync_test.c | 79 ++++++++
tools/testing/selftests/sync/sync_wait.c | 91 +++++++++
tools/testing/selftests/sync/synctest.h | 66 ++++++
15 files changed, 1246 insertions(+)
create mode 100644 tools/testing/selftests/sync/.gitignore
create mode 100644 tools/testing/selftests/sync/Makefile
create mode 100644 tools/testing/selftests/sync/sw_sync.h
create mode 100644 tools/testing/selftests/sync/sync.c
create mode 100644 tools/testing/selftests/sync/sync.h
create mode 100644 tools/testing/selftests/sync/sync_alloc.c
create mode 100644 tools/testing/selftests/sync/sync_fence.c
create mode 100644 tools/testing/selftests/sync/sync_merge.c
create mode 100644 tools/testing/selftests/sync/sync_stress_consumer.c
create mode 100644 tools/testing/selftests/sync/sync_stress_merge.c
create mode 100644 tools/testing/selftests/sync/sync_stress_parallelism.c
create mode 100644 tools/testing/selftests/sync/sync_test.c
create mode 100644 tools/testing/selftests/sync/sync_wait.c
create mode 100644 tools/testing/selftests/sync/synctest.h

--
2.10.1


2016-10-19 14:13:08

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 3/7] selftest: sync: merge tests for sw_sync framework

These tests are based on the libsync test suite from Android.
This commit includes tests for basic merge operations.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
tools/testing/selftests/sync/sync_merge.c | 60 +++++++++++++++++++++++++++++++
tools/testing/selftests/sync/sync_test.c | 1 +
tools/testing/selftests/sync/synctest.h | 3 ++
4 files changed, 65 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_merge.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 69e18b3..a39497d 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -12,6 +12,7 @@ OBJS = sync_test.o sync.o

TESTS += sync_alloc.o
TESTS += sync_fence.o
+TESTS += sync_merge.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_merge.c b/tools/testing/selftests/sync/sync_merge.c
new file mode 100644
index 0000000..8914d43
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_merge.c
@@ -0,0 +1,60 @@
+/*
+ * sync fence merge tests
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+int test_fence_merge_same_fence(void)
+{
+ int fence, valid, merged;
+ int timeline = sw_sync_timeline_create();
+
+ valid = sw_sync_timeline_is_valid(timeline);
+ ASSERT(valid, "Failure allocating timeline\n");
+
+ fence = sw_sync_fence_create(timeline, "allocFence", 5);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure allocating fence\n");
+
+ merged = sync_merge("mergeFence", fence, fence);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure merging fence\n");
+
+ ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 0,
+ "fence signaled too early!\n");
+
+ sw_sync_timeline_inc(timeline, 5);
+ ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 1,
+ "fence did not signal!\n");
+
+ sw_sync_fence_destroy(merged);
+ sw_sync_fence_destroy(fence);
+ sw_sync_timeline_destroy(timeline);
+
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index b442292b..ab37eee 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -64,6 +64,7 @@ int main(void)

err += RUN_TEST(test_fence_one_timeline_wait);
err += RUN_TEST(test_fence_one_timeline_merge);
+ err += RUN_TEST(test_fence_merge_same_fence);

if (err)
printf("[FAIL]\tsync errors: %d\n", err);
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index 6505c28..c3b0b5e 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -48,4 +48,7 @@ int test_alloc_fence_negative(void);
int test_fence_one_timeline_wait(void);
int test_fence_one_timeline_merge(void);

+/* Fence merge tests */
+int test_fence_merge_same_fence(void);
+
#endif
--
2.10.1

2016-10-19 15:18:46

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 7/7] selftest: sync: stress test for merges

This test is based on the libsync test suite from Android.
This commit includes a test to stress merge operations.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
tools/testing/selftests/sync/sync_stress_merge.c | 115 +++++++++++++++++++++++
tools/testing/selftests/sync/sync_test.c | 1 +
tools/testing/selftests/sync/synctest.h | 3 +
4 files changed, 120 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_stress_merge.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 20428d5..87ac400 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -16,6 +16,7 @@ TESTS += sync_merge.o
TESTS += sync_wait.o
TESTS += sync_stress_parallelism.o
TESTS += sync_stress_consumer.o
+TESTS += sync_stress_merge.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_stress_merge.c b/tools/testing/selftests/sync/sync_stress_merge.c
new file mode 100644
index 0000000..99e83ef
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_merge.c
@@ -0,0 +1,115 @@
+/*
+ * sync stress test: merging
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+int test_merge_stress_random_merge(void)
+{
+ int i, size, ret;
+ int timeline_count = 32;
+ int merge_count = 1024 * 32;
+ int timelines[timeline_count];
+ int fence_map[timeline_count];
+ int fence, tmpfence, merged, valid;
+ int timeline, timeline_offset, sync_point;
+
+ srand(time(NULL));
+
+ for (i = 0; i < timeline_count; i++)
+ timelines[i] = sw_sync_timeline_create();
+
+ fence = sw_sync_fence_create(timelines[0], "fence", 0);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure creating fence\n");
+
+ memset(fence_map, -1, sizeof(fence_map));
+ fence_map[0] = 0;
+
+ /*
+ * Randomly create sync_points out of a fixed set of timelines,
+ * and merge them together
+ */
+ for (i = 0; i < merge_count; i++) {
+ /* Generate sync_point. */
+ timeline_offset = rand() % timeline_count;
+ timeline = timelines[timeline_offset];
+ sync_point = rand();
+
+ /* Keep track of the latest sync_point in each timeline. */
+ if (fence_map[timeline_offset] == -1)
+ fence_map[timeline_offset] = sync_point;
+ else if (fence_map[timeline_offset] < sync_point)
+ fence_map[timeline_offset] = sync_point;
+
+ /* Merge */
+ tmpfence = sw_sync_fence_create(timeline, "fence", sync_point);
+ merged = sync_merge("merge", tmpfence, fence);
+ sw_sync_fence_destroy(tmpfence);
+ sw_sync_fence_destroy(fence);
+ fence = merged;
+
+ valid = sw_sync_fence_is_valid(merged);
+ ASSERT(valid, "Failure creating fence i\n");
+ }
+
+ size = 0;
+ for (i = 0; i < timeline_count; i++)
+ if (fence_map[i] != -1)
+ size++;
+
+ /* Confirm our map matches the fence. */
+ ASSERT(sync_fence_size(fence) == size,
+ "Quantity of elements not matching\n");
+
+ /* Trigger the merged fence */
+ for (i = 0; i < timeline_count; i++) {
+ if (fence_map[i] != -1) {
+ ret = sync_wait(fence, 0);
+ ASSERT(ret == 0,
+ "Failure waiting on fence until timeout\n");
+ /* Increment the timeline to the last sync_point */
+ sw_sync_timeline_inc(timelines[i], fence_map[i]);
+ }
+ }
+
+ /* Check that the fence is triggered. */
+ ret = sync_wait(fence, 0);
+ ASSERT(ret > 0, "Failure triggering fence\n");
+
+ sw_sync_fence_destroy(fence);
+
+ for (i = 0; i < timeline_count; i++)
+ sw_sync_timeline_destroy(timelines[i]);
+
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 32f2534..9ea08d9 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -68,6 +68,7 @@ int main(void)
err += RUN_TEST(test_fence_multi_timeline_wait);
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);

if (err)
printf("[FAIL]\tsync errors: %d\n", err);
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index a94b622..4e0e59f 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -60,4 +60,7 @@ int test_stress_two_threads_shared_timeline(void);
/* Stress test - consumer */
int test_consumer_stress_multi_producer_single_consumer(void);

+/* Stress test - merging */
+int test_merge_stress_random_merge(void);
+
#endif
--
2.10.1

2016-10-19 15:18:47

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 6/7] selftest: sync: stress consumer/producer test

This test is based on the libsync test suite from Android.
This commit includes a stress test that replicates a
consumer/producer pattern.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
.../testing/selftests/sync/sync_stress_consumer.c | 185 +++++++++++++++++++++
tools/testing/selftests/sync/sync_test.c | 1 +
tools/testing/selftests/sync/synctest.h | 3 +
4 files changed, 190 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_stress_consumer.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 14f72bf..20428d5 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -15,6 +15,7 @@ TESTS += sync_fence.o
TESTS += sync_merge.o
TESTS += sync_wait.o
TESTS += sync_stress_parallelism.o
+TESTS += sync_stress_consumer.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_stress_consumer.c b/tools/testing/selftests/sync/sync_stress_consumer.c
new file mode 100644
index 0000000..d9eff8d
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_consumer.c
@@ -0,0 +1,185 @@
+/*
+ * sync stress test: producer/consumer
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <pthread.h>
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+/* IMPORTANT NOTE: if you see this test failing on your system, it may be
+ * due to a shortage of file descriptors. Please ensure your system has
+ * a sensible limit for this test to finish correctly.
+ */
+
+/* Returns 1 on error, 0 on success */
+static int busy_wait_on_fence(int fence)
+{
+ int error, active;
+
+ do {
+ error = sync_fence_count_with_status(fence, FENCE_STATUS_ERROR);
+ ASSERT(error == 0, "Error occurred on fence\n");
+ active = sync_fence_count_with_status(fence,
+ FENCE_STATUS_ACTIVE);
+ } while (active);
+
+ return 0;
+}
+
+static struct {
+ int iterations;
+ int threads;
+ int counter;
+ int consumer_timeline;
+ int *producer_timelines;
+ pthread_mutex_t lock;
+} test_data_mpsc;
+
+static int mpsc_producer_thread(void *d)
+{
+ int id = (long)d;
+ int fence, valid, i;
+ int *producer_timelines = test_data_mpsc.producer_timelines;
+ int consumer_timeline = test_data_mpsc.consumer_timeline;
+ int iterations = test_data_mpsc.iterations;
+
+ for (i = 0; i < iterations; i++) {
+ fence = sw_sync_fence_create(consumer_timeline, "fence", i);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure creating fence\n");
+
+ /*
+ * Wait for the consumer to finish. Use alternate
+ * means of waiting on the fence
+ */
+
+ if ((iterations + id) % 8 != 0) {
+ ASSERT(sync_wait(fence, -1) > 0,
+ "Failure waiting on fence\n");
+ } else {
+ ASSERT(busy_wait_on_fence(fence) == 0,
+ "Failure waiting on fence\n");
+ }
+
+ /*
+ * Every producer increments the counter, the consumer
+ * checks and erases it
+ */
+ pthread_mutex_lock(&test_data_mpsc.lock);
+ test_data_mpsc.counter++;
+ pthread_mutex_unlock(&test_data_mpsc.lock);
+
+ ASSERT(sw_sync_timeline_inc(producer_timelines[id], 1) == 0,
+ "Error advancing producer timeline\n");
+
+ sw_sync_fence_destroy(fence);
+ }
+
+ return 0;
+}
+
+static int mpcs_consumer_thread(void)
+{
+ int fence, merged, tmp, valid, it, i;
+ int *producer_timelines = test_data_mpsc.producer_timelines;
+ int consumer_timeline = test_data_mpsc.consumer_timeline;
+ int iterations = test_data_mpsc.iterations;
+ int n = test_data_mpsc.threads;
+
+ for (it = 1; it <= iterations; it++) {
+ fence = sw_sync_fence_create(producer_timelines[0], "name", it);
+ for (i = 1; i < n; i++) {
+ tmp = sw_sync_fence_create(producer_timelines[i],
+ "name", it);
+ merged = sync_merge("name", tmp, fence);
+ sw_sync_fence_destroy(tmp);
+ sw_sync_fence_destroy(fence);
+ fence = merged;
+ }
+
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure merging fences\n");
+
+ /*
+ * Make sure we see an increment from every producer thread.
+ * Vary the means by which we wait.
+ */
+ if (iterations % 8 != 0) {
+ ASSERT(sync_wait(fence, -1) > 0,
+ "Producers did not increment as expected\n");
+ } else {
+ ASSERT(busy_wait_on_fence(fence) == 0,
+ "Producers did not increment as expected\n");
+ }
+
+ ASSERT(test_data_mpsc.counter == n * it,
+ "Counter value mismatch!\n");
+
+ /* Release the producer threads */
+ ASSERT(sw_sync_timeline_inc(consumer_timeline, 1) == 0,
+ "Failure releasing producer threads\n");
+
+ sw_sync_fence_destroy(fence);
+ }
+
+ return 0;
+}
+
+int test_consumer_stress_multi_producer_single_consumer(void)
+{
+ int iterations = 1 << 12;
+ int n = 5;
+ long i, ret;
+ int producer_timelines[n];
+ int consumer_timeline;
+ pthread_t threads[n];
+
+ consumer_timeline = sw_sync_timeline_create();
+ for (i = 0; i < n; i++)
+ producer_timelines[i] = sw_sync_timeline_create();
+
+ test_data_mpsc.producer_timelines = producer_timelines;
+ test_data_mpsc.consumer_timeline = consumer_timeline;
+ test_data_mpsc.iterations = iterations;
+ test_data_mpsc.threads = n;
+ test_data_mpsc.counter = 0;
+ pthread_mutex_init(&test_data_mpsc.lock, NULL);
+
+ for (i = 0; i < n; i++) {
+ pthread_create(&threads[i], NULL, (void * (*)(void *))
+ mpsc_producer_thread, (void *)i);
+ }
+
+ /* Consumer thread runs here */
+ ret = mpcs_consumer_thread();
+
+ for (i = 0; i < n; i++)
+ pthread_join(threads[i], NULL);
+
+ return ret;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 3bb1024..32f2534 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -67,6 +67,7 @@ int main(void)
err += RUN_TEST(test_fence_merge_same_fence);
err += RUN_TEST(test_fence_multi_timeline_wait);
err += RUN_TEST(test_stress_two_threads_shared_timeline);
+ err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);

if (err)
printf("[FAIL]\tsync errors: %d\n", err);
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index c461577..a94b622 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -57,4 +57,7 @@ int test_fence_multi_timeline_wait(void);
/* Stress test - parallelism */
int test_stress_two_threads_shared_timeline(void);

+/* Stress test - consumer */
+int test_consumer_stress_multi_producer_single_consumer(void);
+
#endif
--
2.10.1

2016-10-19 16:28:41

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 5/7] selftest: sync: stress test for parallelism

This test is based on the libsync test suite from Android.
This commit includes a stress test that invokes operations
in parallel.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
.../selftests/sync/sync_stress_parallelism.c | 111 +++++++++++++++++++++
tools/testing/selftests/sync/sync_test.c | 1 +
tools/testing/selftests/sync/synctest.h | 3 +
4 files changed, 116 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_stress_parallelism.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 99b58fe..14f72bf 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -14,6 +14,7 @@ TESTS += sync_alloc.o
TESTS += sync_fence.o
TESTS += sync_merge.o
TESTS += sync_wait.o
+TESTS += sync_stress_parallelism.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_stress_parallelism.c b/tools/testing/selftests/sync/sync_stress_parallelism.c
new file mode 100644
index 0000000..e6c9be67
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_parallelism.c
@@ -0,0 +1,111 @@
+/*
+ * sync stress test: parallelism
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <pthread.h>
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+static struct {
+ int iterations;
+ int timeline;
+ int counter;
+} test_data_two_threads;
+
+static int test_stress_two_threads_shared_timeline_thread(void *d)
+{
+ int thread_id = (long)d;
+ int timeline = test_data_two_threads.timeline;
+ int iterations = test_data_two_threads.iterations;
+ int fence, valid, ret, i;
+
+ for (i = 0; i < iterations; i++) {
+ fence = sw_sync_fence_create(timeline, "fence",
+ i * 2 + thread_id);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure allocating fence\n");
+
+ /* Wait on the prior thread to complete */
+ ret = sync_wait(fence, -1);
+ ASSERT(ret > 0, "Problem occurred on prior thread\n");
+
+ /*
+ * Confirm the previous thread's writes are visible
+ * and then increment
+ */
+ ASSERT(test_data_two_threads.counter == i * 2 + thread_id,
+ "Counter got damaged!\n");
+ test_data_two_threads.counter++;
+
+ /* Kick off the other thread */
+ ret = sw_sync_timeline_inc(timeline, 1);
+ ASSERT(ret == 0, "Advancing timeline failed\n");
+
+ sw_sync_fence_destroy(fence);
+ }
+
+ return 0;
+}
+
+int test_stress_two_threads_shared_timeline(void)
+{
+ pthread_t a, b;
+ int valid;
+ int timeline = sw_sync_timeline_create();
+
+ valid = sw_sync_timeline_is_valid(timeline);
+ ASSERT(valid, "Failure allocating timeline\n");
+
+ test_data_two_threads.iterations = 1 << 16;
+ test_data_two_threads.counter = 0;
+ test_data_two_threads.timeline = timeline;
+
+ /*
+ * Use a single timeline to synchronize two threads
+ * hammmering on the same counter.
+ */
+
+ pthread_create(&a, NULL, (void *(*)(void *))
+ test_stress_two_threads_shared_timeline_thread,
+ (void *)0);
+ pthread_create(&b, NULL, (void *(*)(void *))
+ test_stress_two_threads_shared_timeline_thread,
+ (void *)1);
+
+ pthread_join(a, NULL);
+ pthread_join(b, NULL);
+
+ /* make sure the threads did not trample on one another */
+ ASSERT(test_data_two_threads.counter ==
+ test_data_two_threads.iterations * 2,
+ "Counter has unexpected value\n");
+
+ sw_sync_timeline_destroy(timeline);
+
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index eab5ceb..3bb1024 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -66,6 +66,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_stress_two_threads_shared_timeline);

if (err)
printf("[FAIL]\tsync errors: %d\n", err);
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index 0fad57d..c461577 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -54,4 +54,7 @@ int test_fence_merge_same_fence(void);
/* Fence wait tests */
int test_fence_multi_timeline_wait(void);

+/* Stress test - parallelism */
+int test_stress_two_threads_shared_timeline(void);
+
#endif
--
2.10.1

2016-10-19 16:28:39

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 2/7] selftest: sync: fence tests for sw_sync framework

These tests are based on the libsync test suite from Android.
This commit includes tests for basic fence creation.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
tools/testing/selftests/sync/sync_fence.c | 132 ++++++++++++++++++++++++++++++
tools/testing/selftests/sync/sync_test.c | 3 +
tools/testing/selftests/sync/synctest.h | 4 +
4 files changed, 140 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_fence.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 620a59a..69e18b3 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -11,6 +11,7 @@ include ../lib.mk
OBJS = sync_test.o sync.o

TESTS += sync_alloc.o
+TESTS += sync_fence.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_fence.c b/tools/testing/selftests/sync/sync_fence.c
new file mode 100644
index 0000000..13f1752
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_fence.c
@@ -0,0 +1,132 @@
+/*
+ * sync fence tests with one timeline
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+int test_fence_one_timeline_wait(void)
+{
+ int fence, valid, ret;
+ int timeline = sw_sync_timeline_create();
+
+ valid = sw_sync_timeline_is_valid(timeline);
+ ASSERT(valid, "Failure allocating timeline\n");
+
+ fence = sw_sync_fence_create(timeline, "allocFence", 5);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure allocating fence\n");
+
+ /* Wait on fence until timeout */
+ ret = sync_wait(fence, 0);
+ ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
+
+ /* Advance timeline from 0 -> 1 */
+ ret = sw_sync_timeline_inc(timeline, 1);
+ ASSERT(ret == 0, "Failure advancing timeline\n");
+
+ /* Wait on fence until timeout */
+ ret = sync_wait(fence, 0);
+ ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
+
+ /* Signal the fence */
+ ret = sw_sync_timeline_inc(timeline, 4);
+ ASSERT(ret == 0, "Failure signaling the fence\n");
+
+ /* Wait successfully */
+ ret = sync_wait(fence, 0);
+ ASSERT(ret > 0, "Failure waiting on fence\n");
+
+ /* Go even further, and confirm wait still succeeds */
+ ret = sw_sync_timeline_inc(timeline, 10);
+ ASSERT(ret == 0, "Failure going further\n");
+ ret = sync_wait(fence, 0);
+ ASSERT(ret > 0, "Failure waiting ahead\n");
+
+ sw_sync_fence_destroy(fence);
+ sw_sync_timeline_destroy(timeline);
+
+ return 0;
+}
+
+int test_fence_one_timeline_merge(void)
+{
+ int a, b, c, d, valid;
+ int timeline = sw_sync_timeline_create();
+
+ /* create fence a,b,c and then merge them all into fence d */
+ a = sw_sync_fence_create(timeline, "allocFence", 1);
+ b = sw_sync_fence_create(timeline, "allocFence", 2);
+ c = sw_sync_fence_create(timeline, "allocFence", 3);
+
+ valid = sw_sync_fence_is_valid(a) &&
+ sw_sync_fence_is_valid(b) &&
+ sw_sync_fence_is_valid(c);
+ ASSERT(valid, "Failure allocating fences\n");
+
+ d = sync_merge("mergeFence", b, a);
+ d = sync_merge("mergeFence", c, d);
+ valid = sw_sync_fence_is_valid(d);
+ ASSERT(valid, "Failure merging fences\n");
+
+ /* confirm all fences have one active point (even d) */
+ ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
+ "a has too many active fences!\n");
+ ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
+ "b has too many active fences!\n");
+ ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
+ "c has too many active fences!\n");
+ ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
+ "d has too many active fences!\n");
+
+ /* confirm that d is not signaled until the max of a,b,c */
+ sw_sync_timeline_inc(timeline, 1);
+ ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_SIGNALED) == 1,
+ "a did not signal!\n");
+ ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
+ "d signaled too early!\n");
+
+ sw_sync_timeline_inc(timeline, 1);
+ ASSERT(sync_fence_count_with_status(b, FENCE_STATUS_SIGNALED) == 1,
+ "b did not signal!\n");
+ ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
+ "d signaled too early!\n");
+
+ sw_sync_timeline_inc(timeline, 1);
+ ASSERT(sync_fence_count_with_status(c, FENCE_STATUS_SIGNALED) == 1,
+ "c did not signal!\n");
+ ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 0 &&
+ sync_fence_count_with_status(d, FENCE_STATUS_SIGNALED) == 1,
+ "d did not signal!\n");
+
+ sw_sync_fence_destroy(d);
+ sw_sync_fence_destroy(c);
+ sw_sync_fence_destroy(b);
+ sw_sync_fence_destroy(a);
+ sw_sync_timeline_destroy(timeline);
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index e471ba9..b442292b 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -62,6 +62,9 @@ int main(void)
err += RUN_TEST(test_alloc_fence);
err += RUN_TEST(test_alloc_fence_negative);

+ err += RUN_TEST(test_fence_one_timeline_wait);
+ err += RUN_TEST(test_fence_one_timeline_merge);
+
if (err)
printf("[FAIL]\tsync errors: %d\n", err);
else
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index 7d2d8ce..6505c28 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -44,4 +44,8 @@ int test_alloc_timeline(void);
int test_alloc_fence(void);
int test_alloc_fence_negative(void);

+/* Fence tests with one timeline */
+int test_fence_one_timeline_wait(void);
+int test_fence_one_timeline_merge(void);
+
#endif
--
2.10.1

2016-10-19 16:29:23

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 4/7] selftest: sync: wait tests for sw_sync framework

These tests are based on the libsync test suite from Android.
This commit includes tests for waiting on fences.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/sync/Makefile | 1 +
tools/testing/selftests/sync/sync_test.c | 1 +
tools/testing/selftests/sync/sync_wait.c | 91 ++++++++++++++++++++++++++++++++
tools/testing/selftests/sync/synctest.h | 3 ++
4 files changed, 96 insertions(+)
create mode 100644 tools/testing/selftests/sync/sync_wait.c

diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index a39497d..99b58fe 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -13,6 +13,7 @@ OBJS = sync_test.o sync.o
TESTS += sync_alloc.o
TESTS += sync_fence.o
TESTS += sync_merge.o
+TESTS += sync_wait.o

sync_test: $(OBJS) $(TESTS)

diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index ab37eee..eab5ceb 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -65,6 +65,7 @@ int main(void)
err += RUN_TEST(test_fence_one_timeline_wait);
err += RUN_TEST(test_fence_one_timeline_merge);
err += RUN_TEST(test_fence_merge_same_fence);
+ err += RUN_TEST(test_fence_multi_timeline_wait);

if (err)
printf("[FAIL]\tsync errors: %d\n", err);
diff --git a/tools/testing/selftests/sync/sync_wait.c b/tools/testing/selftests/sync/sync_wait.c
new file mode 100644
index 0000000..d69b752
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_wait.c
@@ -0,0 +1,91 @@
+/*
+ * sync fence wait tests
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+int test_fence_multi_timeline_wait(void)
+{
+ int timelineA, timelineB, timelineC;
+ int fenceA, fenceB, fenceC, merged;
+ int valid, active, signaled, ret;
+
+ timelineA = sw_sync_timeline_create();
+ timelineB = sw_sync_timeline_create();
+ timelineC = sw_sync_timeline_create();
+
+ fenceA = sw_sync_fence_create(timelineA, "fenceA", 5);
+ fenceB = sw_sync_fence_create(timelineB, "fenceB", 5);
+ fenceC = sw_sync_fence_create(timelineC, "fenceC", 5);
+
+ merged = sync_merge("mergeFence", fenceB, fenceA);
+ merged = sync_merge("mergeFence", fenceC, merged);
+
+ valid = sw_sync_fence_is_valid(merged);
+ ASSERT(valid, "Failure merging fence from various timelines\n");
+
+ /* Confirm fence isn't signaled */
+ active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
+ ASSERT(active == 3, "Fence signaled too early!\n");
+
+ ret = sync_wait(merged, 0);
+ ASSERT(ret == 0,
+ "Failure waiting on fence until timeout\n");
+
+ ret = sw_sync_timeline_inc(timelineA, 5);
+ active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
+ signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
+ ASSERT(active == 2 && signaled == 1,
+ "Fence did not signal properly!\n");
+
+ ret = sw_sync_timeline_inc(timelineB, 5);
+ active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
+ signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
+ ASSERT(active == 1 && signaled == 2,
+ "Fence did not signal properly!\n");
+
+ ret = sw_sync_timeline_inc(timelineC, 5);
+ active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
+ signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
+ ASSERT(active == 0 && signaled == 3,
+ "Fence did not signal properly!\n");
+
+ /* confirm you can successfully wait */
+ ret = sync_wait(merged, 100);
+ ASSERT(ret > 0, "Failure waiting on signaled fence\n");
+
+ sw_sync_fence_destroy(merged);
+ sw_sync_fence_destroy(fenceC);
+ sw_sync_fence_destroy(fenceB);
+ sw_sync_fence_destroy(fenceA);
+ sw_sync_timeline_destroy(timelineC);
+ sw_sync_timeline_destroy(timelineB);
+ sw_sync_timeline_destroy(timelineA);
+
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index c3b0b5e..0fad57d 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -51,4 +51,7 @@ int test_fence_one_timeline_merge(void);
/* Fence merge tests */
int test_fence_merge_same_fence(void);

+/* Fence wait tests */
+int test_fence_multi_timeline_wait(void);
+
#endif
--
2.10.1

2016-10-19 16:29:14

by Emilio López

[permalink] [raw]
Subject: [PATCH v2 1/7] selftest: sync: basic tests for sw_sync framework

These tests are based on the libsync test suite from Android.
This commit lays the ground for future tests, as well as includes
tests for a variety of basic allocation commands.

Signed-off-by: Emilio López <[email protected]>
---
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/sync/.gitignore | 1 +
tools/testing/selftests/sync/Makefile | 18 +++
tools/testing/selftests/sync/sw_sync.h | 46 +++++++
tools/testing/selftests/sync/sync.c | 221 ++++++++++++++++++++++++++++++
tools/testing/selftests/sync/sync.h | 40 ++++++
tools/testing/selftests/sync/sync_alloc.c | 74 ++++++++++
tools/testing/selftests/sync/sync_test.c | 71 ++++++++++
tools/testing/selftests/sync/synctest.h | 47 +++++++
9 files changed, 519 insertions(+)
create mode 100644 tools/testing/selftests/sync/.gitignore
create mode 100644 tools/testing/selftests/sync/Makefile
create mode 100644 tools/testing/selftests/sync/sw_sync.h
create mode 100644 tools/testing/selftests/sync/sync.c
create mode 100644 tools/testing/selftests/sync/sync.h
create mode 100644 tools/testing/selftests/sync/sync_alloc.c
create mode 100644 tools/testing/selftests/sync/sync_test.c
create mode 100644 tools/testing/selftests/sync/synctest.h

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index f770dba..69cf1a6 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -23,6 +23,7 @@ TARGETS += seccomp
TARGETS += sigaltstack
TARGETS += size
TARGETS += static_keys
+TARGETS += sync
TARGETS += sysctl
ifneq (1, $(quicktest))
TARGETS += timers
diff --git a/tools/testing/selftests/sync/.gitignore b/tools/testing/selftests/sync/.gitignore
new file mode 100644
index 0000000..f5091e7
--- /dev/null
+++ b/tools/testing/selftests/sync/.gitignore
@@ -0,0 +1 @@
+sync_test
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
new file mode 100644
index 0000000..620a59a
--- /dev/null
+++ b/tools/testing/selftests/sync/Makefile
@@ -0,0 +1,18 @@
+CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
+CFLAGS += -I../../../../usr/include/
+LDFLAGS += -pthread
+
+TEST_PROGS = sync_test
+
+all: $(TEST_PROGS)
+
+include ../lib.mk
+
+OBJS = sync_test.o sync.o
+
+TESTS += sync_alloc.o
+
+sync_test: $(OBJS) $(TESTS)
+
+clean:
+ $(RM) sync_test $(OBJS) $(TESTS)
diff --git a/tools/testing/selftests/sync/sw_sync.h b/tools/testing/selftests/sync/sw_sync.h
new file mode 100644
index 0000000..e2cfc6ba
--- /dev/null
+++ b/tools/testing/selftests/sync/sw_sync.h
@@ -0,0 +1,46 @@
+/*
+ * sw_sync abstraction
+ *
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2013 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SELFTESTS_SW_SYNC_H
+#define SELFTESTS_SW_SYNC_H
+
+/*
+ * sw_sync is mainly intended for testing and should not be compiled into
+ * production kernels
+ */
+
+int sw_sync_timeline_create(void);
+int sw_sync_timeline_is_valid(int fd);
+int sw_sync_timeline_inc(int fd, unsigned int count);
+void sw_sync_timeline_destroy(int fd);
+
+int sw_sync_fence_create(int fd, const char *name, unsigned int value);
+int sw_sync_fence_is_valid(int fd);
+void sw_sync_fence_destroy(int fd);
+
+#endif
diff --git a/tools/testing/selftests/sync/sync.c b/tools/testing/selftests/sync/sync.c
new file mode 100644
index 0000000..f3d599f
--- /dev/null
+++ b/tools/testing/selftests/sync/sync.c
@@ -0,0 +1,221 @@
+/*
+ * sync / sw_sync abstraction
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <fcntl.h>
+#include <malloc.h>
+#include <poll.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "sync.h"
+#include "sw_sync.h"
+
+#include <linux/sync_file.h>
+
+
+/* SW_SYNC ioctls */
+struct sw_sync_create_fence_data {
+ __u32 value;
+ char name[32];
+ __s32 fence;
+};
+
+#define SW_SYNC_IOC_MAGIC 'W'
+#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
+ struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+
+int sync_wait(int fd, int timeout)
+{
+ struct pollfd fds;
+
+ fds.fd = fd;
+ fds.events = POLLIN | POLLERR;
+
+ return poll(&fds, 1, timeout);
+}
+
+int sync_merge(const char *name, int fd1, int fd2)
+{
+ struct sync_merge_data data = {};
+ int err;
+
+ data.fd2 = fd2;
+ strncpy(data.name, name, sizeof(data.name) - 1);
+ data.name[sizeof(data.name) - 1] = '\0';
+
+ err = ioctl(fd1, SYNC_IOC_MERGE, &data);
+ if (err < 0)
+ return err;
+
+ return data.fence;
+}
+
+static struct sync_file_info *sync_file_info(int fd)
+{
+ struct sync_file_info *info;
+ struct sync_fence_info *fence_info;
+ int err, num_fences;
+
+ info = calloc(1, sizeof(*info));
+ if (info == NULL)
+ return NULL;
+
+ err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
+ if (err < 0) {
+ free(info);
+ return NULL;
+ }
+
+ num_fences = info->num_fences;
+
+ if (num_fences) {
+ info->flags = 0;
+ info->num_fences = num_fences;
+
+ fence_info = calloc(num_fences, sizeof(*fence_info));
+ if (!fence_info) {
+ free(info);
+ return NULL;
+ }
+
+ info->sync_fence_info = (uint64_t)fence_info;
+
+ err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
+ if (err < 0) {
+ free(fence_info);
+ free(info);
+ return NULL;
+ }
+ }
+
+ return info;
+}
+
+static void sync_file_info_free(struct sync_file_info *info)
+{
+ free((void *)info->sync_fence_info);
+ free(info);
+}
+
+int sync_fence_size(int fd)
+{
+ int count;
+ struct sync_file_info *info = sync_file_info(fd);
+
+ if (!info)
+ return 0;
+
+ count = info->num_fences;
+
+ sync_file_info_free(info);
+
+ return count;
+}
+
+int sync_fence_count_with_status(int fd, int status)
+{
+ unsigned int i, count = 0;
+ struct sync_fence_info *fence_info = NULL;
+ struct sync_file_info *info = sync_file_info(fd);
+
+ if (!info)
+ return -1;
+
+ fence_info = (struct sync_fence_info *)info->sync_fence_info;
+ for (i = 0 ; i < info->num_fences ; i++) {
+ if (fence_info[i].status == status)
+ count++;
+ }
+
+ sync_file_info_free(info);
+
+ return count;
+}
+
+int sw_sync_timeline_create(void)
+{
+ return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
+}
+
+int sw_sync_timeline_inc(int fd, unsigned int count)
+{
+ __u32 arg = count;
+
+ return ioctl(fd, SW_SYNC_IOC_INC, &arg);
+}
+
+int sw_sync_timeline_is_valid(int fd)
+{
+ int status;
+
+ if (fd == -1)
+ return 0;
+
+ status = fcntl(fd, F_GETFD, 0);
+ return (status >= 0);
+}
+
+void sw_sync_timeline_destroy(int fd)
+{
+ if (sw_sync_timeline_is_valid(fd))
+ close(fd);
+}
+
+int sw_sync_fence_create(int fd, const char *name, unsigned int value)
+{
+ struct sw_sync_create_fence_data data = {};
+ int err;
+
+ data.value = value;
+ strncpy(data.name, name, sizeof(data.name) - 1);
+ data.name[sizeof(data.name) - 1] = '\0';
+
+ err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
+ if (err < 0)
+ return err;
+
+ return data.fence;
+}
+
+int sw_sync_fence_is_valid(int fd)
+{
+ /* Same code! */
+ return sw_sync_timeline_is_valid(fd);
+}
+
+void sw_sync_fence_destroy(int fd)
+{
+ if (sw_sync_fence_is_valid(fd))
+ close(fd);
+}
diff --git a/tools/testing/selftests/sync/sync.h b/tools/testing/selftests/sync/sync.h
new file mode 100644
index 0000000..fb71561
--- /dev/null
+++ b/tools/testing/selftests/sync/sync.h
@@ -0,0 +1,40 @@
+/*
+ * sync abstraction
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SELFTESTS_SYNC_H
+#define SELFTESTS_SYNC_H
+
+#define FENCE_STATUS_ERROR (-1)
+#define FENCE_STATUS_ACTIVE (0)
+#define FENCE_STATUS_SIGNALED (1)
+
+int sync_wait(int fd, int timeout);
+int sync_merge(const char *name, int fd1, int fd2);
+int sync_fence_size(int fd);
+int sync_fence_count_with_status(int fd, int status);
+
+#endif
diff --git a/tools/testing/selftests/sync/sync_alloc.c b/tools/testing/selftests/sync/sync_alloc.c
new file mode 100644
index 0000000..66a28af
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_alloc.c
@@ -0,0 +1,74 @@
+/*
+ * sync allocation tests
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sync.h"
+#include "sw_sync.h"
+#include "synctest.h"
+
+int test_alloc_timeline(void)
+{
+ int timeline, valid;
+
+ timeline = sw_sync_timeline_create();
+ valid = sw_sync_timeline_is_valid(timeline);
+ ASSERT(valid, "Failure allocating timeline\n");
+
+ sw_sync_timeline_destroy(timeline);
+ return 0;
+}
+
+int test_alloc_fence(void)
+{
+ int timeline, fence, valid;
+
+ timeline = sw_sync_timeline_create();
+ valid = sw_sync_timeline_is_valid(timeline);
+ ASSERT(valid, "Failure allocating timeline\n");
+
+ fence = sw_sync_fence_create(timeline, "allocFence", 1);
+ valid = sw_sync_fence_is_valid(fence);
+ ASSERT(valid, "Failure allocating fence\n");
+
+ sw_sync_fence_destroy(fence);
+ sw_sync_timeline_destroy(timeline);
+ return 0;
+}
+
+int test_alloc_fence_negative(void)
+{
+ int fence, timeline;
+
+ timeline = sw_sync_timeline_create();
+ ASSERT(timeline > 0, "Failure allocating timeline\n");
+
+ fence = sw_sync_fence_create(-1, "fence", 1);
+ ASSERT(fence < 0, "Success allocating negative fence\n");
+
+ sw_sync_fence_destroy(fence);
+ sw_sync_timeline_destroy(timeline);
+ return 0;
+}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
new file mode 100644
index 0000000..e471ba9
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -0,0 +1,71 @@
+/*
+ * sync test runner
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "synctest.h"
+
+static int run_test(int (*test)(void), char *name)
+{
+ int result;
+ pid_t childpid;
+
+ fflush(stdout);
+ childpid = fork();
+
+ if (childpid) {
+ waitpid(childpid, &result, 0);
+ if (WIFEXITED(result))
+ return WEXITSTATUS(result);
+ return 1;
+ }
+
+ printf("[RUN]\tExecuting %s\n", name);
+ exit(test());
+}
+
+int main(void)
+{
+ int err = 0;
+
+ printf("[RUN]\tTesting sync framework\n");
+
+ err += RUN_TEST(test_alloc_timeline);
+ err += RUN_TEST(test_alloc_fence);
+ err += RUN_TEST(test_alloc_fence_negative);
+
+ if (err)
+ printf("[FAIL]\tsync errors: %d\n", err);
+ else
+ printf("[OK]\tsync\n");
+
+ return !!err;
+}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
new file mode 100644
index 0000000..7d2d8ce
--- /dev/null
+++ b/tools/testing/selftests/sync/synctest.h
@@ -0,0 +1,47 @@
+/*
+ * sync tests
+ * Copyright 2015-2016 Collabora Ltd.
+ *
+ * Based on the implementation from the Android Open Source Project,
+ *
+ * Copyright 2012 Google, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SELFTESTS_SYNCTEST_H
+#define SELFTESTS_SYNCTEST_H
+
+#include <stdio.h>
+
+#define ASSERT(cond, msg) do { \
+ if (!(cond)) { \
+ printf("[BAD]\t%s", (msg)); \
+ return 1; \
+ } \
+} while (0)
+
+#define RUN_TEST(x) run_test((x), #x)
+
+/* Allocation tests */
+int test_alloc_timeline(void);
+int test_alloc_fence(void);
+int test_alloc_fence_negative(void);
+
+#endif
--
2.10.1

2016-11-01 16:18:55

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] selftest: sync: basic tests for sw_sync framework

Hi Emilio,

2016-10-19 Emilio L?pez <[email protected]>:

> These tests are based on the libsync test suite from Android.
> This commit lays the ground for future tests, as well as includes
> tests for a variety of basic allocation commands.
>
> Signed-off-by: Emilio L?pez <[email protected]>
> ---
> tools/testing/selftests/Makefile | 1 +
> tools/testing/selftests/sync/.gitignore | 1 +
> tools/testing/selftests/sync/Makefile | 18 +++
> tools/testing/selftests/sync/sw_sync.h | 46 +++++++
> tools/testing/selftests/sync/sync.c | 221 ++++++++++++++++++++++++++++++
> tools/testing/selftests/sync/sync.h | 40 ++++++
> tools/testing/selftests/sync/sync_alloc.c | 74 ++++++++++
> tools/testing/selftests/sync/sync_test.c | 71 ++++++++++
> tools/testing/selftests/sync/synctest.h | 47 +++++++
> 9 files changed, 519 insertions(+)
> create mode 100644 tools/testing/selftests/sync/.gitignore
> create mode 100644 tools/testing/selftests/sync/Makefile
> create mode 100644 tools/testing/selftests/sync/sw_sync.h
> create mode 100644 tools/testing/selftests/sync/sync.c
> create mode 100644 tools/testing/selftests/sync/sync.h
> create mode 100644 tools/testing/selftests/sync/sync_alloc.c
> create mode 100644 tools/testing/selftests/sync/sync_test.c
> create mode 100644 tools/testing/selftests/sync/synctest.h
>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index f770dba..69cf1a6 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -23,6 +23,7 @@ TARGETS += seccomp
> TARGETS += sigaltstack
> TARGETS += size
> TARGETS += static_keys
> +TARGETS += sync
> TARGETS += sysctl
> ifneq (1, $(quicktest))
> TARGETS += timers
> diff --git a/tools/testing/selftests/sync/.gitignore b/tools/testing/selftests/sync/.gitignore
> new file mode 100644
> index 0000000..f5091e7
> --- /dev/null
> +++ b/tools/testing/selftests/sync/.gitignore
> @@ -0,0 +1 @@
> +sync_test
> diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
> new file mode 100644
> index 0000000..620a59a
> --- /dev/null
> +++ b/tools/testing/selftests/sync/Makefile
> @@ -0,0 +1,18 @@
> +CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
> +CFLAGS += -I../../../../usr/include/
> +LDFLAGS += -pthread
> +
> +TEST_PROGS = sync_test
> +
> +all: $(TEST_PROGS)
> +
> +include ../lib.mk
> +
> +OBJS = sync_test.o sync.o
> +
> +TESTS += sync_alloc.o
> +
> +sync_test: $(OBJS) $(TESTS)
> +
> +clean:
> + $(RM) sync_test $(OBJS) $(TESTS)
> diff --git a/tools/testing/selftests/sync/sw_sync.h b/tools/testing/selftests/sync/sw_sync.h
> new file mode 100644
> index 0000000..e2cfc6ba
> --- /dev/null
> +++ b/tools/testing/selftests/sync/sw_sync.h
> @@ -0,0 +1,46 @@
> +/*
> + * sw_sync abstraction
> + *
> + * Copyright 2015-2016 Collabora Ltd.
> + *
> + * Based on the implementation from the Android Open Source Project,
> + *
> + * Copyright 2013 Google, Inc
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef SELFTESTS_SW_SYNC_H
> +#define SELFTESTS_SW_SYNC_H
> +
> +/*
> + * sw_sync is mainly intended for testing and should not be compiled into
> + * production kernels
> + */
> +
> +int sw_sync_timeline_create(void);
> +int sw_sync_timeline_is_valid(int fd);
> +int sw_sync_timeline_inc(int fd, unsigned int count);
> +void sw_sync_timeline_destroy(int fd);
> +
> +int sw_sync_fence_create(int fd, const char *name, unsigned int value);
> +int sw_sync_fence_is_valid(int fd);
> +void sw_sync_fence_destroy(int fd);
> +
> +#endif
> diff --git a/tools/testing/selftests/sync/sync.c b/tools/testing/selftests/sync/sync.c
> new file mode 100644
> index 0000000..f3d599f
> --- /dev/null
> +++ b/tools/testing/selftests/sync/sync.c
> @@ -0,0 +1,221 @@
> +/*
> + * sync / sw_sync abstraction
> + * Copyright 2015-2016 Collabora Ltd.
> + *
> + * Based on the implementation from the Android Open Source Project,
> + *
> + * Copyright 2012 Google, Inc
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include <fcntl.h>
> +#include <malloc.h>
> +#include <poll.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include <sys/ioctl.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +
> +#include "sync.h"
> +#include "sw_sync.h"
> +
> +#include <linux/sync_file.h>
> +
> +
> +/* SW_SYNC ioctls */
> +struct sw_sync_create_fence_data {
> + __u32 value;
> + char name[32];
> + __s32 fence;
> +};
> +
> +#define SW_SYNC_IOC_MAGIC 'W'
> +#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
> + struct sw_sync_create_fence_data)
> +#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
> +
> +
> +int sync_wait(int fd, int timeout)
> +{
> + struct pollfd fds;
> +
> + fds.fd = fd;
> + fds.events = POLLIN | POLLERR;
> +
> + return poll(&fds, 1, timeout);
> +}

I think it is a good idea to keep the sync_wait behaviour similar to
what it was on android libsync. It should be something like this:

int sw_sync_wait(int fd, int timeout)
{
struct pollfd fds = {0};
int ret;

fds.fd = fd;
fds.events = POLLIN;

do {
ret = poll(&fds, 1, timeout);
if (ret > 0) {
if (fds.revents & (POLLERR | POLLNVAL)) {
errno = EINVAL;
return -1;
}
return 0;
} else if (ret == 0) {
errno = ETIME;
return -1;
}
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));

return ret;
}


Gustavo

2016-12-02 01:23:19

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH v2 0/7] Tests for sync infrastructure

On 10/19/2016 06:49 AM, Emilio López wrote:
> Hello everyone,
>
> This is a series of tests to exercise the sync kernel infrastructure. It is
> meant to be a test suite for the work Gustavo has been doing to destage it.
>
> These tests were originally part of a battery of tests shipping with
> Android's libsync that were rewritten to use the new userspace interfaces.
>
> This is the second iteration of the test suite. Main changes over v1 are
> a reworked Makefile and small code style fixes.
>
> If you are testing this on v4.9-rc1, do note that the last test will
> currently fail due to a regression[0].

Hi Emilio,

Thanks. I will apply these to linux-kselftest next for 4.10-rc1

-- Shuah
>
> As usual, all comments are welcome.
>
> Cheers!
> Emilio
>
> [0] https://patchwork.kernel.org/patch/9343347/
>
> Emilio López (7):
> selftest: sync: basic tests for sw_sync framework
> selftest: sync: fence tests for sw_sync framework
> selftest: sync: merge tests for sw_sync framework
> selftest: sync: wait tests for sw_sync framework
> selftest: sync: stress test for parallelism
> selftest: sync: stress consumer/producer test
> selftest: sync: stress test for merges
>
> tools/testing/selftests/Makefile | 1 +
> tools/testing/selftests/sync/.gitignore | 1 +
> tools/testing/selftests/sync/Makefile | 24 +++
> tools/testing/selftests/sync/sw_sync.h | 46 +++++
> tools/testing/selftests/sync/sync.c | 221 +++++++++++++++++++++
> tools/testing/selftests/sync/sync.h | 40 ++++
> tools/testing/selftests/sync/sync_alloc.c | 74 +++++++
> tools/testing/selftests/sync/sync_fence.c | 132 ++++++++++++
> tools/testing/selftests/sync/sync_merge.c | 60 ++++++
> .../testing/selftests/sync/sync_stress_consumer.c | 185 +++++++++++++++++
> tools/testing/selftests/sync/sync_stress_merge.c | 115 +++++++++++
> .../selftests/sync/sync_stress_parallelism.c | 111 +++++++++++
> tools/testing/selftests/sync/sync_test.c | 79 ++++++++
> tools/testing/selftests/sync/sync_wait.c | 91 +++++++++
> tools/testing/selftests/sync/synctest.h | 66 ++++++
> 15 files changed, 1246 insertions(+)
> create mode 100644 tools/testing/selftests/sync/.gitignore
> create mode 100644 tools/testing/selftests/sync/Makefile
> create mode 100644 tools/testing/selftests/sync/sw_sync.h
> create mode 100644 tools/testing/selftests/sync/sync.c
> create mode 100644 tools/testing/selftests/sync/sync.h
> create mode 100644 tools/testing/selftests/sync/sync_alloc.c
> create mode 100644 tools/testing/selftests/sync/sync_fence.c
> create mode 100644 tools/testing/selftests/sync/sync_merge.c
> create mode 100644 tools/testing/selftests/sync/sync_stress_consumer.c
> create mode 100644 tools/testing/selftests/sync/sync_stress_merge.c
> create mode 100644 tools/testing/selftests/sync/sync_stress_parallelism.c
> create mode 100644 tools/testing/selftests/sync/sync_test.c
> create mode 100644 tools/testing/selftests/sync/sync_wait.c
> create mode 100644 tools/testing/selftests/sync/synctest.h
>

2016-12-02 14:09:27

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH v2 0/7] Tests for sync infrastructure

On 12/01/2016 06:17 PM, Shuah Khan wrote:
> On 10/19/2016 06:49 AM, Emilio López wrote:
>> Hello everyone,
>>
>> This is a series of tests to exercise the sync kernel infrastructure. It is
>> meant to be a test suite for the work Gustavo has been doing to destage it.
>>
>> These tests were originally part of a battery of tests shipping with
>> Android's libsync that were rewritten to use the new userspace interfaces.
>>
>> This is the second iteration of the test suite. Main changes over v1 are
>> a reworked Makefile and small code style fixes.
>>
>> If you are testing this on v4.9-rc1, do note that the last test will
>> currently fail due to a regression[0].
>
> Hi Emilio,
>
> Thanks. I will apply these to linux-kselftest next for 4.10-rc1
>
> -- Shuah
>>
>> As usual, all comments are welcome.
>>

Hi Emilio,

Applied to linux-kselftest next. Could you take a look at the output
and see if it can be refined. Does [BAD] mean the test failed? Results
could refined to help user understand if a test failed or not clearly.
This can be done in a separate patch as a fix in one of the 4.01-rcs

thanks,
-- Shuah

2016-12-13 16:47:57

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] selftest: sync: basic tests for sw_sync framework

Hi Gustavo,

On 11/01/2016 10:18 AM, Gustavo Padovan wrote:
> Hi Emilio,
>
> 2016-10-19 Emilio L?pez <[email protected]>:
>
>> These tests are based on the libsync test suite from Android.
>> This commit lays the ground for future tests, as well as includes
>> tests for a variety of basic allocation commands.
>>
>> Signed-off-by: Emilio L?pez <[email protected]>
>> ---
>> tools/testing/selftests/Makefile | 1 +
>> tools/testing/selftests/sync/.gitignore | 1 +
>> tools/testing/selftests/sync/Makefile | 18 +++
>> tools/testing/selftests/sync/sw_sync.h | 46 +++++++
>> tools/testing/selftests/sync/sync.c | 221 ++++++++++++++++++++++++++++++
>> tools/testing/selftests/sync/sync.h | 40 ++++++
>> tools/testing/selftests/sync/sync_alloc.c | 74 ++++++++++
>> tools/testing/selftests/sync/sync_test.c | 71 ++++++++++
>> tools/testing/selftests/sync/synctest.h | 47 +++++++
>> 9 files changed, 519 insertions(+)
>> create mode 100644 tools/testing/selftests/sync/.gitignore
>> create mode 100644 tools/testing/selftests/sync/Makefile
>> create mode 100644 tools/testing/selftests/sync/sw_sync.h
>> create mode 100644 tools/testing/selftests/sync/sync.c
>> create mode 100644 tools/testing/selftests/sync/sync.h
>> create mode 100644 tools/testing/selftests/sync/sync_alloc.c
>> create mode 100644 tools/testing/selftests/sync/sync_test.c
>> create mode 100644 tools/testing/selftests/sync/synctest.h
>>
>> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
>> index f770dba..69cf1a6 100644
>> --- a/tools/testing/selftests/Makefile
>> +++ b/tools/testing/selftests/Makefile
>> @@ -23,6 +23,7 @@ TARGETS += seccomp
>> TARGETS += sigaltstack
>> TARGETS += size
>> TARGETS += static_keys
>> +TARGETS += sync
>> TARGETS += sysctl
>> ifneq (1, $(quicktest))
>> TARGETS += timers
>> diff --git a/tools/testing/selftests/sync/.gitignore b/tools/testing/selftests/sync/.gitignore
>> new file mode 100644
>> index 0000000..f5091e7
>> --- /dev/null
>> +++ b/tools/testing/selftests/sync/.gitignore
>> @@ -0,0 +1 @@
>> +sync_test
>> diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
>> new file mode 100644
>> index 0000000..620a59a
>> --- /dev/null
>> +++ b/tools/testing/selftests/sync/Makefile
>> @@ -0,0 +1,18 @@
>> +CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
>> +CFLAGS += -I../../../../usr/include/
>> +LDFLAGS += -pthread
>> +
>> +TEST_PROGS = sync_test
>> +
>> +all: $(TEST_PROGS)
>> +
>> +include ../lib.mk
>> +
>> +OBJS = sync_test.o sync.o
>> +
>> +TESTS += sync_alloc.o
>> +
>> +sync_test: $(OBJS) $(TESTS)
>> +
>> +clean:
>> + $(RM) sync_test $(OBJS) $(TESTS)
>> diff --git a/tools/testing/selftests/sync/sw_sync.h b/tools/testing/selftests/sync/sw_sync.h
>> new file mode 100644
>> index 0000000..e2cfc6ba
>> --- /dev/null
>> +++ b/tools/testing/selftests/sync/sw_sync.h
>> @@ -0,0 +1,46 @@
>> +/*
>> + * sw_sync abstraction
>> + *
>> + * Copyright 2015-2016 Collabora Ltd.
>> + *
>> + * Based on the implementation from the Android Open Source Project,
>> + *
>> + * Copyright 2013 Google, Inc
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +#ifndef SELFTESTS_SW_SYNC_H
>> +#define SELFTESTS_SW_SYNC_H
>> +
>> +/*
>> + * sw_sync is mainly intended for testing and should not be compiled into
>> + * production kernels
>> + */
>> +
>> +int sw_sync_timeline_create(void);
>> +int sw_sync_timeline_is_valid(int fd);
>> +int sw_sync_timeline_inc(int fd, unsigned int count);
>> +void sw_sync_timeline_destroy(int fd);
>> +
>> +int sw_sync_fence_create(int fd, const char *name, unsigned int value);
>> +int sw_sync_fence_is_valid(int fd);
>> +void sw_sync_fence_destroy(int fd);
>> +
>> +#endif
>> diff --git a/tools/testing/selftests/sync/sync.c b/tools/testing/selftests/sync/sync.c
>> new file mode 100644
>> index 0000000..f3d599f
>> --- /dev/null
>> +++ b/tools/testing/selftests/sync/sync.c
>> @@ -0,0 +1,221 @@
>> +/*
>> + * sync / sw_sync abstraction
>> + * Copyright 2015-2016 Collabora Ltd.
>> + *
>> + * Based on the implementation from the Android Open Source Project,
>> + *
>> + * Copyright 2012 Google, Inc
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +#include <fcntl.h>
>> +#include <malloc.h>
>> +#include <poll.h>
>> +#include <stdint.h>
>> +#include <string.h>
>> +#include <unistd.h>
>> +
>> +#include <sys/ioctl.h>
>> +#include <sys/stat.h>
>> +#include <sys/types.h>
>> +
>> +#include "sync.h"
>> +#include "sw_sync.h"
>> +
>> +#include <linux/sync_file.h>
>> +
>> +
>> +/* SW_SYNC ioctls */
>> +struct sw_sync_create_fence_data {
>> + __u32 value;
>> + char name[32];
>> + __s32 fence;
>> +};
>> +
>> +#define SW_SYNC_IOC_MAGIC 'W'
>> +#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
>> + struct sw_sync_create_fence_data)
>> +#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
>> +
>> +
>> +int sync_wait(int fd, int timeout)
>> +{
>> + struct pollfd fds;
>> +
>> + fds.fd = fd;
>> + fds.events = POLLIN | POLLERR;
>> +
>> + return poll(&fds, 1, timeout);
>> +}
>
> I think it is a good idea to keep the sync_wait behaviour similar to
> what it was on android libsync. It should be something like this:

I didn't notice that this comment wasn't addressed. I will go ahead
and continue with the plan to get these into 4.10-rc1. If you want
to send me patch for this behavior, please do. We can address that
as a fix in 4.10-rc2

>
> int sw_sync_wait(int fd, int timeout)
> {
> struct pollfd fds = {0};
> int ret;
>
> fds.fd = fd;
> fds.events = POLLIN;
>
> do {
> ret = poll(&fds, 1, timeout);
> if (ret > 0) {
> if (fds.revents & (POLLERR | POLLNVAL)) {
> errno = EINVAL;
> return -1;
> }
> return 0;
> } else if (ret == 0) {
> errno = ETIME;
> return -1;
> }
> } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
>
> return ret;
> }
>
>
> Gustavo
>

thanks,
-- Shuah