Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * fill_buf benchmark
  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 <stdio.h>
 12#include <unistd.h>
 13#include <stdlib.h>
 14#include <sys/types.h>
 15#include <sys/wait.h>
 16#include <inttypes.h>
 
 17#include <string.h>
 18
 19#include "resctrl.h"
 20
 21#define CL_SIZE			(64)
 22#define PAGE_SIZE		(4 * 1024)
 23#define MB			(1024 * 1024)
 24
 
 
 25static void sb(void)
 26{
 27#if defined(__i386) || defined(__x86_64)
 28	asm volatile("sfence\n\t"
 29		     : : : "memory");
 30#endif
 31}
 32
 
 
 
 
 
 
 
 
 33static void cl_flush(void *p)
 34{
 35#if defined(__i386) || defined(__x86_64)
 36	asm volatile("clflush (%0)\n\t"
 37		     : : "r"(p) : "memory");
 38#endif
 39}
 40
 41void mem_flush(unsigned char *buf, size_t buf_size)
 42{
 43	unsigned char *cp = buf;
 44	size_t i = 0;
 45
 46	buf_size = buf_size / CL_SIZE; /* mem size in cache lines */
 47
 48	for (i = 0; i < buf_size; i++)
 49		cl_flush(&cp[i * CL_SIZE]);
 50
 51	sb();
 52}
 53
 54/*
 55 * Buffer index step advance to workaround HW prefetching interfering with
 56 * the measurements.
 57 *
 58 * Must be a prime to step through all indexes of the buffer.
 59 *
 60 * Some primes work better than others on some architectures (from MBA/MBM
 61 * result stability point of view).
 62 */
 63#define FILL_IDX_MULT	23
 64
 65static int fill_one_span_read(unsigned char *buf, size_t buf_size)
 66{
 67	unsigned int size = buf_size / (CL_SIZE / 2);
 68	unsigned int i, idx = 0;
 69	unsigned char sum = 0;
 70
 71	/*
 72	 * Read the buffer in an order that is unexpected by HW prefetching
 73	 * optimizations to prevent them interfering with the caching pattern.
 74	 *
 75	 * The read order is (in terms of halves of cachelines):
 76	 *	i * FILL_IDX_MULT % size
 77	 * The formula is open-coded below to avoiding modulo inside the loop
 78	 * as it improves MBA/MBM result stability on some architectures.
 79	 */
 80	for (i = 0; i < size; i++) {
 81		sum += buf[idx * (CL_SIZE / 2)];
 82
 83		idx += FILL_IDX_MULT;
 84		while (idx >= size)
 85			idx -= size;
 
 
 
 
 
 
 86	}
 87
 88	return sum;
 89}
 90
 91void fill_cache_read(unsigned char *buf, size_t buf_size, bool once)
 
 
 
 
 
 
 
 
 
 
 
 
 
 92{
 93	int ret = 0;
 
 94
 95	while (1) {
 96		ret = fill_one_span_read(buf, buf_size);
 97		if (once)
 98			break;
 99	}
100
101	/* Consume read result so that reading memory is not optimized out. */
102	*value_sink = ret;
 
 
 
 
 
 
 
 
103}
104
105unsigned char *alloc_buffer(size_t buf_size, bool memflush)
 
106{
107	void *buf = NULL;
108	uint64_t *p64;
109	ssize_t s64;
 
 
 
 
 
 
 
 
 
 
 
 
110	int ret;
111
112	ret = posix_memalign(&buf, PAGE_SIZE, buf_size);
113	if (ret < 0)
114		return NULL;
115
116	/* Initialize the buffer */
117	p64 = buf;
118	s64 = buf_size / sizeof(uint64_t);
119
120	while (s64 > 0) {
121		*p64 = (uint64_t)rand();
122		p64 += (CL_SIZE / sizeof(uint64_t));
123		s64 -= (CL_SIZE / sizeof(uint64_t));
 
 
 
 
 
 
 
 
 
124	}
125
 
 
126	/* Flush the memory before using to avoid "cache hot pages" effect */
127	if (memflush)
128		mem_flush(buf, buf_size);
 
 
 
 
 
 
 
 
 
 
 
 
129
130	return buf;
131}
132
133ssize_t get_fill_buf_size(int cpu_no, const char *cache_type)
 
134{
135	unsigned long cache_total_size = 0;
136	int ret;
137
138	ret = get_cache_size(cpu_no, cache_type, &cache_total_size);
139	if (ret)
140		return ret;
 
 
 
 
 
 
 
 
 
141
142	return cache_total_size * 2 > MINIMUM_SPAN ?
143			cache_total_size * 2 : MINIMUM_SPAN;
144}
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * fill_buf benchmark
  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 <stdio.h>
 12#include <unistd.h>
 13#include <stdlib.h>
 14#include <sys/types.h>
 15#include <sys/wait.h>
 16#include <inttypes.h>
 17#include <malloc.h>
 18#include <string.h>
 19
 20#include "resctrl.h"
 21
 22#define CL_SIZE			(64)
 23#define PAGE_SIZE		(4 * 1024)
 24#define MB			(1024 * 1024)
 25
 26static unsigned char *startptr;
 27
 28static void sb(void)
 29{
 30#if defined(__i386) || defined(__x86_64)
 31	asm volatile("sfence\n\t"
 32		     : : : "memory");
 33#endif
 34}
 35
 36static void ctrl_handler(int signo)
 37{
 38	free(startptr);
 39	printf("\nEnding\n");
 40	sb();
 41	exit(EXIT_SUCCESS);
 42}
 43
 44static void cl_flush(void *p)
 45{
 46#if defined(__i386) || defined(__x86_64)
 47	asm volatile("clflush (%0)\n\t"
 48		     : : "r"(p) : "memory");
 49#endif
 50}
 51
 52static void mem_flush(void *p, size_t s)
 53{
 54	char *cp = (char *)p;
 55	size_t i = 0;
 56
 57	s = s / CL_SIZE; /* mem size in cache llines */
 58
 59	for (i = 0; i < s; i++)
 60		cl_flush(&cp[i * CL_SIZE]);
 61
 62	sb();
 63}
 64
 65static void *malloc_and_init_memory(size_t s)
 66{
 67	uint64_t *p64;
 68	size_t s64;
 69
 70	void *p = memalign(PAGE_SIZE, s);
 
 
 
 
 
 
 
 
 
 
 71
 72	p64 = (uint64_t *)p;
 73	s64 = s / sizeof(uint64_t);
 74
 75	while (s64 > 0) {
 76		*p64 = (uint64_t)rand();
 77		p64 += (CL_SIZE / sizeof(uint64_t));
 78		s64 -= (CL_SIZE / sizeof(uint64_t));
 79	}
 80
 81	return p;
 82}
 83
 84static int fill_one_span_read(unsigned char *start_ptr, unsigned char *end_ptr)
 85{
 86	unsigned char sum, *p;
 87
 88	sum = 0;
 89	p = start_ptr;
 90	while (p < end_ptr) {
 91		sum += *p;
 92		p += (CL_SIZE / 2);
 93	}
 94
 95	return sum;
 96}
 97
 98static
 99void fill_one_span_write(unsigned char *start_ptr, unsigned char *end_ptr)
100{
101	unsigned char *p;
102
103	p = start_ptr;
104	while (p < end_ptr) {
105		*p = '1';
106		p += (CL_SIZE / 2);
107	}
108}
109
110static int fill_cache_read(unsigned char *start_ptr, unsigned char *end_ptr,
111			   char *resctrl_val)
112{
113	int ret = 0;
114	FILE *fp;
115
116	while (1) {
117		ret = fill_one_span_read(start_ptr, end_ptr);
118		if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)))
119			break;
120	}
121
122	/* Consume read result so that reading memory is not optimized out. */
123	fp = fopen("/dev/null", "w");
124	if (!fp) {
125		perror("Unable to write to /dev/null");
126		return -1;
127	}
128	fprintf(fp, "Sum: %d ", ret);
129	fclose(fp);
130
131	return 0;
132}
133
134static int fill_cache_write(unsigned char *start_ptr, unsigned char *end_ptr,
135			    char *resctrl_val)
136{
137	while (1) {
138		fill_one_span_write(start_ptr, end_ptr);
139		if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)))
140			break;
141	}
142
143	return 0;
144}
145
146static int
147fill_cache(unsigned long long buf_size, int malloc_and_init, int memflush,
148	   int op, char *resctrl_val)
149{
150	unsigned char *start_ptr, *end_ptr;
151	unsigned long long i;
152	int ret;
153
154	if (malloc_and_init)
155		start_ptr = malloc_and_init_memory(buf_size);
156	else
157		start_ptr = malloc(buf_size);
 
 
 
158
159	if (!start_ptr)
160		return -1;
161
162	startptr = start_ptr;
163	end_ptr = start_ptr + buf_size;
164
165	/*
166	 * It's better to touch the memory once to avoid any compiler
167	 * optimizations
168	 */
169	if (!malloc_and_init) {
170		for (i = 0; i < buf_size; i++)
171			*start_ptr++ = (unsigned char)rand();
172	}
173
174	start_ptr = startptr;
175
176	/* Flush the memory before using to avoid "cache hot pages" effect */
177	if (memflush)
178		mem_flush(start_ptr, buf_size);
179
180	if (op == 0)
181		ret = fill_cache_read(start_ptr, end_ptr, resctrl_val);
182	else
183		ret = fill_cache_write(start_ptr, end_ptr, resctrl_val);
184
185	if (ret) {
186		printf("\n Error in fill cache read/write...\n");
187		return -1;
188	}
189
190	free(startptr);
191
192	return 0;
193}
194
195int run_fill_buf(unsigned long span, int malloc_and_init_memory,
196		 int memflush, int op, char *resctrl_val)
197{
198	unsigned long long cache_size = span;
199	int ret;
200
201	/* set up ctrl-c handler */
202	if (signal(SIGINT, ctrl_handler) == SIG_ERR)
203		printf("Failed to catch SIGINT!\n");
204	if (signal(SIGHUP, ctrl_handler) == SIG_ERR)
205		printf("Failed to catch SIGHUP!\n");
206
207	ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op,
208			 resctrl_val);
209	if (ret) {
210		printf("\n Error in fill cache\n");
211		return -1;
212	}
213
214	return 0;
 
215}