diff options
Diffstat (limited to 'tools/testing/selftests/resctrl/fill_buf.c')
-rw-r--r-- | tools/testing/selftests/resctrl/fill_buf.c | 182 |
1 files changed, 69 insertions, 113 deletions
diff --git a/tools/testing/selftests/resctrl/fill_buf.c b/tools/testing/selftests/resctrl/fill_buf.c index 79c611c99a3d..ae120f1735c0 100644 --- a/tools/testing/selftests/resctrl/fill_buf.c +++ b/tools/testing/selftests/resctrl/fill_buf.c @@ -14,7 +14,6 @@ #include <sys/types.h> #include <sys/wait.h> #include <inttypes.h> -#include <malloc.h> #include <string.h> #include "resctrl.h" @@ -23,8 +22,6 @@ #define PAGE_SIZE (4 * 1024) #define MB (1024 * 1024) -static unsigned char *startptr; - static void sb(void) { #if defined(__i386) || defined(__x86_64) @@ -33,14 +30,6 @@ static void sb(void) #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) @@ -49,165 +38,132 @@ static void cl_flush(void *p) #endif } -static void mem_flush(void *p, size_t s) +void mem_flush(unsigned char *buf, size_t buf_size) { - char *cp = (char *)p; + unsigned char *cp = buf; size_t i = 0; - s = s / CL_SIZE; /* mem size in cache llines */ + buf_size = buf_size / CL_SIZE; /* mem size in cache lines */ - for (i = 0; i < s; i++) + for (i = 0; i < buf_size; 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; -} +/* + * Buffer index step advance to workaround HW prefetching interfering with + * the measurements. + * + * Must be a prime to step through all indexes of the buffer. + * + * Some primes work better than others on some architectures (from MBA/MBM + * result stability point of view). + */ +#define FILL_IDX_MULT 23 -static int fill_one_span_read(unsigned char *start_ptr, unsigned char *end_ptr) +static int fill_one_span_read(unsigned char *buf, size_t buf_size) { - unsigned char sum, *p; + unsigned int size = buf_size / (CL_SIZE / 2); + unsigned int i, idx = 0; + unsigned char sum = 0; - sum = 0; - p = start_ptr; - while (p < end_ptr) { - sum += *p; - p += (CL_SIZE / 2); + /* + * Read the buffer in an order that is unexpected by HW prefetching + * optimizations to prevent them interfering with the caching pattern. + * + * The read order is (in terms of halves of cachelines): + * i * FILL_IDX_MULT % size + * The formula is open-coded below to avoiding modulo inside the loop + * as it improves MBA/MBM result stability on some architectures. + */ + for (i = 0; i < size; i++) { + sum += buf[idx * (CL_SIZE / 2)]; + + idx += FILL_IDX_MULT; + while (idx >= size) + idx -= size; } return sum; } -static -void fill_one_span_write(unsigned char *start_ptr, unsigned char *end_ptr) +static void fill_one_span_write(unsigned char *buf, size_t buf_size) { + unsigned char *end_ptr = buf + buf_size; unsigned char *p; - p = start_ptr; + p = buf; 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) +void fill_cache_read(unsigned char *buf, size_t buf_size, bool once) { int ret = 0; - FILE *fp; while (1) { - ret = fill_one_span_read(start_ptr, end_ptr); - if (!strcmp(resctrl_val, "cat")) + ret = fill_one_span_read(buf, buf_size); + if (once) 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; + *value_sink = ret; } -static int fill_cache_write(unsigned char *start_ptr, unsigned char *end_ptr, - char *resctrl_val) +static void fill_cache_write(unsigned char *buf, size_t buf_size, bool once) { while (1) { - fill_one_span_write(start_ptr, end_ptr); - if (!strcmp(resctrl_val, "cat")) + fill_one_span_write(buf, buf_size); + if (once) 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 *alloc_buffer(size_t buf_size, int memflush) { - unsigned char *start_ptr, *end_ptr; - unsigned long long i; + void *buf = NULL; + uint64_t *p64; + size_t s64; 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; + ret = posix_memalign(&buf, PAGE_SIZE, buf_size); + if (ret < 0) + return NULL; - startptr = start_ptr; - end_ptr = start_ptr + buf_size; + /* Initialize the buffer */ + p64 = buf; + s64 = buf_size / sizeof(uint64_t); - /* - * 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(); + while (s64 > 0) { + *p64 = (uint64_t)rand(); + p64 += (CL_SIZE / sizeof(uint64_t)); + s64 -= (CL_SIZE / sizeof(uint64_t)); } - start_ptr = startptr; - /* Flush the memory before using to avoid "cache hot pages" effect */ if (memflush) - mem_flush(start_ptr, buf_size); + mem_flush(buf, 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; + return buf; } -int run_fill_buf(unsigned long span, int malloc_and_init_memory, - int memflush, int op, char *resctrl_val) +int run_fill_buf(size_t buf_size, int memflush, int op, bool once) { - unsigned long long cache_size = span; - int ret; + unsigned char *buf; - /* 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"); + buf = alloc_buffer(buf_size, memflush); + if (!buf) return -1; - } + + if (op == 0) + fill_cache_read(buf, buf_size, once); + else + fill_cache_write(buf, buf_size, once); + free(buf); return 0; } |