Commit e0be6a60 authored by Marco Perronet's avatar Marco Perronet
Browse files

Add trace-cmd libraries submodules

parent 50d53ac9
......@@ -32,7 +32,5 @@ testing/workloads/manual-input
*.pdf
*.csv
# Cloned repos
src/events_generation/binary_parser/lib/libtraceevent
src/events_generation/binary_parser/lib/libtracefs
src/events_generation/binary_parser/lib/trace-cmd
# Build output from trace-cmd's libraries
src/events_generation/binary_parser/lib/build_output
[submodule "src/events_generation/binary_parser/lib/trace-cmd"]
path = src/events_generation/binary_parser/lib/trace-cmd
url = https://github.com/cedric-courtaud/trace-cmd.git
[submodule "src/events_generation/binary_parser/lib/libtraceevent"]
path = src/events_generation/binary_parser/lib/libtraceevent
url = https://github.com/perronet/libtraceevent.git
[submodule "src/events_generation/binary_parser/lib/libtracefs"]
path = src/events_generation/binary_parser/lib/libtracefs
url = https://github.com/perronet/libtracefs.git
use std::path::Path;
use std::process::Command;
fn main() {
// Tell Cargo that if the given file changes, to rerun this build script.
......@@ -6,26 +7,31 @@ fn main() {
println!("cargo:rerun-if-changed=src/events_generation/binary_parser/stream.c");
println!("cargo:rerun-if-changed=src/events_generation/binary_parser/stream.h");
// Build a C file and statically link it.
// Compile the trace-cmd libraries.
let mut build_libs_command = Command::new("./build_libs.sh");
build_libs_command.current_dir("src/events_generation/binary_parser/lib");
build_libs_command.status().expect("Failed to build trace-cmd libraries.");
// Build our own library and statically link it to the rust binary.
cc::Build::new()
.file("src/events_generation/binary_parser/stream.c")
.file("src/events_generation/binary_parser/record.c")
.include(Path::new("/usr/local/include/traceevent"))
.include(Path::new("/usr/local/include/tracefs"))
.include(Path::new("/usr/local/include/trace-cmd"))
.flag("-ltraceevent")
.flag("-ltracefs")
.flag("-ltracecmd")
.include(Path::new("src/events_generation/binary_parser/lib/build_output/usr/include/traceevent"))
.include(Path::new("src/events_generation/binary_parser/lib/build_output/usr/include/tracefs"))
.include(Path::new("src/events_generation/binary_parser/lib/build_output/usr/include/trace-cmd"))
.flag("-Lsrc/events_generation/binary_parser/lib/build_output/usr/lib64")
.compile("binparse");
// Linker options for rustc.
println!("cargo:rustc-link-search=/usr/local/include/traceevent");
println!("cargo:rustc-link-search=/usr/local/include/tracefs");
println!("cargo:rustc-link-search=/usr/local/include/trace-cmd");
println!("cargo:rustc-link-lib=traceevent");
println!("cargo:rustc-link-lib=tracefs");
println!("cargo:rustc-link-lib=tracecmd");
// Linker options for rustc (link trace-cmd libraries).
println!("cargo:rustc-link-lib=dylib=traceevent");
println!("cargo:rustc-link-lib=dylib=tracefs");
println!("cargo:rustc-link-lib=dylib=tracecmd");
println!("cargo:rustc-link-search=native=src/events_generation/binary_parser/lib/build_output/usr/lib64");
// Without this we won't be able to find the library when running cargo run
// Note: this *only works* with cargo run
println!("cargo:rustc-env=LD_LIBRARY_PATH=src/events_generation/binary_parser/lib/build_output/usr/lib64");
// Generate bindings (reminder)
// bindgen -o src/events_generation/bindings.rs src/events_generation/binary_parser/stream.h -- -I/usr/local/include/traceevent -I/usr/local/include/tracefs -I/usr/local/include/trace-cmd
}
\ No newline at end of file
// bindgen -o src/bindings.rs src/events_generation/binary_parser/stream.h -- -I/usr/local/include/traceevent -I/usr/local/include/tracefs -I/usr/local/include/trace-cmd
}
#!/bin/bash
sudo ../target/debug/main "$@"
#!/bin/bash
sudo LD_LIBRARY_PATH=../events_generation/binary_parser/lib/build_output/usr/lib64 ../../target/debug/rbf-trace "$@"
#!/bin/bash
sudo ../../target/debug/trace-sched-event "$@"
sudo LD_LIBRARY_PATH=../events_generation/binary_parser/lib/build_output/usr/lib64 ../../target/debug/trace-sched-event "$@"
......@@ -33,9 +33,6 @@ fn main() {
target_pids = traced_pids.clone();
}
/* Tracing */
let mut evg = FTraceEVG::new(&target_pids, &traced_pids, args.ftrace_len, args.ftrace_bufsize);
let mut outputfile = None;
if let Some(ref path) = args.output {
if path.exists() {
......@@ -48,6 +45,9 @@ fn main() {
.expect("Can't initialize file.");
outputfile = Some(file);
}
/* Tracing */
let mut evg = FTraceEVG::new(&target_pids, &traced_pids, args.ftrace_len, args.ftrace_bufsize);
evg.setup();
......
all:
gcc -g -Wall -I/usr/local/include/traceevent -I/usr/local/include/tracefs -I/usr/local/include/trace-cmd -ltraceevent -ltracefs -ltracecmd -std=gnu99 stream.c bin_parser.c -o bin_parser.out
clean:
rm bin_parser.out
#include "stream.h"
// Used by each child recorder after forking. Each child has its own "recorder" instance
static struct tracecmd_recorder *recorder;
static int sleep_time = 1000;
// If true, the thread must stop (could be the main thread or a child recorder)
static int finished = 0;
void finish(int sig) {
if (recorder)
tracecmd_stop_recording(recorder); // Only executed by child recorders
finished = 1;
}
void stop_threads(struct recorder_data *recorders, int cpu_cnt) {
int ret;
int i;
struct rbftrace_event_raw *event = malloc(sizeof(*event));
/* Tell all threads to finish up */
for (i = 0; i < cpu_cnt; i++) {
if (recorders[i].pid > 0) {
kill(recorders[i].pid, SIGUSR1);
}
}
/* Flush out the pipes */
do {
ret = read_stream(recorders, cpu_cnt, event);
printf("Flushed: ");
print_event(event);
} while (ret > 0);
free(event);
}
void wait_threads(struct recorder_data *recorders, int cpu_cnt) {
int i;
for (i = 0; i < cpu_cnt; i++) {
if (recorders[i].pid > 0) {
waitpid(recorders[i].pid, NULL, 0);
recorders[i].pid = -1;
fprintf(stderr, "Waited recorder #%d\n", i);
}
}
}
/* Returns recorder pid */
// TODO shall we set real-time priority? In that case, we might need to use add_filter_pid
int create_recorder(int cpu, int *event_pipe, char *tracefs_path) {
pid_t pid;
pid = fork();
// Father
if (pid != 0)
return pid;
// Child
signal(SIGINT, SIG_IGN); // Ignore sigint
signal(SIGUSR1, finish); // Stop on sigusr
close(event_pipe[0]);
recorder = tracecmd_create_buffer_recorder_fd(event_pipe[1], cpu, TRACECMD_RECORD_BLOCK_SPLICE, tracefs_path);
tracefs_put_tracing_file(tracefs_path);
if (!recorder) {
printf("Can't create recorder\n");
exit(-1);
}
while (!finished) {
if (tracecmd_start_recording(recorder, sleep_time) < 0)
break;
}
tracecmd_free_recorder(recorder);
recorder = NULL;
exit(0);
}
void setup_ftrace(struct tracefs_instance *tracefs, int argc, char **argv) {
char pid_str[200] = "";
// Set clock (also empties the buffer)
tracefs_instance_file_write(tracefs, "trace_clock", "mono");
// Activate events
tracefs_instance_file_write(tracefs, "events/sched/sched_wakeup/enable", "1");
tracefs_instance_file_write(tracefs, "events/sched/sched_wakeup_new/enable", "1");
tracefs_instance_file_write(tracefs, "events/sched/sched_switch/enable", "1");
tracefs_instance_file_write(tracefs, "events/sched/sched_process_exit/enable", "1");
// Setup pids
if (argc > 1) {
for (int i = 1; i < argc; i++) {
strcat(pid_str, argv[i]);
strcat(pid_str, " ");
}
tracefs_instance_file_write(tracefs, "set_event_pid", pid_str);
}
}
void shutdown_ftrace(struct tracefs_instance *tracefs) {
tracefs_instance_file_write(tracefs, "tracing_on", "0");
tracefs_instance_file_write(tracefs, "set_event", "");
tracefs_instance_file_write(tracefs, "trace", ""); // Empty buffer
tracefs_instance_file_write(tracefs, "set_event_pid", "");
tracefs_instance_destroy(tracefs);
}
int main(int argc, char **argv) {
struct tracefs_instance *tracefs = tracefs_instance_create(NULL);
struct recorder_data *recorders;
struct rbftrace_event_raw *event;
char *tracefs_path = tracefs_instance_get_dir(tracefs);
int *event_pipe = NULL;
int cpu_cnt = tracecmd_count_cpus();
int ret;
int i;
setup_ftrace(tracefs, argc, argv);
if (!tracefs) {
printf("Are you using sudo?\n");
goto exit;
}
/* Stop on signal */
signal(SIGINT, finish); // TODO use SIGUSR1 in final implementation (to stop from rust)
// signal(SIGINT, SIG_IGN); // Ignore sigint
// signal(SIGUSR1, finish); // Stop on sigusr
/* Setup recorders: one for each cpu */
recorders = calloc(cpu_cnt, sizeof(*recorders));
for (i = 0; i < cpu_cnt; i++) {
/* Setup recorder */
recorders[i].cpu = i;
recorders[i].record = NULL;
event_pipe = recorders[i].event_pipe;
ret = pipe(event_pipe);
if (ret < 0) {
printf("Pipe error\n");
goto exit;
}
recorders[i].stream = init_stream(event_pipe[0], i, cpu_cnt);
if (!recorders[i].stream) {
printf("Stream error\n");
goto exit;
}
fflush(stdout);
/* Start recorder thread */
ret = create_recorder(i, event_pipe, tracefs_path);
recorders[i].pid = ret;
if (ret < 0) {
printf("Fork error\n");
goto exit;
}
if (event_pipe)
close(event_pipe[1]);
}
/* Activate tracing */
tracefs_instance_file_write(tracefs, "tracing_on", "1");
// TODO set finished if pids are dead
/* Read until "finished" is set from signal */
event = malloc(sizeof(*event));
while(!finished) {
if (read_stream(recorders, cpu_cnt, event))
print_event(event);
}
/* Stop tracing */
tracefs_instance_file_write(tracefs, "tracing_on", "0");
free(event);
stop_threads(recorders, cpu_cnt);
wait_threads(recorders, cpu_cnt);
exit:
shutdown_ftrace(tracefs);
}
#!/bin/bash
# To test the script use INSTALL_PATH=/tmp/install
mkdir -p build_output
# Clean previous output
make -C libtraceevent clean
make -C libtracefs clean
make -C trace-cmd clean
rm -rf build_output/*
CUSTOM_PATH=$(pwd)/build_output
cd libtraceevent
INSTALL_PATH="$CUSTOM_PATH" ../trace-cmd/make-trace-cmd.sh install
cd ../libtracefs
INSTALL_PATH="$CUSTOM_PATH" ../trace-cmd/make-trace-cmd.sh install
cd ../trace-cmd
INSTALL_PATH="$CUSTOM_PATH" ./make-trace-cmd.sh install_libs
cd ..
make -C libtraceevent clean
make -C libtracefs clean
make -C trace-cmd clean
#!/bin/bash
# To test the script use INSTALL_PATH=/tmp/install
git clone git://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git
git clone git://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git
git clone git://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git
make -C libtraceevent clean
make -C libtracefs clean
make -C trace-cmd clean
cd libtraceevent
PREFIX=/usr/local INSTALL_PATH=/ ../trace-cmd/make-trace-cmd.sh install
cd ../libtracefs
PREFIX=/usr/local INSTALL_PATH=/ ../trace-cmd/make-trace-cmd.sh install
cd ../trace-cmd
PREFIX=/usr/local INSTALL_PATH=/ ./make-trace-cmd.sh install_libs
# Replace the trace-cmd.h header with a custom header.
# The reason for this is that the standard header does not expose
# some of the functions that we need in the binary parser.
cd ..
cp trace-cmd-private.h /usr/local/include/trace-cmd/trace-cmd.h
make -C libtraceevent clean
make -C libtracefs clean
make -C trace-cmd clean
sudo ldconfig
Subproject commit 60db83e60b321eee516d026d84e53ed6ca6891be
Subproject commit 9539673ff83d984b0ea93e63411774bf3a6c0cd7
Subproject commit 88e1a5e1a5fec0345f51b3683564c5118004fb8e
#include "stream.h"
enum {
TRACECMD_RECORD_NOSPLICE = (1 << 0), /* Use read instead of splice */
TRACECMD_RECORD_SNAPSHOT = (1 << 1), /* Extract from snapshot */
TRACECMD_RECORD_BLOCK_SPLICE = (1 << 2), /* Block on splice write */
TRACECMD_RECORD_NOBRASS = (1 << 3), /* Splice directly without a brass pipe */
TRACECMD_RECORD_POLL = (1 << 4), /* Use O_NONBLOCK, poll trace buffers */
};
struct tracecmd_recorder;
void tracecmd_stop_recording(struct tracecmd_recorder *recorder);
struct tracecmd_recorder *tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, const char *buffer);
int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long sleep);
void tracecmd_free_recorder(struct tracecmd_recorder *recorder);
// Used by each child recorder after forking. Each child has its own "recorder" instance
static struct tracecmd_recorder *recorder;
static int sleep_time = 1000;
......
#include "stream.h"
enum tracecmd_file_states {
TRACECMD_FILE_INIT = 1,
TRACECMD_FILE_HEADERS,
TRACECMD_FILE_FTRACE_EVENTS,
TRACECMD_FILE_ALL_EVENTS,
TRACECMD_FILE_KALLSYMS,
TRACECMD_FILE_PRINTK,
TRACECMD_FILE_CMD_LINES,
TRACECMD_FILE_CPU_COUNT,
TRACECMD_FILE_OPTIONS,
TRACECMD_FILE_CPU_LATENCY,
TRACECMD_FILE_CPU_FLYRECORD,
};
// libtracecmd private
struct tracecmd_output *tracecmd_create_init_fd(int fd);
void tracecmd_output_free(struct tracecmd_output *handle);
struct tracecmd_input *tracecmd_alloc_fd(int fd, int flags);
int tracecmd_read_headers(struct tracecmd_input *handle, enum tracecmd_file_states state);
int tracecmd_make_pipe(struct tracecmd_input *handle, int cpu, int fd, int cpus);
// TODO rewrite this without these horrible static variables and gotos
struct tracecmd_input *init_stream(int read_fd, int cpu, int cpu_cnt) {
struct tracecmd_output *trace_output;
......
#!/bin/bash
# Check this:
# 1) Wakeups should be spaced by 2 seconds
# 2) Between a wakeup and switch with prev_state=S there should be 1 second
sudo echo
make
cd ../../../scripts
python3 evaluation/generate_workload.py --workload evaluation/workloads/uniprocessor_single/1_uni_single_slow.json &
sleep 1
PID=$(pgrep rtspin)
sudo ../src/events_generation/binary_parser/bin_parser.out "$PID"
# EXAMPLE WITH TRACE-CMD
# sudo trace-cmd stream -e "sched_switch" -e "sched_wakeup" -e "sched_process_exit" -P 3410
\ No newline at end of file
......@@ -130,8 +130,8 @@ impl SparseMap {
}
}
pub fn bucket_index_of(&self, cost : Duration) -> usize {
return (cost / self.bucket_size) as usize;
pub fn bucket_index_of(&self, delta : Duration) -> usize {
return (delta / self.bucket_size) as usize;
}
// Used when a new element cannot fit
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment