From 463408146a9c3f47a82baf246d8a33c72395d251 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sun, 17 Jul 2016 23:58:56 +0300 Subject: [PATCH] kms_cursor_legacy: Fix mutex starvation Signed-off-by: Imre Deak --- tests/kms_cursor_legacy.c | 63 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/tests/kms_cursor_legacy.c b/tests/kms_cursor_legacy.c index 7dca383..15e071d 100644 --- a/tests/kms_cursor_legacy.c +++ b/tests/kms_cursor_legacy.c @@ -24,6 +24,7 @@ #define _GNU_SOURCE #include +#include #include "igt.h" #include "igt_rand.h" @@ -347,11 +348,17 @@ static void basic_cursor_vs_flip(struct data *data, int nloops) struct drm_event_vblank vbl; struct igt_fb fb_info; unsigned vblank_start, vblank_last; - volatile unsigned long *shared; + struct { + volatile unsigned long count; + volatile bool flipping; + pthread_mutex_t mutex; + pthread_cond_t cond; + } *shared; int target; uint32_t fb_id; - shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + shared = mmap(NULL, sizeof(*shared), PROT_WRITE, MAP_SHARED | MAP_ANON, + -1, 0); igt_assert(shared != MAP_FAILED); memset(&arg, 0, sizeof(arg)); @@ -384,23 +391,61 @@ static void basic_cursor_vs_flip(struct data *data, int nloops) target); for (int i = 0; i < nloops; i++) { - shared[0] = 0; + pthread_mutexattr_t mutex_attr; + pthread_condattr_t cond_attr; + + shared->count = 0; + shared->flipping = false; + + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_setpshared(&mutex_attr, + PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&shared->mutex, &mutex_attr); + + pthread_condattr_init(&cond_attr); + pthread_condattr_setpshared(&cond_attr, + PTHREAD_PROCESS_SHARED); + pthread_cond_init(&shared->cond, &cond_attr); + igt_fork(child, 1) { unsigned long count = 0; - while (!shared[0]) { + + while (!shared->count) { + pthread_mutex_lock(&shared->mutex); + while (shared->flipping) + pthread_cond_wait(&shared->cond, + &shared->mutex); + pthread_mutex_unlock(&shared->mutex); + drmIoctl(data->fd, DRM_IOCTL_MODE_CURSOR, &arg); + count++; } igt_debug("child: %lu cursor updates\n", count); - shared[0] = count; + shared->count = count; } + + shared->flipping = true; + do_or_die(drmModePageFlip(data->fd, arg.crtc_id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, &fb_id)); + + pthread_mutex_lock(&shared->mutex); + shared->flipping = false; + pthread_cond_signal(&shared->cond); + pthread_mutex_unlock(&shared->mutex); + igt_assert_eq(read(data->fd, &vbl, sizeof(vbl)), sizeof(vbl)); vblank_start = vblank_last = vbl.sequence; for (int n = 0; n < 60; n++) { + shared->flipping = true; do_or_die(drmModePageFlip(data->fd, arg.crtc_id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, &fb_id)); + pthread_mutex_lock(&shared->mutex); + shared->flipping = false; + pthread_cond_signal(&shared->cond); + pthread_mutex_unlock(&shared->mutex); + igt_assert_eq(read(data->fd, &vbl, sizeof(vbl)), sizeof(vbl)); if (vbl.sequence != vblank_last + 1) { igt_warn("page flip %d was delayed, missed %d frames\n", @@ -410,18 +455,18 @@ static void basic_cursor_vs_flip(struct data *data, int nloops) } igt_assert_eq(vbl.sequence, vblank_start + 60); - shared[0] = 1; + shared->count = 1; igt_waitchildren(); - igt_assert_f(shared[0] > 60*target, + igt_assert_f(shared->count > 60*target, "completed %lu cursor updated in a period of 60 flips, " "we expect to complete approximately %lu updateds, " "with the threshold set at %lu\n", - shared[0], 2*60ul*target, 60ul*target); + shared->count, 2*60ul*target, 60ul*target); } igt_remove_fb(data->fd, &fb_info); gem_close(data->fd, arg.handle); - munmap((void *)shared, 4096); + munmap((void *)shared, sizeof(*shared)); } igt_main -- 2.7.4