diff options
Diffstat (limited to 'tools/testing/selftests/resctrl/fill_buf.c')
| -rw-r--r-- | tools/testing/selftests/resctrl/fill_buf.c | 213 | 
1 files changed, 213 insertions, 0 deletions
diff --git a/tools/testing/selftests/resctrl/fill_buf.c b/tools/testing/selftests/resctrl/fill_buf.c new file mode 100644 index 000000000000..79c611c99a3d --- /dev/null +++ b/tools/testing/selftests/resctrl/fill_buf.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fill_buf benchmark + * + * Copyright (C) 2018 Intel Corporation + * + * Authors: + *    Sai Praneeth Prakhya <[email protected]>, + *    Fenghua Yu <[email protected]> + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <inttypes.h> +#include <malloc.h> +#include <string.h> + +#include "resctrl.h" + +#define CL_SIZE			(64) +#define PAGE_SIZE		(4 * 1024) +#define MB			(1024 * 1024) + +static unsigned char *startptr; + +static void sb(void) +{ +#if defined(__i386) || defined(__x86_64) +	asm volatile("sfence\n\t" +		     : : : "memory"); +#endif +} + +static void ctrl_handler(int signo) +{ +	free(startptr); +	printf("\nEnding\n"); +	sb(); +	exit(EXIT_SUCCESS); +} + +static void cl_flush(void *p) +{ +#if defined(__i386) || defined(__x86_64) +	asm volatile("clflush (%0)\n\t" +		     : : "r"(p) : "memory"); +#endif +} + +static void mem_flush(void *p, size_t s) +{ +	char *cp = (char *)p; +	size_t i = 0; + +	s = s / CL_SIZE; /* mem size in cache llines */ + +	for (i = 0; i < s; i++) +		cl_flush(&cp[i * CL_SIZE]); + +	sb(); +} + +static void *malloc_and_init_memory(size_t s) +{ +	uint64_t *p64; +	size_t s64; + +	void *p = memalign(PAGE_SIZE, s); + +	p64 = (uint64_t *)p; +	s64 = s / sizeof(uint64_t); + +	while (s64 > 0) { +		*p64 = (uint64_t)rand(); +		p64 += (CL_SIZE / sizeof(uint64_t)); +		s64 -= (CL_SIZE / sizeof(uint64_t)); +	} + +	return p; +} + +static int fill_one_span_read(unsigned char *start_ptr, unsigned char *end_ptr) +{ +	unsigned char sum, *p; + +	sum = 0; +	p = start_ptr; +	while (p < end_ptr) { +		sum += *p; +		p += (CL_SIZE / 2); +	} + +	return sum; +} + +static +void fill_one_span_write(unsigned char *start_ptr, unsigned char *end_ptr) +{ +	unsigned char *p; + +	p = start_ptr; +	while (p < end_ptr) { +		*p = '1'; +		p += (CL_SIZE / 2); +	} +} + +static int fill_cache_read(unsigned char *start_ptr, unsigned char *end_ptr, +			   char *resctrl_val) +{ +	int ret = 0; +	FILE *fp; + +	while (1) { +		ret = fill_one_span_read(start_ptr, end_ptr); +		if (!strcmp(resctrl_val, "cat")) +			break; +	} + +	/* Consume read result so that reading memory is not optimized out. */ +	fp = fopen("/dev/null", "w"); +	if (!fp) +		perror("Unable to write to /dev/null"); +	fprintf(fp, "Sum: %d ", ret); +	fclose(fp); + +	return 0; +} + +static int fill_cache_write(unsigned char *start_ptr, unsigned char *end_ptr, +			    char *resctrl_val) +{ +	while (1) { +		fill_one_span_write(start_ptr, end_ptr); +		if (!strcmp(resctrl_val, "cat")) +			break; +	} + +	return 0; +} + +static int +fill_cache(unsigned long long buf_size, int malloc_and_init, int memflush, +	   int op, char *resctrl_val) +{ +	unsigned char *start_ptr, *end_ptr; +	unsigned long long i; +	int ret; + +	if (malloc_and_init) +		start_ptr = malloc_and_init_memory(buf_size); +	else +		start_ptr = malloc(buf_size); + +	if (!start_ptr) +		return -1; + +	startptr = start_ptr; +	end_ptr = start_ptr + buf_size; + +	/* +	 * It's better to touch the memory once to avoid any compiler +	 * optimizations +	 */ +	if (!malloc_and_init) { +		for (i = 0; i < buf_size; i++) +			*start_ptr++ = (unsigned char)rand(); +	} + +	start_ptr = startptr; + +	/* Flush the memory before using to avoid "cache hot pages" effect */ +	if (memflush) +		mem_flush(start_ptr, buf_size); + +	if (op == 0) +		ret = fill_cache_read(start_ptr, end_ptr, resctrl_val); +	else +		ret = fill_cache_write(start_ptr, end_ptr, resctrl_val); + +	if (ret) { +		printf("\n Error in fill cache read/write...\n"); +		return -1; +	} + +	free(startptr); + +	return 0; +} + +int run_fill_buf(unsigned long span, int malloc_and_init_memory, +		 int memflush, int op, char *resctrl_val) +{ +	unsigned long long cache_size = span; +	int ret; + +	/* set up ctrl-c handler */ +	if (signal(SIGINT, ctrl_handler) == SIG_ERR) +		printf("Failed to catch SIGINT!\n"); +	if (signal(SIGHUP, ctrl_handler) == SIG_ERR) +		printf("Failed to catch SIGHUP!\n"); + +	ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op, +			 resctrl_val); +	if (ret) { +		printf("\n Error in fill cache\n"); +		return -1; +	} + +	return 0; +}  |