Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * fill_buf benchmark
0004  *
0005  * Copyright (C) 2018 Intel Corporation
0006  *
0007  * Authors:
0008  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
0009  *    Fenghua Yu <fenghua.yu@intel.com>
0010  */
0011 #include <stdio.h>
0012 #include <unistd.h>
0013 #include <stdlib.h>
0014 #include <sys/types.h>
0015 #include <sys/wait.h>
0016 #include <inttypes.h>
0017 #include <malloc.h>
0018 #include <string.h>
0019 
0020 #include "resctrl.h"
0021 
0022 #define CL_SIZE         (64)
0023 #define PAGE_SIZE       (4 * 1024)
0024 #define MB          (1024 * 1024)
0025 
0026 static unsigned char *startptr;
0027 
0028 static void sb(void)
0029 {
0030 #if defined(__i386) || defined(__x86_64)
0031     asm volatile("sfence\n\t"
0032              : : : "memory");
0033 #endif
0034 }
0035 
0036 static void ctrl_handler(int signo)
0037 {
0038     free(startptr);
0039     printf("\nEnding\n");
0040     sb();
0041     exit(EXIT_SUCCESS);
0042 }
0043 
0044 static void cl_flush(void *p)
0045 {
0046 #if defined(__i386) || defined(__x86_64)
0047     asm volatile("clflush (%0)\n\t"
0048              : : "r"(p) : "memory");
0049 #endif
0050 }
0051 
0052 static void mem_flush(void *p, size_t s)
0053 {
0054     char *cp = (char *)p;
0055     size_t i = 0;
0056 
0057     s = s / CL_SIZE; /* mem size in cache llines */
0058 
0059     for (i = 0; i < s; i++)
0060         cl_flush(&cp[i * CL_SIZE]);
0061 
0062     sb();
0063 }
0064 
0065 static void *malloc_and_init_memory(size_t s)
0066 {
0067     uint64_t *p64;
0068     size_t s64;
0069 
0070     void *p = memalign(PAGE_SIZE, s);
0071 
0072     p64 = (uint64_t *)p;
0073     s64 = s / sizeof(uint64_t);
0074 
0075     while (s64 > 0) {
0076         *p64 = (uint64_t)rand();
0077         p64 += (CL_SIZE / sizeof(uint64_t));
0078         s64 -= (CL_SIZE / sizeof(uint64_t));
0079     }
0080 
0081     return p;
0082 }
0083 
0084 static int fill_one_span_read(unsigned char *start_ptr, unsigned char *end_ptr)
0085 {
0086     unsigned char sum, *p;
0087 
0088     sum = 0;
0089     p = start_ptr;
0090     while (p < end_ptr) {
0091         sum += *p;
0092         p += (CL_SIZE / 2);
0093     }
0094 
0095     return sum;
0096 }
0097 
0098 static
0099 void fill_one_span_write(unsigned char *start_ptr, unsigned char *end_ptr)
0100 {
0101     unsigned char *p;
0102 
0103     p = start_ptr;
0104     while (p < end_ptr) {
0105         *p = '1';
0106         p += (CL_SIZE / 2);
0107     }
0108 }
0109 
0110 static int fill_cache_read(unsigned char *start_ptr, unsigned char *end_ptr,
0111                char *resctrl_val)
0112 {
0113     int ret = 0;
0114     FILE *fp;
0115 
0116     while (1) {
0117         ret = fill_one_span_read(start_ptr, end_ptr);
0118         if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)))
0119             break;
0120     }
0121 
0122     /* Consume read result so that reading memory is not optimized out. */
0123     fp = fopen("/dev/null", "w");
0124     if (!fp) {
0125         perror("Unable to write to /dev/null");
0126         return -1;
0127     }
0128     fprintf(fp, "Sum: %d ", ret);
0129     fclose(fp);
0130 
0131     return 0;
0132 }
0133 
0134 static int fill_cache_write(unsigned char *start_ptr, unsigned char *end_ptr,
0135                 char *resctrl_val)
0136 {
0137     while (1) {
0138         fill_one_span_write(start_ptr, end_ptr);
0139         if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)))
0140             break;
0141     }
0142 
0143     return 0;
0144 }
0145 
0146 static int
0147 fill_cache(unsigned long long buf_size, int malloc_and_init, int memflush,
0148        int op, char *resctrl_val)
0149 {
0150     unsigned char *start_ptr, *end_ptr;
0151     unsigned long long i;
0152     int ret;
0153 
0154     if (malloc_and_init)
0155         start_ptr = malloc_and_init_memory(buf_size);
0156     else
0157         start_ptr = malloc(buf_size);
0158 
0159     if (!start_ptr)
0160         return -1;
0161 
0162     startptr = start_ptr;
0163     end_ptr = start_ptr + buf_size;
0164 
0165     /*
0166      * It's better to touch the memory once to avoid any compiler
0167      * optimizations
0168      */
0169     if (!malloc_and_init) {
0170         for (i = 0; i < buf_size; i++)
0171             *start_ptr++ = (unsigned char)rand();
0172     }
0173 
0174     start_ptr = startptr;
0175 
0176     /* Flush the memory before using to avoid "cache hot pages" effect */
0177     if (memflush)
0178         mem_flush(start_ptr, buf_size);
0179 
0180     if (op == 0)
0181         ret = fill_cache_read(start_ptr, end_ptr, resctrl_val);
0182     else
0183         ret = fill_cache_write(start_ptr, end_ptr, resctrl_val);
0184 
0185     if (ret) {
0186         printf("\n Error in fill cache read/write...\n");
0187         return -1;
0188     }
0189 
0190     free(startptr);
0191 
0192     return 0;
0193 }
0194 
0195 int run_fill_buf(unsigned long span, int malloc_and_init_memory,
0196          int memflush, int op, char *resctrl_val)
0197 {
0198     unsigned long long cache_size = span;
0199     int ret;
0200 
0201     /* set up ctrl-c handler */
0202     if (signal(SIGINT, ctrl_handler) == SIG_ERR)
0203         printf("Failed to catch SIGINT!\n");
0204     if (signal(SIGHUP, ctrl_handler) == SIG_ERR)
0205         printf("Failed to catch SIGHUP!\n");
0206 
0207     ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op,
0208              resctrl_val);
0209     if (ret) {
0210         printf("\n Error in fill cache\n");
0211         return -1;
0212     }
0213 
0214     return 0;
0215 }