[PATCH i-g-t v9] tests/intel/xe_compute: Add Compute workload Scheduling and Display EU busyness

Kamil Konieczny kamil.konieczny at linux.intel.com
Tue Jul 8 10:15:17 UTC 2025


Hi nishit.sharma,
On 2025-07-08 at 08:05:45 +0000, nishit.sharma at intel.com wrote:
> From: Nishit Sharma <nishit.sharma at intel.com>

please simplify your description in subject, imho this is better:

[PATCH i-g-t v9] tests/intel/xe_compute: Add Compute workload scheduling

I think by 'Display EU business' you mean 'print business'
and that info is not needed here. It is better to write it in description
below.

> 
> Adds compute workload scheduling and execution on multi-ccs available.
> This also adds logic to show EU busyness information on console while workload is running
--------------------------^^^^
imho s/show/print info about/
Also imho print only basic info about it and detailed one
with either --debug or some new option (if really needed?)

> on multiple CCS engine instances.
> 
> Signed-off-by: Nishit Sharma <nishit.sharma at intel.com>
> ---
>  lib/intel_compute.c      |  34 ++-
>  lib/intel_compute.h      |   2 +
>  tests/intel/xe_compute.c | 564 ++++++++++++++++++++++++++++++++++++++-
>  tests/meson.build        |   1 +
>  4 files changed, 594 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/intel_compute.c b/lib/intel_compute.c
> index 147dd2916..e1685788c 100644
> --- a/lib/intel_compute.c
> +++ b/lib/intel_compute.c
> @@ -255,8 +255,14 @@ static void bo_execenv_bind(struct bo_execenv *execenv,
>  				break;
>  			}
>  
> -			bo_dict[i].handle = xe_bo_create(fd, execenv->vm, bo_dict[i].size,
> -							 placement, flags);
> +			if (!execenv->user)
> +				bo_dict[i].handle = xe_bo_create(fd, execenv->vm, bo_dict[i].size,
> +								 placement, flags);
> +			else if (execenv->user)

Drop 'if (...)' here, no need to repeat negated first condition:
!!execenv->user == execenv->user 

Regards,
Kamil

> +				bo_dict[i].handle = xe_bo_create_caching(fd, execenv->vm,
> +									 bo_dict[i].size,
> +									 placement, flags,
> +									 DRM_XE_GEM_CPU_CACHING_WC);
>  			bo_dict[i].data = xe_bo_map(fd, bo_dict[i].handle, bo_dict[i].size);
>  			xe_vm_bind_async(fd, vm, 0, bo_dict[i].handle, 0, bo_dict[i].addr,
>  					 bo_dict[i].size, &sync, 1);
> @@ -1849,10 +1855,26 @@ static void xe2lpg_compute_exec(int fd, const unsigned char *kernel,
>  				    OFFSET_KERNEL, 0, false,
>  				    execenv.array_size);
>  
> -	bo_execenv_exec(&execenv, ADDR_BATCH);
> -
> -	if (!user || (user && !user->skip_results_check))
> -		bo_check_square(input_data, output_data, execenv.array_size);
> +	if (user && user->loop_kernel_duration) {
> +		bo_execenv_exec_async(&execenv, ADDR_BATCH);
> +		igt_measured_usleep(user->loop_kernel_duration);
> +		((int *)bo_dict[4].data)[0] = MAGIC_LOOP_STOP;
> +		bo_execenv_sync(&execenv);
> +		user->skip_results_check = 1;
> +	} else
> +		bo_execenv_exec(&execenv, ADDR_BATCH);
> +
> +	for (int i = 0; i < execenv.array_size; i++) {
> +		float input = input_data[i];
> +		float output = output_data[i];
> +		float expected_output = input * input;
> +
> +		if (output != expected_output)
> +			igt_debug("[%4d] input:%f output:%f expected_output:%f\n",
> +					i, input, output, expected_output);
> +		if (!user || (user && !user->skip_results_check))
> +			igt_assert_eq_double(output, expected_output);
> +	}
>  
>  	bo_execenv_unbind(&execenv, bo_dict, entries);
>  	bo_execenv_destroy(&execenv);
> diff --git a/lib/intel_compute.h b/lib/intel_compute.h
> index 412791d07..19977933f 100644
> --- a/lib/intel_compute.h
> +++ b/lib/intel_compute.h
> @@ -63,6 +63,8 @@ struct user_execenv {
>  	uint64_t input_addr;
>  	/** @output_addr: override default address of the output array if provided */
>  	uint64_t output_addr;
> +	/** @loop_kernel_duration: duration till kernel should execute in gpu **/
> +	uint32_t loop_kernel_duration;
>  };
>  
>  enum execenv_alloc_prefs {
> diff --git a/tests/intel/xe_compute.c b/tests/intel/xe_compute.c
> index 5e9140902..9a140c77f 100644
> --- a/tests/intel/xe_compute.c
> +++ b/tests/intel/xe_compute.c
> @@ -12,6 +12,7 @@
>   */
>  
>  #include <string.h>
> +#include <sys/ioctl.h>
>  
>  #include "igt.h"
>  #include "igt_sysfs.h"
> @@ -19,6 +20,45 @@
>  #include "xe/xe_ioctl.h"
>  #include "xe/xe_query.h"
>  
> +#include "igt_device.h"
> +#include "tools/gputop/xe_gputop.h"
> +#include "igt_drm_clients.h"
> +
> +/**
> + * Number of supported drivers needs to be adjusted as per the length of
> + * the drivers[] array.
> + */
> +#define	NUM_DRIVER	1
> +#define	LOOP_DURATION	(1000000ull)
> +#define	engine_ptr(engines, n)	(&(engines)->engine + (n))
> +#define NS_SLEEP	(1000000ull)
> +
> +enum utilization_type {
> +	UTILIZATION_TYPE_ENGINE_TIME,
> +	UTILIZATION_TYPE_TOTAL_CYCLES,
> +};
> +
> +bool workload_sched;
> +
> +pthread_barrier_t barrier;
> +struct thread_data {
> +	pthread_t thread;
> +	pthread_mutex_t *mutex;
> +	pthread_cond_t *cond;
> +	int class;
> +	int fd;
> +	int gt;
> +	struct user_execenv *execenv;
> +	struct drm_xe_engine_class_instance *eci;
> +	bool *go;
> +};
> +
> +struct xe_gpu_info {
> +	char *pmu_device;
> +	struct igt_device_card *card;
> +	struct xe_pmu_device *eng_obj;
> +};
> +
>  static int gt_sysfs_open(int gt)
>  {
>  	int fd, gt_fd;
> @@ -203,12 +243,530 @@ test_compute_square(int fd)
>  		      "GPU not supported\n");
>  }
>  
> +static void
> +*intel_compute_thread(void *data)
> +{
> +	struct thread_data *t = (struct thread_data *)data;
> +
> +	usleep(3 * NS_SLEEP);
> +
> +	igt_info("Compute kernel executing on engine class :%s instance :%d gt: GT-%d\n",
> +			xe_engine_class_string(t->eci->engine_class), t->eci->engine_instance,
> +			t->eci->gt_id);
> +
> +	pthread_mutex_lock(t->mutex);
> +	while (*t->go == 0)
> +		pthread_cond_wait(t->cond, t->mutex);
> +	pthread_mutex_unlock(t->mutex);
> +
> +	workload_sched = true;
> +	igt_assert_f(xe_run_intel_compute_kernel_on_engine(t->fd,
> +				t->eci,
> +				t->execenv,
> +				EXECENV_PREF_VRAM_IF_POSSIBLE),
> +			"Unable to run compute kernel successfully\n");
> +	workload_sched = false;
> +	return NULL;
> +}
> +
> +static volatile bool stop_top;
> +
> +static const char
> +*class_display_name(unsigned int class)
> +{
> +	switch (class) {
> +	case DRM_XE_ENGINE_CLASS_RENDER:
> +		return "Render/3D";
> +	case DRM_XE_ENGINE_CLASS_COPY:
> +		return "Blitter";
> +	case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
> +		return "Video";
> +	case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
> +		return "VideoEnhance";
> +	case DRM_XE_ENGINE_CLASS_COMPUTE:
> +		return "Compute";
> +	default:
> +		return "[unknown]";
> +	}
> +}
> +
> +static void
> +*xe_init_engines(const void *obj)
> +{
> +	struct igt_device_card *card = ((struct xe_gpu_info *)obj)->card;
> +	struct xe_pmu_device *engines;
> +	struct drm_xe_engine *ccs_engine;
> +	int ret = 0, engine_count = 0;
> +	struct drm_xe_engine_class_instance *hwe;
> +	int card_fd;
> +	uint32_t engine_class, engine_instance, gt_shift;
> +	uint64_t engine_active_config, engine_total_config;
> +
> +	if (!card || !strlen(card->card) || !strlen(card->render))
> +		return NULL;
> +
> +	if (strlen(card->card)) {
> +		card_fd = igt_open_card(card);
> +	} else if (strlen(card->render)) {
> +		card_fd = igt_open_render(card);
> +	} else {
> +		fprintf(stderr, "Failed to detect device!\n");
> +		return NULL;
> +	}
> +	xe_device_get(card_fd);
> +
> +	xe_for_each_engine(card_fd, hwe) {
> +		ccs_engine = xe_find_engine_by_class(card_fd, DRM_XE_ENGINE_CLASS_COMPUTE);
> +		if (ccs_engine)
> +			engine_count++;
> +	}
> +
> +	engines = calloc(1, sizeof(struct xe_pmu_device) +
> +			engine_count * sizeof(struct xe_engine));
> +	if (!engines)
> +		return NULL;
> +
> +	engines->num_engines = 0;
> +	engines->device = ((struct xe_gpu_info *)obj)->pmu_device;
> +	perf_event_format(((struct xe_gpu_info *)obj)->pmu_device, "gt", &gt_shift);
> +	perf_event_format(((struct xe_gpu_info *)obj)->pmu_device, "engine_class", &engine_class);
> +	perf_event_format(((struct xe_gpu_info *)obj)->pmu_device, "engine_instance", &engine_instance);
> +	ret = perf_event_config(((struct xe_gpu_info *)obj)->pmu_device,
> +			"engine-active-ticks",
> +			&engine_active_config);
> +	if (ret < 0)
> +		return NULL;
> +	ret = perf_event_config(((struct xe_gpu_info *)obj)->pmu_device,
> +			"engine-total-ticks",
> +			&engine_total_config);
> +	if (ret < 0)
> +		return NULL;
> +	xe_for_each_engine(card_fd, hwe) {
> +		if (hwe->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE) {
> +			uint64_t  param_config;
> +			struct xe_engine *engine;
> +
> +			engine = engine_ptr(engines, engines->num_engines);
> +			param_config = (uint64_t)hwe->gt_id << gt_shift | hwe->engine_class << engine_class
> +				| hwe->engine_instance << engine_instance;
> +			engine->drm_xe_engine = *hwe;
> +			engine->engine_active_ticks.config = engine_active_config | param_config;
> +			engine->engine_total_ticks.config = engine_total_config | param_config;
> +
> +			if (engine->engine_active_ticks.config == -1 ||
> +					engine->engine_total_ticks.config == -1) {
> +				ret = ENOENT;
> +				break;
> +			}
> +
> +			ret = asprintf(&engine->display_name, "%s/%u",
> +					class_display_name(engine->drm_xe_engine.engine_class),
> +					engine->drm_xe_engine.engine_instance);
> +
> +			if (ret <= 0) {
> +				ret = errno;
> +				break;
> +			}
> +
> +			engines->num_engines++;
> +		}
> +	}
> +
> +	if (!ret) {
> +		errno = ret;
> +		return NULL;
> +	}
> +
> +	((struct xe_gpu_info *)obj)->eng_obj = engines;
> +
> +	return engines;
> +}
> +
> +static int
> +_open_pmu(uint64_t type, unsigned int *cnt,
> +	  struct xe_pmu_counter *pmu, int *fd)
> +{
> +	int fd__ = igt_perf_open_group(type, pmu->config, *fd);
> +
> +	if (fd__ >= 0) {
> +		if (*fd == -1)
> +			*fd = fd__;
> +		pmu->present = true;
> +		pmu->idx = (*cnt)++;
> +		pmu->fd = fd__;
> +	}
> +
> +	return fd__;
> +}
> +
> +static int xe_gpu_pmu_init(const void *obj)
> +{
> +	struct xe_pmu_device *engines = ((struct xe_gpu_info *)obj)->eng_obj;
> +	unsigned int i;
> +	int fd;
> +	struct xe_engine *engine;
> +	uint64_t type = igt_perf_type_id(engines->device);
> +
> +	engines->fd = -1;
> +	engines->num_counters = 0;
> +
> +	for (i = 0; i < engines->num_engines; i++) {
> +		engine = engine_ptr(engines, i);
> +		fd = _open_pmu(type, &engines->num_counters, &engine->engine_active_ticks,
> +				&engines->fd);
> +		if (fd < 0)
> +			return -1;
> +		fd = _open_pmu(type, &engines->num_counters, &engine->engine_total_ticks,
> +				&engines->fd);
> +		if (fd < 0)
> +			return -1;
> +	}
> +	return 0;
> +}
> +
> +static void
> +eu_util_free(struct xe_gpu_info *gpu_ptr)
> +{
> +	struct xe_engine *eng;
> +	struct xe_pmu_counter pmu;
> +
> +	igt_info("EU cleanup process\n");
> +
> +	if (gpu_ptr->card)
> +		free(gpu_ptr->card);
> +
> +	if (gpu_ptr->eng_obj) {
> +		for (int j = 0; j < ((struct xe_pmu_device *)gpu_ptr->eng_obj)->num_engines ; j++) {
> +			eng = engine_ptr((struct xe_pmu_device *)(gpu_ptr)->eng_obj, j);
> +			if (eng->display_name)
> +				free(eng->display_name);
> +
> +			pmu = eng->engine_active_ticks;
> +			if (pmu.present)
> +				close(pmu.fd);
> +
> +			pmu = eng->engine_total_ticks;
> +			if (pmu.present)
> +				close(pmu.fd);
> +		}
> +		free(gpu_ptr->eng_obj);
> +	}
> +	if (gpu_ptr->pmu_device)
> +		free(gpu_ptr->pmu_device);
> +}
> +
> +static char
> +*pmu_name(struct igt_device_card *card)
> +{
> +	int card_fd;
> +	char device[30];
> +	char *path;
> +
> +	if (strlen(card->card))
> +		card_fd = igt_open_card(card);
> +	else if (strlen(card->render))
> +		card_fd = igt_open_render(card);
> +
> +	if (card_fd == -1)
> +		return NULL;
> +
> +	xe_perf_device(card_fd, device, sizeof(device));
> +	path = strdup(device);
> +	close(card_fd);
> +	return path;
> +}
> +
> +static struct xe_gpu_info *
> +xe_device_match(const char *filter)
> +{
> +	struct igt_device_card card;
> +	struct xe_gpu_info *gpu_ptr =  NULL;
> +
> +	if (!igt_device_card_match(filter, &card)) {
> +		igt_info("No device found for the filter\n\n");
> +		return NULL;
> +	}
> +
> +	gpu_ptr = (struct xe_gpu_info *)malloc(sizeof(struct xe_gpu_info));
> +	igt_assert(gpu_ptr);
> +
> +	gpu_ptr->pmu_device = pmu_name(&card);
> +	if (!gpu_ptr->pmu_device) {
> +		fprintf(stderr, "%s : pmu_device path returned NULL", card.pci_slot_name);
> +		exit(EXIT_FAILURE);
> +	}
> +	gpu_ptr->card = &card;
> +	return gpu_ptr;
> +}
> +
> +static void
> +update_sample(struct xe_pmu_counter *counter, uint64_t *val)
> +{
> +	if (counter->present) {
> +		counter->val.prev = counter->val.cur;
> +		counter->val.cur = val[counter->idx];
> +	}
> +}
> +
> +static void xe_pmu_device_sample(const void *obj)
> +{
> +	struct xe_pmu_device *engines = ((struct xe_gpu_info *)obj)->eng_obj;
> +	const int num_val = engines->num_counters;
> +	uint64_t val[2 + num_val];
> +	uint64_t buf[2 + num_val];
> +	unsigned int i;
> +	ssize_t len;
> +
> +	memset(buf, 0, sizeof(buf));
> +	len = read(engines->fd, buf, sizeof(buf));
> +	assert(len == sizeof(buf));
> +
> +	for (i = 0; i < num_val; i++)
> +		val[i] = buf[2 + i];
> +
> +	for (i = 0; i < engines->num_engines; i++) {
> +		struct xe_engine *engine = engine_ptr(engines, i);
> +
> +		update_sample(&engine->engine_active_ticks, val);
> +		update_sample(&engine->engine_total_ticks, val);
> +	}
> +}
> +
> +static double
> +pmu_active_percentage(struct xe_engine *engine)
> +{
> +	double pmu_active_ticks = engine->engine_active_ticks.val.cur -
> +		engine->engine_active_ticks.val.prev;
> +	double pmu_total_ticks = engine->engine_total_ticks.val.cur -
> +		engine->engine_total_ticks.val.prev;
> +	double percentage;
> +
> +	percentage = (pmu_active_ticks * 100) / pmu_total_ticks;
> +	return percentage;
> +}
> +
> +static void xe_print_perc(const void *obj)
> +{
> +	struct xe_pmu_device *pmu_device = ((struct xe_gpu_info *)obj)->eng_obj;
> +
> +	for (unsigned int i = 0; i < pmu_device->num_engines; i++) {
> +		double percentage;
> +		struct xe_engine *engine = engine_ptr(pmu_device, i);
> +		igt_assert(engine);
> +
> +		percentage = pmu_active_percentage(engine);
> +
> +		if (engine->drm_xe_engine.engine_class == DRM_XE_ENGINE_CLASS_COMPUTE && !workload_sched) {
> +			igt_info("Engine_instance :%d EU busyness :%5.1f\n", engine->drm_xe_engine.engine_instance, percentage);
> +			if (!percentage)
> +				igt_info("No workload scheduled, BU busyness :%5.1f expected\n", percentage);
> +			else
> +				igt_info("Workload scheduled, BU busyness :%5.1f expected\n", percentage);
> +		} else if (engine->drm_xe_engine.engine_class == DRM_XE_ENGINE_CLASS_COMPUTE && workload_sched) {
> +			igt_info("Engine_instance :%d EU busyness :%5.1f\n", engine->drm_xe_engine.engine_instance, percentage);
> +			if (!percentage)
> +				igt_info("No workload scheduled, BU busyness :%5.1f expected\n", percentage);
> +			else
> +				igt_info("Workload scheduled, BU busyness :%5.1f expected\n", percentage);
> +		}
> +	}
> +}
> +
> +static void *show_eu_util(void *data)
> +{
> +	struct igt_drm_clients *clients = NULL;
> +	struct pci_device *pdev = NULL;
> +	struct xe_gpu_info *gpu_ptr = NULL;
> +	char filter[50] = "";
> +	int ret, dev_fd;
> +	long n;
> +
> +	dev_fd = drm_open_driver(DRIVER_XE);
> +
> +	pdev = igt_device_get_pci_device(dev_fd);
> +	igt_require(pdev);
> +
> +	strcpy(filter, "pci:vendor=Intel,device=discrete,card=0");
> +	gpu_ptr = xe_device_match(filter);
> +	if (!gpu_ptr) {
> +		printf("No device found.\n");
> +		eu_util_free(gpu_ptr);
> +		exit(1);
> +	}
> +
> +	drm_close_driver(dev_fd);
> +
> +	if (!xe_init_engines(gpu_ptr)) {
> +		fprintf(stderr,
> +				"Failed to initialize engines! (%s)\n",
> +				strerror(errno));
> +		eu_util_free(gpu_ptr);
> +		return NULL;
> +	}
> +
> +	ret = xe_gpu_pmu_init(gpu_ptr);
> +	if (ret) {
> +		fprintf(stderr,
> +				"Failed to initialize PMU! (%s)\n",
> +				strerror(errno));
> +		if (errno == EACCES && geteuid())
> +			fprintf(stderr,
> +					"\n"
> +					"Access error\n"
> +					"More info athttps://www.kernel.org/doc/html/latest/admin-guide/perf-security.html\n");
> +		igt_devices_free();
> +		eu_util_free(gpu_ptr);
> +		return NULL;
> +	}
> +
> +	xe_pmu_device_sample(gpu_ptr);
> +
> +	clients = igt_drm_clients_init(NULL);
> +	if (!clients)
> +		exit(1);
> +	igt_drm_clients_scan(clients, NULL, NULL, 0, NULL, 0);
> +	while ((n != 0) && !stop_top) {
> +		igt_drm_clients_scan(clients, NULL, NULL, 0, NULL, 0);
> +		xe_pmu_device_sample(gpu_ptr);
> +		xe_print_perc(gpu_ptr);
> +		usleep(2 * NS_SLEEP);
> +	}
> +	igt_drm_clients_free(clients);
> +	eu_util_free(gpu_ptr);
> +
> +	return NULL;
> +}
> +
> +static void
> +thread_init_eu_utils(void)
> +{
> +	pthread_t eu_utils;
> +	int fd;
> +	uint16_t dev_id;
> +
> +	fd = drm_open_driver(DRIVER_XE);
> +	dev_id = intel_get_drm_devid(fd);
> +
> +	/* Creating thread to display EU utilization in BMG */
> +	if (IS_BATTLEMAGE(dev_id))
> +		pthread_create(&eu_utils, NULL, show_eu_util, NULL);
> +}
> +
> +/**
> + * SUBTEST: eu-busy-10-sec
> + * Functionality: OpenCL kernel
> + * Description:
> + *      Run an openCL long rinning Kernel that returns output[i] = input[i] * input[i],
> + */
> +static void
> +test_eu_busy(int fd, int num_gt, u32 duration_sec)
> +{
> +	struct user_execenv execenv = { 0 };
> +	struct thread_data *threads_data;
> +	struct drm_xe_engine_class_instance *hwe;
> +	const struct intel_compute_kernels *kernels;
> +	pthread_mutex_t mutex;
> +	pthread_cond_t cond;
> +	u32 gt, n_threads = 0, iterations = 0, n_instances = 0, i;
> +	bool go = false;
> +	int ccs_mode, gt_fd;
> +	u32 num_slices, ip_ver;
> +
> +	fd = drm_open_driver(DRIVER_XE);
> +	ip_ver = intel_graphics_ver(intel_get_drm_devid(fd));
> +	kernels = intel_compute_square_kernels;
> +	drm_close_driver(fd);
> +
> +	for (gt = 0; gt < num_gt; gt++) {
> +		if (!get_num_cslices(gt, &num_slices))
> +			continue;
> +
> +		gt_fd = gt_sysfs_open(gt);
> +		igt_assert(igt_sysfs_printf(gt_fd, "ccs_mode", "%u", 2) > 0);
> +		igt_assert(igt_sysfs_scanf(gt_fd, "ccs_mode", "%u", &ccs_mode) > 0);
> +		close(gt_fd);
> +	}
> +
> +	igt_skip_on_f(ccs_mode <= 1, "Skipping test as ccs_mode <=1 not matching criteria :%d\n",
> +		      ccs_mode);
> +
> +	fd = drm_open_driver(DRIVER_XE);
> +	thread_init_eu_utils();
> +
> +	while (kernels->kernel) {
> +		if (ip_ver == kernels->ip_ver)
> +			break;
> +		kernels++;
> +	}
> +
> +	/*If loop_kernel_duration not set user should use different
> +	 *kernel and size
> +	 *use with loop kernel and loop duration it assumes we stop
> +	 *it via memory write
> +	 */
> +
> +	execenv.loop_kernel_duration = duration_sec;
> +	execenv.kernel = kernels->loop_kernel;
> +	execenv.kernel_size = kernels->loop_kernel_size;
> +	for (gt = 0; gt < num_gt; gt++) {
> +		xe_for_each_engine(fd, hwe) {
> +			igt_assert(hwe);
> +			if (hwe->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE)
> +				++n_instances;
> +		}
> +	}
> +
> +	threads_data = calloc(n_instances, sizeof(*threads_data));
> +	igt_assert(threads_data);
> +
> +	pthread_mutex_init(&mutex, 0);
> +	pthread_cond_init(&cond, 0);
> +
> +	for (gt = 0; gt < num_gt; gt++) {
> +		xe_for_each_engine(fd, hwe) {
> +			if (hwe->gt_id != gt ||
> +					hwe->engine_class != DRM_XE_ENGINE_CLASS_COMPUTE)
> +				continue;
> +
> +			threads_data[i].mutex = &mutex;
> +			threads_data[i].cond = &cond;
> +			threads_data[i].fd = fd;
> +			threads_data[i].eci = hwe;
> +			threads_data[i].go = &go;
> +			threads_data[i].execenv = &execenv;
> +			++n_threads;
> +			pthread_create(&threads_data[i].thread, 0, intel_compute_thread,
> +					&threads_data[i]);
> +			++i;
> +			++iterations;
> +			usleep(2 * NS_SLEEP);
> +		}
> +
> +		pthread_mutex_lock(&mutex);
> +		go = true;
> +		pthread_cond_broadcast(&cond);
> +		pthread_mutex_unlock(&mutex);
> +
> +		for (int val = 0; val < i; ++val) {
> +			pthread_join(threads_data[val].thread, NULL);
> +		}
> +
> +		i = 0;
> +		n_threads = 0;
> +		iterations = 0;
> +		stop_top = true;
> +	}
> +	free(threads_data);
> +	drm_close_driver(fd);
> +}
> +
>  igt_main
>  {
> -	int xe;
> +	int xe, num_gt;
>  
>  	igt_fixture {
>  		xe = drm_open_driver(DRIVER_XE);
> +		num_gt = xe_number_gt(xe);
>  	}
>  
>  	igt_subtest("compute-square")
> @@ -223,4 +781,8 @@ igt_main
>  
>  	igt_subtest("ccs-mode-compute-kernel")
>  		test_compute_kernel_with_ccs_mode();
> +
> +	/* test to check available EU utilisation for multi_ccs */
> +	igt_subtest("eu-busy-10-sec")
> +		test_eu_busy(xe, num_gt, 10 * LOOP_DURATION);
>  }
> diff --git a/tests/meson.build b/tests/meson.build
> index 9b87a0d24..7945f68f8 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -405,6 +405,7 @@ extra_dependencies = {
>  	'sw_sync': [ libatomic ],
>  	'xe_fault_injection': [ lib_igt_xe_oa ],
>  	'xe_oa': [ lib_igt_xe_oa ],
> +	'xe_compute': [ igt_deps,lib_igt_perf,lib_igt_drm_clients,lib_igt_drm_fdinfo,lib_igt_profiling,math ],
>  }
>  
>  test_executables = []
> -- 
> 2.43.0
> 


More information about the igt-dev mailing list