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