@@ -10,9 +10,9 @@ struct read_format {
} values[2];
};
-static struct perf_event_attr pea_llc_miss;
+static struct perf_event_attr pea_llc_miss, pea_llc_access;
static struct read_format rf_cqm;
-static int fd_lm;
+static int fd_lm, fd_la;
char llc_occup_path[1024];
static void initialize_perf_event_attr(void)
@@ -27,15 +27,30 @@ static void initialize_perf_event_attr(void)
pea_llc_miss.inherit = 1;
pea_llc_miss.exclude_guest = 1;
pea_llc_miss.disabled = 1;
+
+ pea_llc_access.type = PERF_TYPE_HARDWARE;
+ pea_llc_access.size = sizeof(struct perf_event_attr);
+ pea_llc_access.read_format = PERF_FORMAT_GROUP;
+ pea_llc_access.exclude_kernel = 1;
+ pea_llc_access.exclude_hv = 1;
+ pea_llc_access.exclude_idle = 1;
+ pea_llc_access.exclude_callchain_kernel = 1;
+ pea_llc_access.inherit = 1;
+ pea_llc_access.exclude_guest = 1;
+ pea_llc_access.disabled = 1;
+
}
static void ioctl_perf_event_ioc_reset_enable(void)
{
ioctl(fd_lm, PERF_EVENT_IOC_RESET, 0);
ioctl(fd_lm, PERF_EVENT_IOC_ENABLE, 0);
+
+ ioctl(fd_la, PERF_EVENT_IOC_RESET, 0);
+ ioctl(fd_la, PERF_EVENT_IOC_ENABLE, 0);
}
-static int perf_event_open_llc_miss(pid_t pid, int cpu_no)
+static int perf_event_open_llc_miss_rate(pid_t pid, int cpu_no)
{
fd_lm = perf_event_open(&pea_llc_miss, pid, cpu_no, -1,
PERF_FLAG_FD_CLOEXEC);
@@ -45,29 +60,40 @@ static int perf_event_open_llc_miss(pid_t pid, int cpu_no)
return -1;
}
+ fd_la = perf_event_open(&pea_llc_access, pid, cpu_no, fd_lm,
+ PERF_FLAG_FD_CLOEXEC);
+ if (fd_la == -1) {
+ perror("Error opening member");
+ ctrlc_handler(0, NULL, NULL);
+ return -1;
+ }
+
return 0;
}
-static int initialize_llc_perf(void)
+static void initialize_llc_perf(void)
{
memset(&pea_llc_miss, 0, sizeof(struct perf_event_attr));
+ memset(&pea_llc_access, 0, sizeof(struct perf_event_attr));
memset(&rf_cqm, 0, sizeof(struct read_format));
- /* Initialize perf_event_attr structures for HW_CACHE_MISSES */
+ /*
+ * Initialize perf_event_attr structures for HW_CACHE_MISSES and
+ * HW_CACHE_REFERENCES
+ */
initialize_perf_event_attr();
pea_llc_miss.config = PERF_COUNT_HW_CACHE_MISSES;
+ pea_llc_access.config = PERF_COUNT_HW_CACHE_REFERENCES;
- rf_cqm.nr = 1;
-
- return 0;
+ rf_cqm.nr = 2;
}
static int reset_enable_llc_perf(pid_t pid, int cpu_no)
{
int ret = 0;
- ret = perf_event_open_llc_miss(pid, cpu_no);
+ ret = perf_event_open_llc_miss_rate(pid, cpu_no);
if (ret < 0)
return ret;
@@ -78,21 +104,21 @@ static int reset_enable_llc_perf(pid_t pid, int cpu_no)
}
/*
- * get_llc_perf: llc cache miss through perf events
- * @cpu_no: CPU number that the benchmark PID is binded to
+ * get_llc_perf_miss_rate: llc cache miss rate through perf events
+ * @cpu_no: CPU number that the benchmark PID is binded to
*
- * Perf events like HW_CACHE_MISSES could be used to validate number of
- * cache lines allocated.
+ * Perf events like HW_CACHE_MISSES and HW_CACHE_REFERENCES could be used to
+ * approximate LLc occupancy under controlled environment
*
* Return: =0 on success. <0 on failure.
*/
-static int get_llc_perf(unsigned long *llc_perf_miss)
+static int get_llc_perf_miss_rate(float *llc_perf_miss_rate)
{
- __u64 total_misses;
+ __u64 total_misses, total_references;
/* Stop counters after one span to get miss rate */
-
ioctl(fd_lm, PERF_EVENT_IOC_DISABLE, 0);
+ ioctl(fd_la, PERF_EVENT_IOC_DISABLE, 0);
if (read(fd_lm, &rf_cqm, sizeof(struct read_format)) == -1) {
perror("Could not get llc misses through perf");
@@ -100,11 +126,19 @@ static int get_llc_perf(unsigned long *llc_perf_miss)
return -1;
}
+ if (read(fd_la, &rf_cqm, sizeof(struct read_format)) == -1) {
+ perror("Could not get llc accesses through perf");
+
+ return -1;
+ }
+
total_misses = rf_cqm.values[0].value;
+ total_references = rf_cqm.values[1].value;
close(fd_lm);
+ close(fd_la);
- *llc_perf_miss = total_misses;
+ *llc_perf_miss_rate = ((float)total_misses / total_references) * 100;
return 0;
}
@@ -176,15 +210,16 @@ static int print_results_cache(char *filename, int bm_pid,
int measure_cache_vals(struct resctrl_val_param *param, int bm_pid)
{
- unsigned long llc_perf_miss = 0, llc_occu_resc = 0, llc_value = 0;
+ unsigned long llc_occu_resc = 0, llc_value = 0;
+ float llc_perf_miss_rate = 0;
int ret;
/* Measure cache miss from perf */
if (!strcmp(param->resctrl_val, "cat")) {
- ret = get_llc_perf(&llc_perf_miss);
+ ret = get_llc_perf_miss_rate(&llc_perf_miss_rate);
if (ret < 0)
return ret;
- llc_value = llc_perf_miss;
+ llc_value = llc_perf_miss_rate;
}
/* Measure llc occupancy from resctrl */
@@ -202,66 +237,72 @@ int measure_cache_vals(struct resctrl_val_param *param, int bm_pid)
}
/*
- * cache_val: execute benchmark and measure LLC occupancy resctrl
- * and perf cache miss for the benchmark
- * @param: parameters passed to cache_val()
+ * setup_critical_process: Bind given pid to given cpu and write the pid
+ * in requested resctrl FS location, set schemata,
+ * initialize perf LLC counters and also initialize
+ * fill buffer benchmark.
+ * @pid: pid of the process
+ * @param: Parameters passed to cache_val()
*
- * Return: 0 on success. non-zero on failure.
+ * Return: 0 on success. non-zero on failure.
*/
-int cat_val(struct resctrl_val_param *param)
+int setup_critical_process(pid_t pid, struct resctrl_val_param *param)
{
- int malloc_and_init_memory = 1, memflush = 1, operation = 0, ret = 0;
+ int ret = 0;
char *resctrl_val = param->resctrl_val;
- pid_t bm_pid;
+ char schemata[64];
- if (strcmp(param->filename, "") == 0)
- sprintf(param->filename, "stdio");
+ /* Taskset parent (critical process) to a specified cpu */
+ ret = taskset_benchmark(pid, param->cpu_no);
+ if (ret)
+ return ret;
- bm_pid = getpid();
+ /* Write parent to specified con_mon grp, mon_grp in resctrl FS */
+ ret = write_bm_pid_to_resctrl(pid, param->ctrlgrp, param->mongrp,
+ resctrl_val);
+ if (ret)
+ return ret;
- /* Taskset benchmark to specified cpu */
- ret = taskset_benchmark(bm_pid, param->cpu_no);
+ sprintf(schemata, "%lx", param->mask);
+ ret = write_schemata(param->ctrlgrp, schemata, param->cpu_no, "cat");
if (ret)
return ret;
- /* Write benchmark to specified con_mon grp, mon_grp in resctrl FS */
- ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp,
- resctrl_val);
+ initialize_llc_perf();
+
+ ret = init_buffer(param->span, 1, 1);
if (ret)
return ret;
- if ((strcmp(resctrl_val, "cat") == 0)) {
- ret = initialize_llc_perf();
- if (ret)
- return ret;
- }
+ return 0;
+}
+
+int run_critical_process(pid_t pid, struct resctrl_val_param *param)
+{
+ int ret = 0;
- /* Test runs until the callback setup() tells the test to stop. */
+ /* Test runs until the callback setup() tells the test to stop */
while (1) {
- if (strcmp(resctrl_val, "cat") == 0) {
- ret = param->setup(param);
- if (ret) {
- ret = 0;
- break;
- }
- ret = reset_enable_llc_perf(bm_pid, param->cpu_no);
- if (ret)
- break;
-
- if (run_fill_buf(param->span, malloc_and_init_memory,
- memflush, operation, resctrl_val)) {
- fprintf(stderr, "Error-running fill buffer\n");
- ret = -1;
- break;
- }
-
- sleep(1);
- ret = measure_cache_vals(param, bm_pid);
- if (ret)
- break;
- } else {
+ ret = param->setup(param);
+ if (ret) {
+ ret = 0;
+ break;
+ }
+
+ ret = reset_enable_llc_perf(pid, param->cpu_no);
+ if (ret)
+ break;
+
+ /* Read buffer once */
+ if (use_buffer_once(0)) {
+ fprintf(stderr, "Error-running fill buffer\n");
+ ret = -1;
break;
}
+
+ ret = measure_cache_vals(param, pid);
+ if (ret)
+ break;
}
return ret;
@@ -11,70 +11,65 @@
#include "resctrl.h"
#include <unistd.h>
-#define RESULT_FILE_NAME1 "result_cat1"
-#define RESULT_FILE_NAME2 "result_cat2"
-#define NUM_OF_RUNS 5
-#define MAX_DIFF_PERCENT 4
-#define MAX_DIFF 1000000
+#define RESULT_FILE_NAME "result_cat"
+#define NUM_OF_RUNS 10
+#define MAX_DIFF_PERCENT 5
-int count_of_bits;
char cbm_mask[256];
-unsigned long long_mask;
-unsigned long cache_size;
-/*
- * Change schemata. Write schemata to specified
- * con_mon grp, mon_grp in resctrl FS.
- * Run 5 times in order to get average values.
- */
+static unsigned long avg_llc_perf_miss_rate_single_thread;
+static unsigned long p1_mask, p2_mask;
+static unsigned long cache_size;
+static pid_t noisy_pid;
+static int count_of_bits;
+
+/* Run 5 times in order to get average values */
static int cat_setup(struct resctrl_val_param *p)
{
- char schemata[64];
- int ret = 0;
-
/* Run NUM_OF_RUNS times */
if (p->num_of_runs >= NUM_OF_RUNS)
return -1;
- if (p->num_of_runs == 0) {
- sprintf(schemata, "%lx", p->mask);
- ret = write_schemata(p->ctrlgrp, schemata, p->cpu_no,
- p->resctrl_val);
- }
p->num_of_runs++;
-
- return ret;
+ return 0;
}
-static void show_cache_info(unsigned long sum_llc_perf_miss, int no_of_bits,
- unsigned long span)
+static void show_cache_info(unsigned long sum_llc_perf_miss_rate,
+ int no_of_bits, unsigned long span)
{
- unsigned long allocated_cache_lines = span / 64;
- unsigned long avg_llc_perf_miss = 0;
- float diff_percent;
+ unsigned long avg_llc_perf_miss_rate = 0, diff_percent = 0;
+
+ avg_llc_perf_miss_rate = sum_llc_perf_miss_rate / (NUM_OF_RUNS - 1);
+ if (!noisy_pid) {
+ avg_llc_perf_miss_rate_single_thread = avg_llc_perf_miss_rate;
+ return;
+ }
- avg_llc_perf_miss = sum_llc_perf_miss / (NUM_OF_RUNS - 1);
- diff_percent = ((float)allocated_cache_lines - avg_llc_perf_miss) /
- allocated_cache_lines * 100;
+ diff_percent = labs(avg_llc_perf_miss_rate -
+ avg_llc_perf_miss_rate_single_thread);
- printf("%sok CAT: cache miss rate within %d%%\n",
- !is_amd && abs((int)diff_percent) > MAX_DIFF_PERCENT ?
+ printf("%sok CAT: cache miss rate difference within %d%%\n",
+ !is_amd && diff_percent > MAX_DIFF_PERCENT ?
"not " : "", MAX_DIFF_PERCENT);
- tests_run++;
- printf("# Percent diff=%d\n", abs((int)diff_percent));
printf("# Number of bits: %d\n", no_of_bits);
- printf("# Avg_llc_perf_miss: %lu\n", avg_llc_perf_miss);
- printf("# Allocated cache lines: %lu\n", allocated_cache_lines);
+ printf("# Buffer size: %lu\n", span);
+ printf("# Avg_llc_perf_miss_rate without noisy process: %lu%%\n",
+ avg_llc_perf_miss_rate_single_thread);
+ printf("# Avg_llc_perf_miss_rate with noisy process: %lu%%\n",
+ avg_llc_perf_miss_rate);
+ printf("# Percent diff: %lu\n", diff_percent);
+ tests_run++;
}
static int check_results(struct resctrl_val_param *param)
{
char *token_array[8], temp[512];
- unsigned long sum_llc_perf_miss = 0;
+ unsigned long sum_llc_perf_miss_rate = 0;
int runs = 0, no_of_bits = 0;
FILE *fp;
- printf("# Checking for pass/fail\n");
+ if (noisy_pid)
+ printf("# Checking for pass/fail\n");
fp = fopen(param->filename, "r");
if (!fp) {
perror("# Cannot open file");
@@ -90,37 +85,107 @@ static int check_results(struct resctrl_val_param *param)
token_array[fields++] = token;
token = strtok(NULL, ":\t");
}
+
/*
* Discard the first value which is inaccurate due to monitoring
* setup transition phase.
*/
- if (runs > 0)
- sum_llc_perf_miss += strtoul(token_array[3], NULL, 0);
runs++;
+ if (runs == 1)
+ continue;
+
+ sum_llc_perf_miss_rate += strtoul(token_array[3], NULL, 0);
}
fclose(fp);
no_of_bits = count_bits(param->mask);
-
- show_cache_info(sum_llc_perf_miss, no_of_bits, param->span);
+ show_cache_info(sum_llc_perf_miss_rate, no_of_bits, param->span);
return 0;
}
void cat_test_cleanup(void)
{
- remove(RESULT_FILE_NAME1);
- remove(RESULT_FILE_NAME2);
+ remove(RESULT_FILE_NAME);
+}
+
+static int prepare_masks_for_two_processes(int no_of_bits, char *cache_type)
+{
+ int ret, i;
+ unsigned long long_mask, shareable_mask;
+
+ /* Get default cbm mask for L3/L2 cache */
+ ret = get_cbm_mask(cache_type);
+ if (ret)
+ return ret;
+
+ /* Get max number of bits from default cbm mask */
+ long_mask = strtoul(cbm_mask, NULL, 16);
+ count_of_bits = count_bits(long_mask);
+
+ /*
+ * Max limit is count_of_bits - 1 because we need exclusive masks for
+ * the two processes. So, the last saved bit will be used by the other
+ * process.
+ */
+ if (no_of_bits < 1 || no_of_bits > count_of_bits - 1) {
+ printf("Invalid input value for no_of_bits 'n'\n");
+ printf("Please Enter value in range 1 to %d\n",
+ count_of_bits - 1);
+ return -1;
+ }
+
+ ret = get_shareable_mask(cache_type, &shareable_mask);
+ if (ret)
+ return ret;
+
+ /* Prepare cbm mask without any shareable bits */
+ for (i = 0; i < no_of_bits; i++) {
+ p1_mask <<= 1;
+ p1_mask |= 1;
+ }
+ p1_mask = ~shareable_mask & p1_mask;
+ p2_mask = ~p1_mask & long_mask;
+
+ return 0;
}
-int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
+static int start_noisy_process(pid_t pid, int sibling_cpu_no)
{
- unsigned long l_mask, l_mask_1;
- int ret, pipefd[2], sibling_cpu_no;
- char pipe_message;
- pid_t bm_pid;
+ int ret;
+ unsigned long buf_size = cache_size * 10;
- cache_size = 0;
+ /* Taskset noisy process to specified cpu */
+ ret = taskset_benchmark(pid, sibling_cpu_no);
+ if (ret)
+ return ret;
+
+ /* Write noisy process to root con_mon grp in resctrl FS */
+ ret = write_bm_pid_to_resctrl(pid, "", "", "cat");
+ if (ret)
+ return ret;
+
+ /*
+ * Passing 'cat' will not loop around buffer forever, hence don't pass
+ * test name
+ */
+ ret = run_fill_buf(buf_size, 1, 1, 0, "");
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type)
+{
+ int ret, sibling_cpu_no;
+ unsigned long buf_size;
+ pid_t critical_pid;
+ char schemata[64];
+
+ noisy_pid = 0;
+ critical_pid = getpid();
+ printf("# critical_pid: %d\n", critical_pid);
ret = remount_resctrlfs(true);
if (ret)
@@ -129,77 +194,43 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
if (!validate_resctrl_feature_request("cat"))
return -1;
- /* Get default cbm mask for L3/L2 cache */
- ret = get_cbm_mask(cache_type);
+ ret = prepare_masks_for_two_processes(no_of_bits, cache_type);
if (ret)
return ret;
- long_mask = strtoul(cbm_mask, NULL, 16);
+ /*
+ * Change root con_mon grp schemata to be exclusive of critical process
+ * schemata to avoid any interference
+ */
+ sprintf(schemata, "%lx", p2_mask);
+ ret = write_schemata("", schemata, cpu_no, "cat");
+ if (ret)
+ return ret;
/* Get L3/L2 cache size */
ret = get_cache_size(cpu_no, cache_type, &cache_size);
if (ret)
return ret;
- printf("cache size :%lu\n", cache_size);
-
- /* Get max number of bits from default-cabm mask */
- count_of_bits = count_bits(long_mask);
-
- if (n < 1 || n > count_of_bits - 1) {
- printf("Invalid input value for no_of_bits n!\n");
- printf("Please Enter value in range 1 to %d\n",
- count_of_bits - 1);
- return -1;
- }
-
- /* Get core id from same socket for running another thread */
- sibling_cpu_no = get_core_sibling(cpu_no);
- if (sibling_cpu_no < 0)
- return -1;
+ printf("# cache size: %lu\n", cache_size);
+ buf_size = cache_size * ((float)(no_of_bits) / count_of_bits);
struct resctrl_val_param param = {
.resctrl_val = "cat",
.cpu_no = cpu_no,
.mum_resctrlfs = 0,
.setup = cat_setup,
+ .ctrlgrp = "c1",
+ .filename = RESULT_FILE_NAME,
+ .mask = p1_mask,
+ .num_of_runs = 0,
+ .span = buf_size
};
- l_mask = long_mask >> n;
- l_mask_1 = ~l_mask & long_mask;
-
- /* Set param values for parent thread which will be allocated bitmask
- * with (max_bits - n) bits
- */
- param.span = cache_size * (count_of_bits - n) / count_of_bits;
- strcpy(param.ctrlgrp, "c2");
- strcpy(param.mongrp, "m2");
- strcpy(param.filename, RESULT_FILE_NAME2);
- param.mask = l_mask;
- param.num_of_runs = 0;
-
- if (pipe(pipefd)) {
- perror("# Unable to create pipe");
- return errno;
- }
-
- bm_pid = fork();
-
- /* Set param values for child thread which will be allocated bitmask
- * with n bits
- */
- if (bm_pid == 0) {
- param.mask = l_mask_1;
- strcpy(param.ctrlgrp, "c1");
- strcpy(param.mongrp, "m1");
- param.span = cache_size * n / count_of_bits;
- strcpy(param.filename, RESULT_FILE_NAME1);
- param.num_of_runs = 0;
- param.cpu_no = sibling_cpu_no;
- }
-
- remove(param.filename);
+ ret = setup_critical_process(critical_pid, ¶m);
+ if (ret)
+ return ret;
- ret = cat_val(¶m);
+ ret = run_critical_process(critical_pid, ¶m);
if (ret)
return ret;
@@ -207,38 +238,51 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
if (ret)
return ret;
- if (bm_pid == 0) {
- /* Tell parent that child is ready */
- close(pipefd[0]);
- pipe_message = 1;
- if (write(pipefd[1], &pipe_message, sizeof(pipe_message)) <
- sizeof(pipe_message)) {
- close(pipefd[1]);
- perror("# failed signaling parent process");
- return errno;
- }
+ printf("# ran critical process without noisy process\n");
- close(pipefd[1]);
- while (1)
- ;
+ /*
+ * Results from first run of critical process are already calculated
+ * and stored in 'avg_llc_perf_miss_single_thread'. Hence, delete the
+ * file, so that it could be reused for second run.
+ */
+ cat_test_cleanup();
+
+ /* Get core id from same socket for running noisy process */
+ sibling_cpu_no = get_core_sibling(cpu_no);
+ if (sibling_cpu_no < 0)
+ return -1;
+
+ noisy_pid = fork();
+ if (noisy_pid == 0) {
+ /*
+ * Child is the noisy_process which runs in root con_mon grp by
+ * default and hence no need to write pid to resctrl FS.
+ * Schemata for root con_mon grp is also set above.
+ */
+ printf("# noisy_pid: %d\n", getpid());
+ ret = start_noisy_process(getpid(), sibling_cpu_no);
+ exit(EXIT_SUCCESS);
+ } else if (noisy_pid == -1) {
+ return -1;
} else {
- /* Parent waits for child to be ready. */
- close(pipefd[1]);
- pipe_message = 0;
- while (pipe_message != 1) {
- if (read(pipefd[0], &pipe_message,
- sizeof(pipe_message)) < sizeof(pipe_message)) {
- perror("# failed reading from child process");
- break;
- }
- }
- close(pipefd[0]);
- kill(bm_pid, SIGKILL);
- }
+ /*
+ * Parent runs again. Sleep for a second here so that noisy
+ * process gets to run before critical process
+ */
+ sleep(1);
+ param.num_of_runs = 0;
+ ret = run_critical_process(critical_pid, ¶m);
+ if (ret)
+ return ret;
- cat_test_cleanup();
- if (bm_pid)
- umount_resctrlfs();
+ ret = check_results(¶m);
+ if (ret)
+ return ret;
+
+ ret = kill(noisy_pid, SIGKILL);
+ if (ret)
+ printf("Failed to kill noisy_pid\n");
+ }
return 0;
}
@@ -139,7 +139,6 @@ static int fill_cache_write(char *resctrl_val)
return 0;
}
-static
int init_buffer(unsigned long long buf_size, int malloc_and_init, int memflush)
{
unsigned char *start_ptr, *end_ptr;
@@ -177,7 +176,33 @@ int init_buffer(unsigned long long buf_size, int malloc_and_init, int memflush)
return 0;
}
-static int use_buffer_forever(int op, char *resctrl_val)
+int use_buffer_once(int op)
+{
+ FILE *fp;
+ int ret = 0;
+
+ if (op == 0) {
+ ret = fill_one_span_read();
+
+ /* Consume result so that reading memory is not optimized */
+ fp = fopen("/dev/null", "w");
+ if (!fp)
+ perror("Unable to write to /dev/null");
+ fprintf(fp, "Sum: %d ", ret);
+ fclose(fp);
+ ret = 0;
+ } else {
+ fill_one_span_write();
+ }
+
+ if (ret) {
+ printf("\n Error in fill cache read/write...\n");
+ return -1;
+ }
+ return 0;
+}
+
+int use_buffer_forever(int op, char *resctrl_val)
{
int ret;
@@ -187,7 +212,7 @@ static int use_buffer_forever(int op, char *resctrl_val)
ret = fill_cache_write(resctrl_val);
if (ret) {
- printf("\n Errror in fill cache read/write...\n");
+ printf("\n Error in fill cache read/write...\n");
return -1;
}
@@ -228,7 +253,7 @@ int run_fill_buf(unsigned long span, int malloc_and_init_memory,
ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op,
resctrl_val);
if (ret) {
- printf("\n Errror in fill cache\n");
+ printf("\n Error in fill cache\n");
return -1;
}
@@ -27,7 +27,7 @@
#define MB (1024 * 1024)
#define RESCTRL_PATH "/sys/fs/resctrl"
#define PHYS_ID_PATH "/sys/devices/system/cpu/cpu"
-#define CBM_MASK_PATH "/sys/fs/resctrl/info"
+#define INFO_PATH "/sys/fs/resctrl/info"
#define PARENT_EXIT(err_msg) \
do { \
@@ -84,6 +84,9 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
char *resctrl_val);
int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
int group_fd, unsigned long flags);
+int init_buffer(unsigned long long buf_size, int malloc_and_init, int memflush);
+int use_buffer_once(int op);
+int use_buffer_forever(int op, char *resctrl_val);
int run_fill_buf(unsigned long span, int malloc_and_init_memory, int memflush,
int op, char *resctrl_va);
int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param);
@@ -93,9 +96,11 @@ void mbm_test_cleanup(void);
int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd);
void mba_test_cleanup(void);
int get_cbm_mask(char *cache_type);
+int get_shareable_mask(char *cache_type, unsigned long *shareable_mask);
int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size);
void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
-int cat_val(struct resctrl_val_param *param);
+int setup_critical_process(pid_t pid, struct resctrl_val_param *param);
+int run_critical_process(pid_t pid, struct resctrl_val_param *param);
void cat_test_cleanup(void);
int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type);
int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd);
@@ -192,8 +192,8 @@ int main(int argc, char **argv)
printf("# Starting CAT test ...\n");
res = cat_perf_miss_val(cpu_no, no_of_bits, "L3");
printf("%sok CAT: test\n", res ? "not " : "");
- tests_run++;
cat_test_cleanup();
+ tests_run++;
}
printf("1..%d\n", tests_run);
@@ -215,7 +215,7 @@ int get_cbm_mask(char *cache_type)
char cbm_mask_path[1024];
FILE *fp;
- sprintf(cbm_mask_path, "%s/%s/cbm_mask", CBM_MASK_PATH, cache_type);
+ sprintf(cbm_mask_path, "%s/%s/cbm_mask", INFO_PATH, cache_type);
fp = fopen(cbm_mask_path, "r");
if (!fp) {
@@ -235,6 +235,38 @@ int get_cbm_mask(char *cache_type)
}
/*
+ * get_shareable_mask - Get shareable mask from shareable_bits for given cache
+ * @cache_type: Cache level L2/L3
+ * @shareable_mask: Mask is returned as unsigned long value
+ *
+ * Return: = 0 on success, < 0 on failure.
+ */
+int get_shareable_mask(char *cache_type, unsigned long *shareable_mask)
+{
+ char shareable_bits_file[1024];
+ FILE *fp;
+
+ sprintf(shareable_bits_file, "%s/%s/shareable_bits", INFO_PATH,
+ cache_type);
+
+ fp = fopen(shareable_bits_file, "r");
+ if (!fp) {
+ perror("Failed to open shareable_bits file");
+
+ return -1;
+ }
+ if (fscanf(fp, "%lx", shareable_mask) <= 0) {
+ perror("Could not get shareable bits");
+ fclose(fp);
+
+ return -1;
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+/*
* get_core_sibling - Get sibling core id from the same socket for given CPU
* @cpu_no: CPU number
*