[igt-dev] [PATCH i-g-t] igt/drm_read: Exercise waking up the next waiter

Ville Syrjälä ville.syrjala at linux.intel.com
Wed Feb 27 20:46:12 UTC 2019


On Wed, Feb 27, 2019 at 10:20:19AM +0000, Chris Wilson wrote:
> Try to hit a bug in the kernel whereby a short reader does not wakeup
> the next waiter (on the same fd) leading to forever blocking.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
>  tests/drm_read.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
> 
> diff --git a/tests/drm_read.c b/tests/drm_read.c
> index 309f389f6..923a9f750 100644
> --- a/tests/drm_read.c
> +++ b/tests/drm_read.c
> @@ -43,6 +43,7 @@
>  #include <sys/ioctl.h>
>  #include <sys/time.h>
>  #include <sys/poll.h>
> +#include <pthread.h>
>  #include "drm.h"
>  
>  IGT_TEST_DESCRIPTION("Call read(drm) and see if it behaves.");
> @@ -166,6 +167,90 @@ static void test_short_buffer(int in, int nonblock, enum pipe pipe)
>  	teardown(fd);
>  }
>  
> +struct short_buffer_wakeup {
> +	pthread_mutex_t mutex;
> +	pthread_cond_t send, recv;
> +	int counter;
> +	int done;
> +	int fd;
> +};
> +
> +static void *thread_short_buffer_wakeup(void *arg)
> +{
> +	struct short_buffer_wakeup *w = arg;
> +	char buffer[1024]; /* events are typically 32 bytes */
> +
> +	while (!w->done) {
> +		/* Short read, does not consume the event. */
> +		igt_assert_eq(read(w->fd, buffer, 4), 0);
> +
> +		pthread_mutex_lock(&w->mutex);
> +		if (!--w->counter)
> +			pthread_cond_signal(&w->send);
> +		pthread_cond_wait(&w->recv, &w->mutex);
> +		pthread_mutex_unlock(&w->mutex);
> +	}
> +
> +	return NULL;
> +}
> +
> +static void test_short_buffer_wakeup(int in, enum pipe pipe)
> +{
> +	const int nt = sysconf(_SC_NPROCESSORS_ONLN) + 1;

Hmm. I guess with less threads there's a better chance
they'd all escape the wait_for_event() before the list
becomes empty and just all pile up on the mutex. So I
was wondering if even more would be better. But since
CI already found the problem with this I guess it's
sufficient.

Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

> +	struct short_buffer_wakeup w = {
> +		.fd = setup(in, 0),
> +	};
> +	pthread_t t[nt];
> +	char buffer[1024]; /* events are typically 32 bytes */
> +
> +	pthread_mutex_init(&w.mutex, NULL);
> +	pthread_cond_init(&w.send, NULL);
> +	pthread_cond_init(&w.recv, NULL);
> +
> +	for (int n = 0; n < nt; n++)
> +		pthread_create(&t[n], NULL, thread_short_buffer_wakeup, &w);
> +
> +	igt_until_timeout(30) {
> +		struct timespec tv;
> +		int err = 0;
> +
> +		pthread_mutex_lock(&w.mutex);
> +		w.counter = nt;
> +		pthread_cond_broadcast(&w.recv);
> +		pthread_mutex_unlock(&w.mutex);
> +
> +		/* Give each thread a chance to sleep in drm_read() */
> +		pthread_yield();
> +
> +		/* One event should wake all threads as none consume */
> +		generate_event(w.fd, pipe);
> +
> +		clock_gettime(CLOCK_REALTIME, &tv);
> +		tv.tv_sec += 5; /* Let's be very generous to the scheduler */
> +
> +		pthread_mutex_lock(&w.mutex);
> +		while (w.counter && !err)
> +			err = pthread_cond_timedwait(&w.send, &w.mutex, &tv);
> +		pthread_mutex_unlock(&w.mutex);
> +
> +		igt_assert_f(err == 0,
> +			     "Timed out waiting for drm_read() to wakeup on an event\n");
> +
> +
> +		/* No thread should consume the event */
> +		igt_assert(read(w.fd, buffer, 40) > 0);
> +	}
> +	pthread_mutex_lock(&w.mutex);
> +	w.done = true;
> +	pthread_cond_broadcast(&w.recv);
> +	pthread_mutex_unlock(&w.mutex);
> +
> +	for (int n = 0; n < nt; n++)
> +		pthread_join(t[n], NULL);
> +
> +	close(w.fd);
> +}
> +
>  igt_main
>  {
>  	int fd;
> @@ -218,4 +303,7 @@ igt_main
>  
>  	igt_subtest("short-buffer-nonblock")
>  		test_short_buffer(fd, 1, pipe);
> +
> +	igt_subtest("short-buffer-wakeup")
> +		test_short_buffer_wakeup(fd, pipe);
>  }
> -- 
> 2.20.1
> 
> _______________________________________________
> igt-dev mailing list
> igt-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev

-- 
Ville Syrjälä
Intel


More information about the igt-dev mailing list