xref: /linux/tools/testing/selftests/resctrl/resctrl_val.c (revision 8459ea00c0abad92cbe4a9b836c4c979823dbb59)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Memory bandwidth monitoring and allocation library
4  *
5  * Copyright (C) 2018 Intel Corporation
6  *
7  * Authors:
8  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9  *    Fenghua Yu <fenghua.yu@intel.com>
10  */
11 #include "resctrl.h"
12 
13 #define UNCORE_IMC		"uncore_imc"
14 #define READ_FILE_NAME		"cas_count_read"
15 #define DYN_PMU_PATH		"/sys/bus/event_source/devices"
16 #define SCALE			0.00006103515625
17 #define MAX_TOKENS		5
18 
19 #define CON_MBM_LOCAL_BYTES_PATH		\
20 	"%s/%s/mon_data/mon_L3_%02d/mbm_local_bytes"
21 
22 struct membw_read_format {
23 	__u64 value;         /* The value of the event */
24 	__u64 time_enabled;  /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
25 	__u64 time_running;  /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
26 	__u64 id;            /* if PERF_FORMAT_ID */
27 };
28 
29 struct imc_counter_config {
30 	struct list_head entry;
31 	__u32 type;
32 	__u64 event;
33 	__u64 umask;
34 	struct perf_event_attr pe;
35 	int fd;
36 };
37 
38 static char mbm_total_path[1024];
39 LIST_HEAD(imc_counters_list);
40 static const struct resctrl_test *current_test;
41 
42 static void read_mem_bw_initialize_perf_event_attr(struct imc_counter_config *imc_counter)
43 {
44 	memset(&imc_counter->pe, 0, sizeof(struct perf_event_attr));
45 	imc_counter->pe.type = imc_counter->type;
46 	imc_counter->pe.size = sizeof(struct perf_event_attr);
47 	imc_counter->pe.disabled = 1;
48 	imc_counter->pe.inherit = 1;
49 	imc_counter->pe.exclude_guest = 0;
50 	imc_counter->pe.config = imc_counter->umask << 8 | imc_counter->event;
51 	imc_counter->pe.sample_type = PERF_SAMPLE_IDENTIFIER;
52 	imc_counter->pe.read_format =
53 		PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
54 }
55 
56 static void read_mem_bw_ioctl_perf_event_ioc_reset_enable(struct imc_counter_config *imc_counter)
57 {
58 	ioctl(imc_counter->fd, PERF_EVENT_IOC_RESET, 0);
59 	ioctl(imc_counter->fd, PERF_EVENT_IOC_ENABLE, 0);
60 }
61 
62 static void read_mem_bw_ioctl_perf_event_ioc_disable(struct imc_counter_config *imc_counter)
63 {
64 	ioctl(imc_counter->fd, PERF_EVENT_IOC_DISABLE, 0);
65 }
66 
67 /*
68  * get_read_event_and_umask:	Parse config into event and umask
69  * @cas_count_cfg:	Config
70  * @imc_counter:	iMC counter config
71  */
72 static void get_read_event_and_umask(char *cas_count_cfg, struct imc_counter_config *imc_counter)
73 {
74 	char *token[MAX_TOKENS];
75 	int i = 0;
76 
77 	token[0] = strtok(cas_count_cfg, "=,");
78 
79 	for (i = 1; i < MAX_TOKENS; i++)
80 		token[i] = strtok(NULL, "=,");
81 
82 	for (i = 0; i < MAX_TOKENS - 1; i++) {
83 		if (!token[i])
84 			break;
85 		if (strcmp(token[i], "event") == 0)
86 			imc_counter->event = strtol(token[i + 1], NULL, 16);
87 		if (strcmp(token[i], "umask") == 0)
88 			imc_counter->umask = strtol(token[i + 1], NULL, 16);
89 	}
90 }
91 
92 static int open_perf_read_event(int cpu_no, struct imc_counter_config *imc_counter)
93 {
94 	imc_counter->fd = perf_event_open(&imc_counter->pe, -1, cpu_no, -1,
95 					  PERF_FLAG_FD_CLOEXEC);
96 
97 	if (imc_counter->fd == -1) {
98 		fprintf(stderr, "Error opening leader %llx\n",
99 			imc_counter->pe.config);
100 
101 		return -1;
102 	}
103 
104 	return 0;
105 }
106 
107 static int parse_imc_read_bw_events(char *imc_dir, unsigned int type)
108 {
109 	char imc_events_dir[PATH_MAX], imc_counter_cfg[PATH_MAX];
110 	struct imc_counter_config *imc_counter;
111 	bool found_event = false;
112 	char cas_count_cfg[1024];
113 	struct dirent *ep;
114 	int path_len;
115 	int ret = -1;
116 	int num_cfg;
117 	FILE *fp;
118 	DIR *dp;
119 
120 	path_len = snprintf(imc_events_dir, sizeof(imc_events_dir), "%sevents",
121 			    imc_dir);
122 	if (path_len >= sizeof(imc_events_dir)) {
123 		ksft_print_msg("Unable to create path to %sevents\n", imc_dir);
124 		goto out;
125 	}
126 
127 	dp = opendir(imc_events_dir);
128 	if (!dp) {
129 		ksft_perror("Unable to open PMU events directory");
130 		goto out;
131 	}
132 
133 	while ((ep = readdir(dp))) {
134 		/*
135 		 * Parse all event files with READ_FILE_NAME prefix that
136 		 * contain the event number and umask. Skip files containing
137 		 * "." that contain unused properties of event.
138 		 */
139 		if (!strstr(ep->d_name, READ_FILE_NAME) ||
140 		    strchr(ep->d_name, '.'))
141 			continue;
142 
143 		path_len = snprintf(imc_counter_cfg, sizeof(imc_counter_cfg),
144 				    "%s/%s", imc_events_dir, ep->d_name);
145 		if (path_len >= sizeof(imc_counter_cfg)) {
146 			ksft_print_msg("Unable to create path to %s/%s\n",
147 				       imc_events_dir, ep->d_name);
148 			goto out_close;
149 		}
150 		fp = fopen(imc_counter_cfg, "r");
151 		if (!fp) {
152 			ksft_perror("Failed to open iMC config file");
153 			goto out_close;
154 		}
155 		num_cfg = fscanf(fp, "%1023s", cas_count_cfg);
156 		fclose(fp);
157 		if (num_cfg <= 0) {
158 			ksft_perror("Could not get iMC cas count read");
159 			goto out_close;
160 		}
161 		imc_counter = calloc(1, sizeof(*imc_counter));
162 		if (!imc_counter) {
163 			ksft_perror("Unable to allocate memory for iMC counters");
164 			goto out_close;
165 		}
166 
167 		imc_counter->type = type;
168 		get_read_event_and_umask(cas_count_cfg, imc_counter);
169 		list_add(&imc_counter->entry, &imc_counters_list);
170 		found_event = true;
171 	}
172 	if (!found_event) {
173 		ksft_print_msg("Unable to find events in %s\n", imc_events_dir);
174 		goto out_close;
175 	}
176 	ret = 0;
177 out_close:
178 	closedir(dp);
179 out:
180 	if (ret)
181 		cleanup_read_mem_bw_imc();
182 
183 	return ret;
184 }
185 
186 /* Get type and config of an iMC counter's read event. */
187 static int read_from_imc_dir(char *imc_dir)
188 {
189 	char imc_counter_type[PATH_MAX];
190 	unsigned int type;
191 	int path_len;
192 	FILE *fp;
193 	int ret;
194 
195 	/* Get type of iMC counter */
196 	path_len = snprintf(imc_counter_type, sizeof(imc_counter_type),
197 			    "%s%s", imc_dir, "type");
198 	if (path_len >= sizeof(imc_counter_type)) {
199 		ksft_print_msg("Unable to create path to %s%s\n",
200 			       imc_dir, "type");
201 		return -1;
202 	}
203 	fp = fopen(imc_counter_type, "r");
204 	if (!fp) {
205 		ksft_perror("Failed to open iMC counter type file");
206 
207 		return -1;
208 	}
209 	ret = fscanf(fp, "%u", &type);
210 	fclose(fp);
211 	if (ret <= 0) {
212 		ksft_perror("Could not get iMC type");
213 		return -1;
214 	}
215 	ret = parse_imc_read_bw_events(imc_dir, type);
216 	if (ret) {
217 		ksft_print_msg("Unable to parse bandwidth event and umask\n");
218 		return ret;
219 	}
220 
221 	return 0;
222 }
223 
224 /*
225  * Discover the properties of the available iMC (Integrated Memory Controller)
226  * counters in support of needed performance measurement via perf. For each iMC
227  * counter get it's type and config. Also obtain each counter's event and umask
228  * for the memory read events that will be measured.
229  *
230  * Enumerate all these details into a linked list of structures.
231  *
232  * Return: >= 0 on success. < 0 on failure.
233  */
234 static int enumerate_imcs(void)
235 {
236 	char imc_dir[512], *temp;
237 	struct dirent *ep;
238 	int ret;
239 	DIR *dp;
240 
241 	dp = opendir(DYN_PMU_PATH);
242 	if (dp) {
243 		while ((ep = readdir(dp))) {
244 			temp = strstr(ep->d_name, UNCORE_IMC);
245 			if (!temp)
246 				continue;
247 
248 			/*
249 			 * imc counters are named as "uncore_imc_<n>", hence
250 			 * increment the pointer to point to <n>. Note that
251 			 * sizeof(UNCORE_IMC) would count for null character as
252 			 * well and hence the last underscore character in
253 			 * uncore_imc'_' need not be counted.
254 			 */
255 			temp = temp + sizeof(UNCORE_IMC);
256 
257 			/*
258 			 * Some directories under "DYN_PMU_PATH" could have
259 			 * names like "uncore_imc_free_running", hence, check if
260 			 * first character is a numerical digit or not.
261 			 */
262 			if (temp[0] >= '0' && temp[0] <= '9') {
263 				sprintf(imc_dir, "%s/%s/", DYN_PMU_PATH,
264 					ep->d_name);
265 				ret = read_from_imc_dir(imc_dir);
266 				if (ret) {
267 					closedir(dp);
268 
269 					return ret;
270 				}
271 			}
272 		}
273 		closedir(dp);
274 		if (list_empty(&imc_counters_list)) {
275 			ksft_print_msg("Unable to find iMC counters\n");
276 
277 			return -1;
278 		}
279 	} else {
280 		ksft_perror("Unable to open PMU directory");
281 
282 		return -1;
283 	}
284 
285 	return 0;
286 }
287 
288 int initialize_read_mem_bw_imc(void)
289 {
290 	struct imc_counter_config *imc_counter;
291 	int ret;
292 
293 	ret = enumerate_imcs();
294 	if (ret < 0)
295 		return ret;
296 
297 	/* Initialize perf_event_attr structures for all iMC's */
298 	list_for_each_entry(imc_counter, &imc_counters_list, entry)
299 		read_mem_bw_initialize_perf_event_attr(imc_counter);
300 
301 	return 0;
302 }
303 
304 void cleanup_read_mem_bw_imc(void)
305 {
306 	struct imc_counter_config *imc_counter, *tmp;
307 
308 	list_for_each_entry_safe(imc_counter, tmp, &imc_counters_list, entry) {
309 		list_del(&imc_counter->entry);
310 		free(imc_counter);
311 	}
312 }
313 
314 static void perf_close_imc_read_mem_bw(void)
315 {
316 	struct imc_counter_config *imc_counter;
317 
318 	list_for_each_entry(imc_counter, &imc_counters_list, entry) {
319 		if (imc_counter->fd != -1)
320 			close(imc_counter->fd);
321 	}
322 }
323 
324 /*
325  * perf_open_imc_read_mem_bw - Open perf fds for IMCs
326  * @cpu_no: CPU number that the benchmark PID is bound to
327  *
328  * Return: = 0 on success. < 0 on failure.
329  */
330 static int perf_open_imc_read_mem_bw(int cpu_no)
331 {
332 	struct imc_counter_config *imc_counter;
333 	int ret;
334 
335 	list_for_each_entry(imc_counter, &imc_counters_list, entry)
336 		imc_counter->fd = -1;
337 
338 	list_for_each_entry(imc_counter, &imc_counters_list, entry) {
339 		ret = open_perf_read_event(cpu_no, imc_counter);
340 		if (ret)
341 			goto close_fds;
342 	}
343 
344 	return 0;
345 
346 close_fds:
347 	perf_close_imc_read_mem_bw();
348 	return -1;
349 }
350 
351 /*
352  * do_imc_read_mem_bw_test - Perform memory bandwidth test
353  *
354  * Runs memory bandwidth test over one second period. Also, handles starting
355  * and stopping of the IMC perf counters around the test.
356  */
357 static void do_imc_read_mem_bw_test(void)
358 {
359 	struct imc_counter_config *imc_counter;
360 
361 	list_for_each_entry(imc_counter, &imc_counters_list, entry)
362 		read_mem_bw_ioctl_perf_event_ioc_reset_enable(imc_counter);
363 
364 	sleep(1);
365 
366 	/* Stop counters after a second to get results. */
367 	list_for_each_entry(imc_counter, &imc_counters_list, entry)
368 		read_mem_bw_ioctl_perf_event_ioc_disable(imc_counter);
369 }
370 
371 /*
372  * get_read_mem_bw_imc - Memory read bandwidth as reported by iMC counters
373  *
374  * Memory read bandwidth utilized by a process on a socket can be calculated
375  * using iMC counters' read events. Perf events are used to read these
376  * counters.
377  *
378  * Return: = 0 on success. < 0 on failure.
379  */
380 static int get_read_mem_bw_imc(float *bw_imc)
381 {
382 	float reads = 0, of_mul_read = 1;
383 	struct imc_counter_config *r;
384 
385 	/*
386 	 * Log read event values from all iMC counters into
387 	 * struct imc_counter_config.
388 	 * Take overflow into consideration before calculating total bandwidth.
389 	 */
390 	list_for_each_entry(r, &imc_counters_list, entry) {
391 		struct membw_read_format measurement;
392 
393 		if (read(r->fd, &measurement, sizeof(measurement)) == -1) {
394 			ksft_perror("Couldn't get read bandwidth through iMC");
395 			return -1;
396 		}
397 
398 		__u64 r_time_enabled = measurement.time_enabled;
399 		__u64 r_time_running = measurement.time_running;
400 
401 		if (r_time_enabled != r_time_running)
402 			of_mul_read = (float)r_time_enabled /
403 					(float)r_time_running;
404 
405 		reads += measurement.value * of_mul_read * SCALE;
406 	}
407 
408 	*bw_imc = reads;
409 	return 0;
410 }
411 
412 /*
413  * initialize_mem_bw_resctrl:	Appropriately populate "mbm_total_path"
414  * @param:	Parameters passed to resctrl_val()
415  * @domain_id:	Domain ID (cache ID; for MB, L3 cache ID)
416  */
417 void initialize_mem_bw_resctrl(const struct resctrl_val_param *param,
418 			       int domain_id)
419 {
420 	sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH,
421 		param->ctrlgrp, domain_id);
422 }
423 
424 /*
425  * Open file to read MBM local bytes from resctrl FS
426  */
427 static FILE *open_mem_bw_resctrl(const char *mbm_bw_file)
428 {
429 	FILE *fp;
430 
431 	fp = fopen(mbm_bw_file, "r");
432 	if (!fp)
433 		ksft_perror("Failed to open total memory bandwidth file");
434 
435 	return fp;
436 }
437 
438 /*
439  * Get MBM Local bytes as reported by resctrl FS
440  */
441 static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total)
442 {
443 	if (fscanf(fp, "%lu\n", mbm_total) <= 0) {
444 		ksft_perror("Could not get MBM local bytes");
445 		return -1;
446 	}
447 	return 0;
448 }
449 
450 static pid_t bm_pid;
451 
452 void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
453 {
454 	/* Only kill child after bm_pid is set after fork() */
455 	if (bm_pid)
456 		kill(bm_pid, SIGKILL);
457 	umount_resctrlfs();
458 	if (current_test && current_test->cleanup)
459 		current_test->cleanup();
460 	ksft_print_msg("Ending\n\n");
461 
462 	exit(EXIT_SUCCESS);
463 }
464 
465 /*
466  * Register CTRL-C handler for parent, as it has to kill
467  * child process before exiting.
468  */
469 int signal_handler_register(const struct resctrl_test *test)
470 {
471 	struct sigaction sigact = {};
472 	int ret = 0;
473 
474 	bm_pid = 0;
475 
476 	current_test = test;
477 	sigact.sa_sigaction = ctrlc_handler;
478 	sigemptyset(&sigact.sa_mask);
479 	sigact.sa_flags = SA_SIGINFO;
480 	if (sigaction(SIGINT, &sigact, NULL) ||
481 	    sigaction(SIGTERM, &sigact, NULL) ||
482 	    sigaction(SIGHUP, &sigact, NULL)) {
483 		ksft_perror("sigaction");
484 		ret = -1;
485 	}
486 	return ret;
487 }
488 
489 /*
490  * Reset signal handler to SIG_DFL.
491  * Non-Value return because the caller should keep
492  * the error code of other path even if sigaction fails.
493  */
494 void signal_handler_unregister(void)
495 {
496 	struct sigaction sigact = {};
497 
498 	current_test = NULL;
499 	sigact.sa_handler = SIG_DFL;
500 	sigemptyset(&sigact.sa_mask);
501 	if (sigaction(SIGINT, &sigact, NULL) ||
502 	    sigaction(SIGTERM, &sigact, NULL) ||
503 	    sigaction(SIGHUP, &sigact, NULL)) {
504 		ksft_perror("sigaction");
505 	}
506 }
507 
508 /*
509  * print_results_bw:	the memory bandwidth results are stored in a file
510  * @filename:		file that stores the results
511  * @bm_pid:		child pid that runs benchmark
512  * @bw_imc:		perf imc counter value
513  * @bw_resc:		memory bandwidth value
514  *
515  * Return:		0 on success, < 0 on error.
516  */
517 static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc,
518 			    unsigned long bw_resc)
519 {
520 	unsigned long diff = fabs(bw_imc - bw_resc);
521 	FILE *fp;
522 
523 	if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) {
524 		printf("Pid: %d \t Mem_BW_iMC: %f \t ", (int)bm_pid, bw_imc);
525 		printf("Mem_BW_resc: %lu \t Difference: %lu\n", bw_resc, diff);
526 	} else {
527 		fp = fopen(filename, "a");
528 		if (!fp) {
529 			ksft_perror("Cannot open results file");
530 
531 			return -1;
532 		}
533 		if (fprintf(fp, "Pid: %d \t Mem_BW_iMC: %f \t Mem_BW_resc: %lu \t Difference: %lu\n",
534 			    (int)bm_pid, bw_imc, bw_resc, diff) <= 0) {
535 			ksft_print_msg("Could not log results\n");
536 			fclose(fp);
537 
538 			return -1;
539 		}
540 		fclose(fp);
541 	}
542 
543 	return 0;
544 }
545 
546 /*
547  * measure_read_mem_bw - Measures read memory bandwidth numbers while benchmark runs
548  * @uparams:		User supplied parameters
549  * @param:		Parameters passed to resctrl_val()
550  * @bm_pid:		PID that runs the benchmark
551  *
552  * Measure memory bandwidth from resctrl and from another source which is
553  * perf imc value or could be something else if perf imc event is not
554  * available. Compare the two values to validate resctrl value. It takes
555  * 1 sec to measure the data.
556  * resctrl does not distinguish between read and write operations so
557  * its data includes all memory operations.
558  */
559 int measure_read_mem_bw(const struct user_params *uparams,
560 			struct resctrl_val_param *param, pid_t bm_pid)
561 {
562 	unsigned long bw_resc, bw_resc_start, bw_resc_end;
563 	FILE *mem_bw_fp;
564 	float bw_imc;
565 	int ret;
566 
567 	mem_bw_fp = open_mem_bw_resctrl(mbm_total_path);
568 	if (!mem_bw_fp)
569 		return -1;
570 
571 	ret = perf_open_imc_read_mem_bw(uparams->cpu);
572 	if (ret < 0)
573 		goto close_fp;
574 
575 	ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_start);
576 	if (ret < 0)
577 		goto close_imc;
578 
579 	rewind(mem_bw_fp);
580 
581 	do_imc_read_mem_bw_test();
582 
583 	ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_end);
584 	if (ret < 0)
585 		goto close_imc;
586 
587 	ret = get_read_mem_bw_imc(&bw_imc);
588 	if (ret < 0)
589 		goto close_imc;
590 
591 	perf_close_imc_read_mem_bw();
592 	fclose(mem_bw_fp);
593 
594 	bw_resc = (bw_resc_end - bw_resc_start) / MB;
595 
596 	return print_results_bw(param->filename, bm_pid, bw_imc, bw_resc);
597 
598 close_imc:
599 	perf_close_imc_read_mem_bw();
600 close_fp:
601 	fclose(mem_bw_fp);
602 	return ret;
603 }
604 
605 /*
606  * resctrl_val:	execute benchmark and measure memory bandwidth on
607  *			the benchmark
608  * @test:		test information structure
609  * @uparams:		user supplied parameters
610  * @param:		parameters passed to resctrl_val()
611  *
612  * Return:		0 when the test was run, < 0 on error.
613  */
614 int resctrl_val(const struct resctrl_test *test,
615 		const struct user_params *uparams,
616 		struct resctrl_val_param *param)
617 {
618 	unsigned char *buf = NULL;
619 	cpu_set_t old_affinity;
620 	int domain_id;
621 	int ret = 0;
622 	pid_t ppid;
623 
624 	if (strcmp(param->filename, "") == 0)
625 		sprintf(param->filename, "stdio");
626 
627 	ret = get_domain_id(test->resource, uparams->cpu, &domain_id);
628 	if (ret < 0) {
629 		ksft_print_msg("Could not get domain ID\n");
630 		return ret;
631 	}
632 
633 	ppid = getpid();
634 
635 	/* Taskset test to specified CPU. */
636 	ret = taskset_benchmark(ppid, uparams->cpu, &old_affinity);
637 	if (ret)
638 		return ret;
639 
640 	/* Write test to specified control & monitoring group in resctrl FS. */
641 	ret = write_bm_pid_to_resctrl(ppid, param->ctrlgrp, param->mongrp);
642 	if (ret)
643 		goto reset_affinity;
644 
645 	if (param->init) {
646 		ret = param->init(test, uparams, param, domain_id);
647 		if (ret)
648 			goto reset_affinity;
649 	}
650 
651 	/*
652 	 * If not running user provided benchmark, run the default
653 	 * "fill_buf". First phase of "fill_buf" is to prepare the
654 	 * buffer that the benchmark will operate on. No measurements
655 	 * are needed during this phase and prepared memory will be
656 	 * passed to next part of benchmark via copy-on-write thus
657 	 * no impact on the benchmark that relies on reading from
658 	 * memory only.
659 	 */
660 	if (param->fill_buf) {
661 		buf = alloc_buffer(param->fill_buf->buf_size,
662 				   param->fill_buf->memflush);
663 		if (!buf) {
664 			ret = -ENOMEM;
665 			goto reset_affinity;
666 		}
667 	}
668 
669 	fflush(stdout);
670 	bm_pid = fork();
671 	if (bm_pid == -1) {
672 		ret = -errno;
673 		ksft_perror("Unable to fork");
674 		goto free_buf;
675 	}
676 
677 	/*
678 	 * What needs to be measured runs in separate process until
679 	 * terminated.
680 	 */
681 	if (bm_pid == 0) {
682 		if (param->fill_buf)
683 			fill_cache_read(buf, param->fill_buf->buf_size, false);
684 		else if (uparams->benchmark_cmd[0])
685 			execvp(uparams->benchmark_cmd[0], (char **)uparams->benchmark_cmd);
686 		exit(EXIT_SUCCESS);
687 	}
688 
689 	ksft_print_msg("Benchmark PID: %d\n", (int)bm_pid);
690 
691 	/* Give benchmark enough time to fully run. */
692 	sleep(1);
693 
694 	/* Test runs until the callback setup() tells the test to stop. */
695 	while (1) {
696 		ret = param->setup(test, uparams, param);
697 		if (ret == END_OF_TESTS) {
698 			ret = 0;
699 			break;
700 		}
701 		if (ret < 0)
702 			break;
703 
704 		ret = param->measure(uparams, param, bm_pid);
705 		if (ret)
706 			break;
707 	}
708 
709 	kill(bm_pid, SIGKILL);
710 free_buf:
711 	free(buf);
712 reset_affinity:
713 	taskset_restore(ppid, &old_affinity);
714 	return ret;
715 }
716