[PATCH i-g-t v2 15/66] tests/xe_eudebug: Race discovery against eudebug attach.

Piatkowski, Dominik Karol dominik.karol.piatkowski at intel.com
Thu Aug 1 12:08:41 UTC 2024


Comment below.

Thanks,
Dominik Karol

> -----Original Message-----
> From: Manszewski, Christoph <christoph.manszewski at intel.com>
> Sent: Tuesday, July 30, 2024 1:45 PM
> To: igt-dev at lists.freedesktop.org
> Cc: Kempczynski, Zbigniew <zbigniew.kempczynski at intel.com>; Kamil
> Konieczny <kamil.konieczny at linux.intel.com>; Grzegorzek, Dominik
> <dominik.grzegorzek at intel.com>; Patelczyk, Maciej
> <maciej.patelczyk at intel.com>; Piatkowski, Dominik Karol
> <dominik.karol.piatkowski at intel.com>; Sikora, Pawel
> <pawel.sikora at intel.com>; Hajda, Andrzej <andrzej.hajda at intel.com>;
> Kolanupaka Naveena <kolanupaka.naveena at intel.com>; Kuoppala, Mika
> <mika.kuoppala at intel.com>; Mun, Gwan-gyeong <gwan-
> gyeong.mun at intel.com>
> Subject: [PATCH i-g-t v2 15/66] tests/xe_eudebug: Race discovery against
> eudebug attach.
> 
> From: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
> 
> Validate eu debug resource discovery in a pretty cruel way.
> Add subtests:
> 
> 1) discovery-race - spawns N client proccesses, which create
>    N+N*N resources each, then it creates M debugger
>    threads competing for an access to the client proccess. After
>    successful attach, with probability of 0.5 read and assert
>    discovered resources, immediately detach otherwise.
> 
> 2) discovery-empty[|-clients] - same as 1#, but destroy
>    resources in flight (explicetly or by closing the client).

Typo: explicitly

>    Expect the last discovery not sending any events.
> 
> Currently N = 4, M = 3.
> 
> Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
> Signed-off-by: Karolina Stolarek <karolina.stolarek at intel.com>
> Cc: Christoph Manszewski <christoph.manszewski at intel.com>
> ---
>  tests/intel/xe_eudebug.c | 254
> +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 254 insertions(+)
> 
> diff --git a/tests/intel/xe_eudebug.c b/tests/intel/xe_eudebug.c index
> 7c1c21a33..d97e7914e 100644
> --- a/tests/intel/xe_eudebug.c
> +++ b/tests/intel/xe_eudebug.c
> @@ -282,6 +282,251 @@ static void test_basic_sessions(int fd, unsigned int
> flags, int count)
>  		xe_eudebug_session_destroy(s[i]);
>  }
> 
> +#define RESOURCE_COUNT 16
> +#define PRIMARY_THREAD			(1 << 0)
> +#define DISCOVERY_CLOSE_CLIENT		(1 << 1)
> +#define DISCOVERY_DESTROY_RESOURCES	(1 << 2)
> +static void run_discovery_client(struct xe_eudebug_client *c) {
> +	int fd[RESOURCE_COUNT], i;
> +	bool skip_sleep = c->flags & (DISCOVERY_DESTROY_RESOURCES |
> +DISCOVERY_CLOSE_CLIENT);
> +
> +	srand(getpid());
> +
> +	for (i = 0; i < RESOURCE_COUNT; i++) {
> +		fd[i] = xe_eudebug_client_open_driver(c);
> +
> +		/*
> +		 * Give the debugger a break in event stream after every
> +		 * other client, that allows to read discovery and dettach in
> quiet.
> +		 */
> +		if (random() % 2 == 0 && !skip_sleep)
> +			sleep(1);
> +
> +		for (int j = 0; j < RESOURCE_COUNT; j++) {
> +			uint32_t vm = xe_eudebug_client_vm_create(c, fd[i],
> 0, 0);
> +
> +			if (c->flags & DISCOVERY_DESTROY_RESOURCES)
> +				xe_eudebug_client_vm_destroy(c, fd[i], vm);
> +		}
> +
> +		if (c->flags & DISCOVERY_CLOSE_CLIENT)
> +			xe_eudebug_client_close_driver(c, fd[i]);
> +	}
> +}
> +
> +/**
> + * SUBTEST: discovery-%s
> + * Description: Race discovery against %arg[1] and the debugger dettach.
> + *
> + * arg[1]:
> + *
> + * @race:		resources creation
> + * @empty:		resources destruction
> + * @empty-clients:	client closure
> + */
> +static void *discovery_race_thread(void *data) {
> +	struct {
> +		uint64_t client_handle;
> +		int vm_count;
> +	} clients[RESOURCE_COUNT];
> +	struct xe_eudebug_session *s = data;
> +	int expected = RESOURCE_COUNT * (1 + RESOURCE_COUNT);
> +	const int tries = 100;
> +	bool done = false;
> +	int ret = 0;
> +
> +	for (int try = 0; try < tries && !done; try++) {
> +
> +		ret = xe_eudebug_debugger_attach(s->d, s->c);
> +
> +		if (ret == -EBUSY) {
> +			usleep(100000);
> +			continue;
> +		}
> +
> +		igt_assert_eq(ret, 0);
> +
> +		if (random() % 2) {
> +			struct drm_xe_eudebug_event *e = NULL;
> +			int i = -1;
> +
> +			xe_eudebug_debugger_start_worker(s->d);
> +			sleep(1);
> +			xe_eudebug_debugger_stop_worker(s->d, 1);
> +			igt_debug("Resources discovered: %lu\n", s->d-
> >event_count);
> +
> +			xe_eudebug_for_each_event(e, s->d->log) {
> +				if (e->type ==
> DRM_XE_EUDEBUG_EVENT_OPEN) {
> +					struct drm_xe_eudebug_event_client
> *eo = (void *)e;
> +
> +					if (i >= 0) {
> +
> 	igt_assert_eq(clients[i].vm_count,
> +
> RESOURCE_COUNT);
> +					}
> +
> +					igt_assert(++i < RESOURCE_COUNT);
> +					clients[i].client_handle = eo-
> >client_handle;
> +					clients[i].vm_count = 0;
> +				}
> +
> +				if (e->type ==
> DRM_XE_EUDEBUG_EVENT_VM)
> +					clients[i].vm_count++;
> +			};
> +
> +			igt_assert_lte(0, i);
> +
> +			for (int j = 0; j < i; j++)
> +				for (int k = 0; k < i; k++) {
> +					if (k == j)
> +						continue;
> +
> +
> 	igt_assert_neq(clients[j].client_handle,
> +						       clients[k].client_handle);
> +				}
> +
> +			if (s->d->event_count >= expected)
> +				done = true;
> +		}
> +
> +		xe_eudebug_debugger_dettach(s->d);
> +		s->d->log->head = 0;
> +		s->d->event_count = 0;
> +	}
> +
> +	/* Primary thread must read everything */
> +	if (s->flags & PRIMARY_THREAD) {
> +		while ((ret = xe_eudebug_debugger_attach(s->d, s->c)) == -
> EBUSY)
> +			usleep(100000);
> +
> +		igt_assert_eq(ret, 0);
> +
> +		xe_eudebug_debugger_start_worker(s->d);
> +		xe_eudebug_client_wait_done(s->c);
> +
> +		if (READ_ONCE(s->d->event_count) != expected)
> +			sleep(5);
> +
> +		xe_eudebug_debugger_stop_worker(s->d, 1);
> +		xe_eudebug_debugger_dettach(s->d);
> +	}
> +
> +	return NULL;
> +}
> +
> +static void test_race_discovery(int fd, unsigned int flags, int
> +clients) {
> +	const int debuggers_per_client = 3;
> +	int count = clients * debuggers_per_client;
> +	struct xe_eudebug_session *sessions, *s;
> +	struct xe_eudebug_client *c;
> +	pthread_t *threads;
> +	int i, j;
> +
> +	sessions = calloc(count, sizeof(*sessions));
> +	threads = calloc(count, sizeof(*threads));
> +
> +	for (i = 0; i < clients; i++) {
> +		c = xe_eudebug_client_create(fd, run_discovery_client, flags,
> NULL);
> +		for (j = 0; j < debuggers_per_client; j++) {
> +			s = &sessions[i * debuggers_per_client + j];
> +			s->c = c;
> +			s->d = xe_eudebug_debugger_create(fd, flags, NULL);
> +			s->flags = flags | (!j ? PRIMARY_THREAD : 0);
> +		}
> +	}
> +
> +	for (i = 0; i < count; i++) {
> +		if (sessions[i].flags & PRIMARY_THREAD)
> +			xe_eudebug_client_start(sessions[i].c);
> +
> +		pthread_create(&threads[i], NULL, discovery_race_thread,
> &sessions[i]);
> +	}
> +
> +	for (i = 0; i < count; i++)
> +		pthread_join(threads[i], NULL);
> +
> +	for (i = count - 1; i > 0; i--) {
> +		if (sessions[i].flags & PRIMARY_THREAD) {
> +			igt_assert_eq(sessions[i].c->seqno-1, sessions[i].d-
> >event_count);
> +
> +			xe_eudebug_event_log_compare(sessions[0].d->log,
> +						     sessions[i].d->log, 0);
> +
> +			xe_eudebug_client_destroy(sessions[i].c);
> +		}
> +		xe_eudebug_debugger_destroy(sessions[i].d);
> +	}
> +}
> +
> +static void *attach_dettach_thread(void *data) {
> +	struct xe_eudebug_session *s = data;
> +	const int tries = 100;
> +	int ret = 0;
> +
> +	for (int try = 0; try < tries; try++) {
> +
> +		ret = xe_eudebug_debugger_attach(s->d, s->c);
> +
> +		if (ret == -EBUSY) {
> +			usleep(100000);
> +			continue;
> +		}
> +
> +		igt_assert_eq(ret, 0);
> +
> +		if (random() % 2 == 0) {
> +			xe_eudebug_debugger_start_worker(s->d);
> +			xe_eudebug_debugger_stop_worker(s->d, 1);
> +		}
> +
> +		xe_eudebug_debugger_dettach(s->d);
> +		s->d->log->head = 0;
> +		s->d->event_count = 0;
> +	}
> +
> +	return NULL;
> +}
> +
> +static void test_empty_discovery(int fd, unsigned int flags, int
> +clients) {
> +	struct xe_eudebug_session **s;
> +	pthread_t *threads;
> +	int i, expected = flags & DISCOVERY_CLOSE_CLIENT ? 0 :
> RESOURCE_COUNT;
> +
> +	igt_assert(flags & (DISCOVERY_DESTROY_RESOURCES |
> +DISCOVERY_CLOSE_CLIENT));
> +
> +	s = calloc(clients, sizeof(struct xe_eudebug_session *));
> +	threads = calloc(clients, sizeof(*threads));
> +
> +	for (i = 0; i < clients; i++)
> +		s[i] = xe_eudebug_session_create(fd, run_discovery_client,
> flags,
> +NULL);
> +
> +	for (i = 0; i < clients; i++) {
> +		xe_eudebug_client_start(s[i]->c);
> +
> +		pthread_create(&threads[i], NULL, attach_dettach_thread,
> s[i]);
> +	}
> +
> +	for (i = 0; i < clients; i++)
> +		pthread_join(threads[i], NULL);
> +
> +	for (i = 0; i < clients; i++) {
> +		xe_eudebug_client_wait_done(s[i]->c);
> +		igt_assert_eq(xe_eudebug_debugger_attach(s[i]->d, s[i]->c),
> 0);
> +
> +		xe_eudebug_debugger_start_worker(s[i]->d);
> +		xe_eudebug_debugger_stop_worker(s[i]->d, 5);
> +		xe_eudebug_debugger_dettach(s[i]->d);
> +
> +		igt_assert_eq(s[i]->d->event_count, expected);
> +
> +		xe_eudebug_session_destroy(s[i]);
> +	}
> +}
> +
>  igt_main
>  {
>  	int fd;
> @@ -308,6 +553,15 @@ igt_main
>  	igt_subtest("basic-vms")
>  		test_basic_sessions(fd, CREATE_VMS, 1);
> 
> +	igt_subtest("discovery-race")
> +		test_race_discovery(fd, 0, 4);
> +
> +	igt_subtest("discovery-empty")
> +		test_empty_discovery(fd, DISCOVERY_CLOSE_CLIENT, 16);
> +
> +	igt_subtest("discovery-empty-clients")
> +		test_empty_discovery(fd, DISCOVERY_DESTROY_RESOURCES,
> 16);
> +
>  	igt_fixture
>  		drm_close_driver(fd);
>  }
> --
> 2.34.1



More information about the igt-dev mailing list