[igt-dev] [PATCH i-g-t] tests/sw_sync: Fix race condition for multi-producer termination
Chris Wilson
chris at chris-wilson.co.uk
Tue Feb 25 23:05:48 UTC 2020
Both the producer/consumer were using a timeout, relying on the consumer
completing after the producers -- which 50% of the time doesn't happen.
Close the timelines (previously leaked!) to cancel the producer threads.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
tests/sw_sync.c | 37 +++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/tests/sw_sync.c b/tests/sw_sync.c
index 63791e0e8..d3d2bec15 100644
--- a/tests/sw_sync.c
+++ b/tests/sw_sync.c
@@ -487,7 +487,6 @@ static void * test_sync_multi_consumer_thread(void *arg)
static void test_sync_multi_consumer(void)
{
-
data_t data_arr[MULTI_CONSUMER_THREADS];
pthread_t thread_arr[MULTI_CONSUMER_THREADS];
sem_t sem;
@@ -620,10 +619,9 @@ static int test_mspc_wait_on_fence(int fence)
static struct {
int threads;
- int counter;
+ _Atomic(uint32_t) counter;
int cons_timeline;
int *prod_timeline;
- pthread_mutex_t lock;
} test_mpsc_data;
static void *mpsc_producer_thread(void *d)
@@ -632,10 +630,14 @@ static void *mpsc_producer_thread(void *d)
int *prod_timeline = test_mpsc_data.prod_timeline;
int cons_timeline = test_mpsc_data.cons_timeline;
int seqno = 0;
- int fence;
- igt_until_timeout(1) {
- fence = sw_sync_timeline_create_fence(cons_timeline, seqno++);
+ while (1) {
+ int fence;
+
+ fence = __sw_sync_timeline_create_fence(cons_timeline,
+ seqno++);
+ if (fence < 0)
+ break;
/* Wait for the consumer to finish. Use alternate
* means of waiting on the fence
@@ -648,12 +650,7 @@ static void *mpsc_producer_thread(void *d)
"Failure waiting on fence\n");
}
- /* Every producer increments the counter, the consumer
- * checks and erases it
- */
- pthread_mutex_lock(&test_mpsc_data.lock);
- test_mpsc_data.counter++;
- pthread_mutex_unlock(&test_mpsc_data.lock);
+ atomic_fetch_add(&test_mpsc_data.counter, 1);
sw_sync_timeline_inc(prod_timeline[id], 1);
close(fence);
@@ -664,16 +661,22 @@ static void *mpsc_producer_thread(void *d)
static int mpsc_consumer_thread(void)
{
- int fence, merged, tmp, i;
int *prod_timeline = test_mpsc_data.prod_timeline;
int cons_timeline = test_mpsc_data.cons_timeline;
int n = test_mpsc_data.threads;
int seqno = 0;
igt_until_timeout(1) {
+ int fence;
+
fence = sw_sync_timeline_create_fence(prod_timeline[0],
++seqno);
- for (i = 1; i < n; i++) {
+ if (fence < 0)
+ break;
+
+ for (int i = 1; i < n; i++) {
+ int tmp, merged;
+
tmp = sw_sync_timeline_create_fence(prod_timeline[i],
seqno);
merged = sync_fence_merge(tmp, fence);
@@ -719,7 +722,6 @@ static void test_sync_multi_producer_single_consumer(void)
test_mpsc_data.cons_timeline = cons_timeline;
test_mpsc_data.threads = n;
test_mpsc_data.counter = 0;
- pthread_mutex_init(&test_mpsc_data.lock, NULL);
for (i = 0; i < n; i++) {
pthread_create(&threads[i], NULL, (void * (*)(void *))
@@ -729,8 +731,11 @@ static void test_sync_multi_producer_single_consumer(void)
mpsc_consumer_thread();
- for (i = 0; i < n; i++)
+ close(cons_timeline);
+ for (i = 0; i < n; i++) {
pthread_join(threads[i], NULL);
+ close(prod_timeline[i]);
+ }
}
static void test_sync_expired_merge(void)
--
2.25.1
More information about the igt-dev
mailing list