Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
* See if I can trigger the cache trashing issue.
*
* Use tcc to compile and run with:
* ./tcc -B. -DNOPS=0 -run cache-test-simple.c
*
* For performance metrics, try
* perf stat -d -d -d ./tcc -B. -DNOPS=0 -run cache-test-simple.c
*/
#include <stdio.h>
int foo;
void spin_wheels() {
foo = 0;
if (foo) {
#if NOPS >= 1
foo++;
#endif
#if NOPS >= 2
foo++;
#endif
#if NOPS >= 3
foo++;
#endif
#if NOPS >= 4
foo++;
#endif
#if NOPS >= 5
foo++;
#endif
#if NOPS >= 6
foo++;
#endif
#if NOPS >= 7
foo++;
#endif
#if NOPS >= 8
foo++;
#endif
#if NOPS >= 9
foo++;
#endif
#if NOPS >= 10
foo++;
#endif
#if NOPS >= 11
foo++;
#endif
#if NOPS >= 12
foo++;
#endif
#if NOPS >= 13
foo++;
#endif
#if NOPS >= 14
foo++;
#endif
#if NOPS >= 15
foo++;
#endif
#if NOPS >= 16
foo++;
#endif
}
foo++;
}
#include <stdio.h>
int main(int argc, char **argv)
{
/* perform the requested number of iterations */
for (int i = 0; i < 10000000; i++) spin_wheels();
return 0;
}
/*
* See if I can trigger the cache trashing issue.
*
* Compile with
* gcc cache-test.c -L. -ltcc -ldl -o cache-test
*
* Run as
* ./cache-test mem 30 50000000
* or, for performance metrics, try
* perf stat -d -d -d ./cache-test mem 30 50000000
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libtcc.h"
void setup_paths(TCCState * state, char **argv);
int setup_link_process(TCCState * state, char **argv);
char * generate_library_code(int N_commands);
void make_library(TCCState * state, int link_process, char *code_to_emit);
void * get_wheels_ptr(TCCState * state, int link_process);
int main(int argc, char **argv)
{
/* Print usage error statement */
if (argc != 4) {
printf("Usage: %s <mem|so> <N-commands> <N-iterations>\n",
argv[0]);
return 1;
}
/* Set up compiler for 'library' code */
TCCState *s = tcc_new();
setup_paths(s, argv);
int link_process = setup_link_process(s, argv);
/* Assemble library code */
int N_commands = atoi(argv[2]);
char * code_to_compile = generate_library_code(N_commands);
//printf("code to compile:\n%s\n", code_to_compile);
make_library(s, link_process, code_to_compile);
void (*spin_wheels)() = get_wheels_ptr(s, link_process);
/* perform the requested number of iterations */
int i, N_iterations = atoi(argv[3]);
for (i = 0; i < N_iterations; i++) spin_wheels();
return 0;
}
/* use the current directory as the lib path so this will work with
* whatever is being built at the moment. */
void setup_paths(TCCState * state, char **argv) {
tcc_set_lib_path(state, ".");
}
int setup_link_process(TCCState * state, char **argv) {
int output_type = TCC_OUTPUT_MEMORY;
if (strcmp(argv[1], "so") == 0) output_type = TCC_OUTPUT_DLL;
else if (strcmp(argv[1], "mem") != 0) {
printf("Invalid output type '%s'\n", argv[1]);
printf("Usage: %s <mem|so> <N-commands> <N-iterations>\n",
argv[0]);
exit(1);
}
tcc_set_output_type(state, output_type);
return output_type;
}
/* produces a function for the library with the specified number of
* commands in the body of the function. */
char header[] = "int i; void spin_wheels() {i = 0; if (i) {";
char footer[] = "} i++; }";
char * ops[] = {
"i++;",
"i--;",
};
#define OP_LENGTH 4
char * generate_library_code(int N_commands) {
/* compute length and allocate */
int total_length = sizeof(header) + N_commands * OP_LENGTH
+ sizeof(footer) - 1;
char * to_return = malloc(total_length);
char * curr_offset = to_return + sizeof(header) - 1;
/* set header */
strcpy(to_return, header);
/* assemble operations */
for (int i = 0; i < N_commands; i++) {
strcpy(curr_offset, ops[i % 2]);
curr_offset += OP_LENGTH;
}
/* closing bracket and trailing null */
strcpy(curr_offset, footer);
curr_offset[sizeof(footer)] = '\0';
return to_return;
}
void make_library(TCCState * state, int link_process, char *code_to_compile) {
tcc_compile_string(state, code_to_compile);
if (link_process == TCC_OUTPUT_MEMORY) {
printf("Code bytes: %d\n", tcc_relocate(state, 0));
tcc_relocate(state, TCC_RELOCATE_AUTO);
}
else {
tcc_output_file(state, "cache-test.so");
}
}
#include <dlfcn.h>
void * get_wheels_ptr(TCCState * state, int link_process) {
if (link_process == TCC_OUTPUT_MEMORY) {
return tcc_get_symbol(state, "spin_wheels");
}
void * lib = dlopen("./cache-test.so", RTLD_NOW);
return dlsym(lib, "spin_wheels");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment