├── .gitignore ├── mitos-config.cmake ├── examples ├── CMakeLists.txt ├── matmul.cpp ├── api_test.cpp └── mpi_matmul.cpp ├── src ├── CMakeLists.txt ├── x86_util.h ├── hwloc_dump.h ├── mattr.h ├── Mitos.cpp ├── mattr.cpp ├── perfsmpl.h ├── Mitos.h ├── mitosrun.cpp ├── mitosoutput.cpp └── perfsmpl.cpp ├── CMakeLists.txt ├── NOTICE ├── cmake └── FindPerfEvents.cmake ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | *.swp 4 | 5 | build/ 6 | -------------------------------------------------------------------------------- /mitos-config.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 2 | include(${SELF_DIR}/mitos-targets.cmake) 3 | get_filename_component(Mitos_INCLUDE_DIRS 4 | "${SELF_DIR}/../../include/Mitos" ABSOLUTE) 5 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${MPI_INCLUDE_PATH}) 2 | include_directories(${DYNINST_INCLUDE_DIR}) 3 | include_directories("..") 4 | 5 | set(CMAKE_BUILD_TYPE Debug) 6 | 7 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") 8 | 9 | add_executable(api_test api_test.cpp) 10 | add_executable(matmul matmul.cpp) 11 | add_executable(mpi_matmul mpi_matmul.cpp) 12 | 13 | target_link_libraries(api_test mitos symtabAPI) 14 | target_link_libraries(mpi_matmul ${MPI_LIBRARIES}) 15 | 16 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Include dirs required 2 | include_directories(${DYNINST_INCLUDE_DIR}) 3 | 4 | # Source and header files 5 | set(MITOS_SRC_FILES perfsmpl.cpp mattr.cpp mitosoutput.cpp Mitos.cpp) 6 | set(MITOS_HDR_FILES perfsmpl.h mattr.h Mitos.h) 7 | set(MITOS_HDR_PUBLIC Mitos.h) 8 | 9 | # Libraries (created) 10 | add_library(mitos SHARED ${MITOS_SRC_FILES}) 11 | 12 | # Binaries 13 | add_executable(mitosrun mitosrun.cpp) 14 | 15 | # Linkage 16 | target_link_libraries(mitos hwloc symtabAPI instructionAPI parseAPI ${CMAKE_THREAD_LIBS_INIT}) 17 | target_link_libraries(mitosrun mitos) 18 | 19 | # Install 20 | install(FILES ${MITOS_HDR_PUBLIC} 21 | DESTINATION "include/Mitos") 22 | install(TARGETS mitosrun 23 | EXPORT mitos-targets 24 | DESTINATION bin) 25 | install(TARGETS mitos 26 | EXPORT mitos-targets 27 | DESTINATION lib) 28 | 29 | -------------------------------------------------------------------------------- /src/x86_util.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | #include 9 | #include 10 | #include 11 | using namespace Dyninst; 12 | using namespace InstructionAPI; 13 | 14 | size_t getReadSize(Instruction::Ptr ins) 15 | { 16 | // Get all read operands and their expressions 17 | vector opds; 18 | ins->getOperands(opds); 19 | set memAccessors; 20 | for(int i=0; i::iterator it; 31 | for(it=memAccessors.begin(); it!=memAccessors.end(); it++) 32 | { 33 | readsz += (*it)->size(); 34 | } 35 | return readsz; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/hwloc_dump.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int dump_hardware_xml(const char *filename) 4 | { 5 | int err; 6 | unsigned long flags = 0; // don't show anything special 7 | hwloc_topology_t topology; 8 | 9 | err = hwloc_topology_init(&topology); 10 | if(err) 11 | { 12 | std::cerr << "hwloc: Failed to initialize" << std::endl; 13 | return 1; 14 | } 15 | 16 | err = hwloc_topology_set_flags(topology, flags); 17 | if(err) 18 | { 19 | std::cerr << "hwloc: Failed to set flags" << std::endl; 20 | return 1; 21 | } 22 | 23 | err = hwloc_topology_load (topology); 24 | if(err) 25 | { 26 | std::cerr << "hwloc: Failed to load topology" << std::endl; 27 | return 1; 28 | } 29 | 30 | err = hwloc_topology_export_xml(topology, "hardware.xml"); 31 | if(err) 32 | { 33 | std::cerr << "hwloc: Failed to export xml" << std::endl; 34 | return 1; 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(Mitos C CXX) 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | # Version info 5 | set(MITOS_MAJOR_VERSION 0) 6 | set(MITOS_MINOR_VERSION 8) 7 | set(MITOS_PATCH_VERSION 1) 8 | set(MITOS_VERSION ${MITOS_MAJOR_VERSION}.${MITOS_MINOR_VERSION}.${MITOS_PATCH_VERSION}) 9 | 10 | # Included cmake files 11 | set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") 12 | 13 | # Packages required 14 | find_package(Threads REQUIRED) 15 | find_package(PerfEvents REQUIRED) 16 | find_package(MPI REQUIRED) 17 | find_package(Boost REQUIRED) 18 | find_package(Dyninst REQUIRED SymtabAPI InstructionAPI ParseAPI) 19 | find_package(OpenMP) 20 | 21 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 22 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 23 | 24 | # Subdirectories 25 | add_subdirectory(src) 26 | add_subdirectory(examples) 27 | 28 | # Export the package 29 | export(PACKAGE Mitos) 30 | 31 | # Install cmake export 32 | install(EXPORT mitos-targets DESTINATION lib/Mitos) 33 | install(FILES mitos-config.cmake DESTINATION lib/Mitos) 34 | 35 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of 2 | Energy by Lawrence Livermore National Laboratory under Contract 3 | DE-AC52-07NA27344. 4 | 5 | This work was prepared as an account of work sponsored by an agency of 6 | the United States Government. Neither the United States Government nor 7 | Lawrence Livermore National Security, LLC, nor any of their employees 8 | makes any warranty, expressed or implied, or assumes any legal liability 9 | or responsibility for the accuracy, completeness, or usefulness of any 10 | information, apparatus, product, or process disclosed, or represents that 11 | its use would not infringe privately owned rights. 12 | 13 | Reference herein to any specific commercial product, process, or service 14 | by trade name, trademark, manufacturer, or otherwise does not necessarily 15 | constitute or imply its endorsement, recommendation, or favoring by the 16 | United States Government or Lawrence Livermore National Security, LLC. 17 | 18 | The views and opinions of authors expressed herein do not necessarily 19 | state or reflect those of the United States Government or Lawrence 20 | Livermore National Security, LLC, and shall not be used for advertising 21 | or product endorsement purposes. 22 | -------------------------------------------------------------------------------- /examples/matmul.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #define ROW_MAJOR(x,y,width) y*width+x 7 | 8 | void init_matrices(int N, double **a, double **b, double **c) 9 | { 10 | int i,j,k; 11 | 12 | *a = new double[N*N]; 13 | *b = new double[N*N]; 14 | *c = new double[N*N]; 15 | 16 | for(i=0; i 27 | #include 28 | 29 | int main(int argc, char **argv) { 30 | printf(\"PERF_SAMPLE_WEIGHT is %d\", PERF_SAMPLE_WEIGHT); 31 | printf(\"PERF_SAMPLE_DATA_SRC is %d\", PERF_SAMPLE_DATA_SRC); 32 | printf(\"PERF_COUNT_SW_DUMMY is %d\", PERF_COUNT_SW_DUMMY); 33 | }" 34 | HAVE_PERF_EVENT_MEM_SAMPLING) 35 | 36 | # Make sure all these checks are true and set PerfEvents_FOUND accordingly. 37 | find_package_handle_standard_args(PerfEvents 38 | FAIL_MESSAGE "ERROR: Need a kernel with perf_events support for memory sampling." 39 | REQUIRED_VARS HAVE_PERF_PARANOID HAVE_PERF_EVENT_H HAVE_PERF_EVENT_MEM_SAMPLING) 40 | 41 | -------------------------------------------------------------------------------- /src/mattr.h: -------------------------------------------------------------------------------- 1 | #ifndef MATTR_H 2 | #define MATTR_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | class mem_symbol; 11 | class mem_symbol_splay_tree; 12 | class mattr; 13 | 14 | class mem_symbol 15 | { 16 | friend class mem_symbol_splay_tree; 17 | 18 | public: 19 | mem_symbol(); 20 | mem_symbol(const char* n, uint64_t a, size_t s, size_t *d, unsigned int nd); 21 | ~mem_symbol(); 22 | 23 | bool contains(uint64_t addr); 24 | 25 | public: 26 | char* get_name() {return name;} 27 | uint64_t get_addr() {return addr;} 28 | size_t get_sz() {return sz;} 29 | size_t get_len() {return len;} 30 | unsigned int get_num_dims() {return num_dims;} 31 | 32 | void get_index(uint64_t a, size_t *d); 33 | 34 | private: 35 | char* name; 36 | uint64_t addr; 37 | size_t sz; 38 | size_t len; 39 | size_t *dims; 40 | unsigned int num_dims; 41 | }; 42 | 43 | class mem_symbol_splay_tree 44 | { 45 | 46 | public: 47 | mem_symbol_splay_tree(); 48 | ~mem_symbol_splay_tree(); 49 | 50 | void insert(mem_symbol m); 51 | void remove(mem_symbol m); 52 | mem_symbol* find_container(uint64_t addr); 53 | std::vector::iterator find_container_itr(uint64_t addr); 54 | private: 55 | std::vector all_mem_symbols; 56 | }; 57 | 58 | class mattr 59 | { 60 | public: 61 | mattr(); 62 | ~mattr(); 63 | 64 | void add_symbol(mem_symbol m); 65 | void add_symbol(const char* n, void *a, size_t s, size_t *d, unsigned int nd); 66 | void add_symbol_vec(std::vector &v); 67 | 68 | mem_symbol* find_symbol(uint64_t addr) { return syms.find_container(addr); } 69 | 70 | private: 71 | mem_symbol_splay_tree syms; 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /examples/api_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../src/Mitos.h" 7 | 8 | mitos_output mout; 9 | 10 | #include 11 | 12 | void sample_handler(perf_event_sample *sample, void *args) 13 | { 14 | Mitos_write_sample(sample, &mout); 15 | } 16 | 17 | #define ROW_MAJOR(x,y,width) y*width+x 18 | 19 | void init_matrices(int N, double **a, double **b, double **c) 20 | { 21 | int i,j,k; 22 | 23 | *a = new double[N*N]; 24 | *b = new double[N*N]; 25 | *c = new double[N*N]; 26 | 27 | size_t dims[2] = {N,N}; 28 | Mitos_add_symbol("a",*a,sizeof(double),dims,2); 29 | Mitos_add_symbol("b",*b,sizeof(double),dims,2); 30 | Mitos_add_symbol("c",*c,sizeof(double),dims,2); 31 | 32 | for(i=0; iaddr); 57 | if(m) 58 | { 59 | s->data_size = m->get_sz(); 60 | s->num_dims = m->get_num_dims(); 61 | s->data_symbol = m->get_name(); 62 | 63 | m->get_index(s->addr, s->access_index); 64 | } 65 | else 66 | { 67 | s->data_size = 0; 68 | s->num_dims = 1; 69 | s->access_index[0] = 0; 70 | s->access_index[1] = 0; 71 | s->access_index[2] = 0; 72 | s->data_symbol = "??"; 73 | } 74 | } 75 | 76 | long Mitos_x_index(struct perf_event_sample *s) 77 | { 78 | if(s->access_index) 79 | { 80 | if(s->num_dims > 0) 81 | return s->access_index[0]; 82 | else 83 | return 0; 84 | } 85 | return -1; 86 | } 87 | 88 | long Mitos_y_index(struct perf_event_sample *s) 89 | { 90 | if(s->access_index) 91 | { 92 | if(s->num_dims > 1) 93 | return s->access_index[1]; 94 | else 95 | return 0; 96 | } 97 | return -1; 98 | } 99 | 100 | long Mitos_z_index(struct perf_event_sample *s) 101 | { 102 | if(s->access_index) 103 | { 104 | if(s->num_dims > 2) 105 | return s->access_index[2]; 106 | else 107 | return 0; 108 | } 109 | return -1; 110 | } 111 | -------------------------------------------------------------------------------- /src/mattr.cpp: -------------------------------------------------------------------------------- 1 | #include "mattr.h" 2 | 3 | #include 4 | #include 5 | 6 | mem_symbol::mem_symbol() 7 | { 8 | 9 | } 10 | 11 | mem_symbol::mem_symbol(const char* n, uint64_t a, size_t s, size_t *d, unsigned int nd) 12 | : 13 | addr(a), 14 | sz(s), 15 | num_dims(nd) 16 | { 17 | name = strdup(n); 18 | dims = (size_t*)malloc(sizeof(size_t)*num_dims); 19 | 20 | len = 1; 21 | for(int i=0; iaddr <= addr && addr < this->addr+sz*len; 36 | } 37 | 38 | void mem_symbol::get_index(uint64_t a, size_t *d) 39 | { 40 | unsigned int idx = (a-addr)/sz; 41 | 42 | for(int i=0; i::iterator r; 68 | r = find_container_itr(m.addr); 69 | all_mem_symbols.erase(r); 70 | } 71 | 72 | mem_symbol* mem_symbol_splay_tree::find_container(uint64_t addr) 73 | { 74 | std::vector::iterator r; 75 | r = find_container_itr(addr); 76 | if(r == all_mem_symbols.end()) 77 | return NULL; 78 | return (mem_symbol*)&(*r); 79 | } 80 | 81 | std::vector::iterator 82 | mem_symbol_splay_tree::find_container_itr(uint64_t addr) 83 | { 84 | std::vector::iterator r; 85 | for(r=all_mem_symbols.begin();rcontains(addr)) 88 | return r; 89 | } 90 | return all_mem_symbols.end(); 91 | } 92 | 93 | mattr::mattr() 94 | { 95 | 96 | } 97 | 98 | mattr::~mattr() 99 | { 100 | 101 | } 102 | 103 | void mattr::add_symbol(mem_symbol m) 104 | { 105 | syms.insert(m); 106 | } 107 | 108 | void mattr::add_symbol(const char* n, void *a, size_t s, size_t *d, unsigned int nd) 109 | { 110 | uint64_t addr = (uint64_t)a; 111 | syms.insert(mem_symbol(n,addr,s,d,nd)); 112 | } 113 | 114 | void mattr::add_symbol_vec(std::vector &v) 115 | { 116 | for(size_t i=0; i 58 | hardware.xml 59 | ``` 60 | 61 | Where `samples.csv` contains a comma-separated list of memory 62 | samples, hardware.xml describes the hardware topology (using hwloc) 63 | and src is an empty directory where you can put the program source 64 | files for use in MemAxes. 65 | 66 | `mitosrun` can also be fine-tuned with the following parameters: 67 | 68 | ``` 69 | [options]: 70 | -b sample buffer size (default 4096) 71 | -p sample period (default 4000) 72 | -t sample latency threshold (default 10) 73 | ``` 74 | 75 | # Authors 76 | 77 | Mitos and MemAxes were originally written by Alfredo Gimenez. 78 | 79 | Thanks to Todd Gamblin for suggestions and for giving Mitos a proper build setup. 80 | 81 | # License 82 | 83 | Mitos is distributed under the Apache-2.0 license with the LLVM exception. 84 | All new contributions must be made under this license. Copyrights and patents 85 | in the Mitos project are retained by contributors. No copyright assignment is 86 | required to contribute to Mitos. 87 | 88 | See [LICENSE](https://github.com/llnl/mitos/blob/develop/LICENSE) and 89 | [NOTICE](https://github.com/llnl/mitos/blob/develop/NOTICE) for details. 90 | 91 | SPDX-License-Identifier: (Apache-2.0 WITH LLVM-exception) 92 | 93 | `LLNL-CODE-838491` 94 | -------------------------------------------------------------------------------- /src/perfsmpl.h: -------------------------------------------------------------------------------- 1 | #ifndef PERFSMPL_H 2 | #define PERFSMPL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Mitos.h" 21 | 22 | class perfsmpl 23 | { 24 | friend class perf_event_sample; 25 | friend void signal_thread_handler(int sig, siginfo_t *info, void *extra); 26 | 27 | public: 28 | perfsmpl(); 29 | ~perfsmpl(); 30 | 31 | int prepare(pid_t PID); 32 | 33 | int begin_sampler(); 34 | void end_sampler(); 35 | 36 | void set_sample_mode(sample_mode m) { mode = m; } 37 | void set_sample_period(uint64_t p) { sample_period = p; } 38 | void set_sample_threshold(uint64_t t) { sample_threshold = t; } 39 | 40 | void set_handler_fn(sample_handler_fn_t h, void* args) { handler_fn = h; handler_fn_args = args; handler_fn_defined = 1; } 41 | void set_end_fn(end_fn_t h, void* args) { end_fn = h; end_fn_args = args; end_fn_defined = 1; } 42 | 43 | inline bool has_attribute(int attr) { return this->pe.sample_type & attr; } 44 | 45 | private: 46 | void init_attr(); 47 | int init_perf(); 48 | int init_sighandler(); 49 | 50 | int process_sample_buffer(); 51 | int process_single_sample(struct perf_event_mmap_page *mmap_buf); 52 | 53 | int read_mmap_buffer(struct perf_event_mmap_page *mmap_buf, char *out, size_t sz); 54 | void skip_mmap_buffer(struct perf_event_mmap_page *mmap_buf, size_t sz); 55 | 56 | void process_lost_sample(struct perf_event_mmap_page *mmap_buf); 57 | void process_freq_sample(struct perf_event_mmap_page *mmap_buf); 58 | void process_exit_sample(struct perf_event_mmap_page *mmap_buf); 59 | 60 | private: 61 | // status 62 | int ret; 63 | int ready; 64 | int stop; 65 | 66 | int mode; 67 | 68 | // perf_event variables 69 | int fd; 70 | pid_t mPID; 71 | struct perf_event_mmap_page *mmap_buf; 72 | perf_event_sample pes; 73 | uint64_t counter_value; 74 | 75 | // event_attr variables 76 | struct perf_event_attr pe; 77 | 78 | uint64_t sample_period; 79 | uint64_t sample_threshold; 80 | uint64_t sample_type; 81 | 82 | size_t mmap_pages; 83 | size_t mmap_size; 84 | size_t pgsz; 85 | size_t pgmsk; 86 | 87 | uint64_t collected_samples; 88 | uint64_t lost_samples; 89 | 90 | pthread_t sample_reader_thr; 91 | 92 | sample_handler_fn_t handler_fn; 93 | void *handler_fn_args; 94 | int handler_fn_defined; 95 | 96 | end_fn_t end_fn; 97 | void *end_fn_args; 98 | int end_fn_defined; 99 | }; 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/Mitos.h: -------------------------------------------------------------------------------- 1 | #ifndef MITOS_H 2 | #define MITOS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct mem_symbol; 10 | struct perf_event_sample; 11 | struct mitos_output; 12 | 13 | typedef void (*sample_handler_fn_t)(struct perf_event_sample *sample, void *args); 14 | typedef void (*end_fn_t)(void *args); 15 | 16 | enum sample_mode 17 | { 18 | SMPL_MEMORY, 19 | SMPL_INSTRUCTIONS 20 | }; 21 | 22 | /* 23 | * Mitos: 24 | * All programs must invoke from these functions. 25 | */ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | // Sampler configuration 32 | void Mitos_set_sample_mode(enum sample_mode m); 33 | void Mitos_set_sample_period(uint64_t p); 34 | void Mitos_set_sample_threshold(uint64_t t); 35 | void Mitos_set_handler_fn(sample_handler_fn_t h, void *args); 36 | void Mitos_set_end_fn(end_fn_t h, void *args); 37 | 38 | // Sampler invocation 39 | void Mitos_prepare(pid_t pid); 40 | void Mitos_begin_sampler(); 41 | void Mitos_end_sampler(); 42 | 43 | // Memory attribution 44 | void Mitos_add_symbol(const char* n, void *a, size_t s, size_t *dims, unsigned int ndims); 45 | void Mitos_resolve_symbol(struct perf_event_sample *s); 46 | 47 | // Get friendly sample information 48 | long Mitos_x_index(struct perf_event_sample *s); 49 | long Mitos_y_index(struct perf_event_sample *s); 50 | long Mitos_z_index(struct perf_event_sample *s); 51 | const char* Mitos_hit_type(struct perf_event_sample *s); 52 | const char* Mitos_data_source(struct perf_event_sample *s); 53 | 54 | // Output 55 | int Mitos_create_output(mitos_output *mout); 56 | int Mitos_pre_process(mitos_output *mout); 57 | int Mitos_write_sample(perf_event_sample *s, mitos_output *mout); 58 | int Mitos_post_process(char *bin_name, mitos_output *mout); 59 | 60 | #ifdef __cplusplus 61 | } // extern "C" 62 | #endif 63 | 64 | /* 65 | * perf_event_sample: 66 | * Struct containing all raw perf event information 67 | */ 68 | 69 | struct perf_event_sample 70 | { 71 | //struct perf_event_header header; 72 | uint64_t sample_id; /* if PERF_SAMPLE_IDENTIFIER */ 73 | uint64_t ip; /* if PERF_SAMPLE_IP */ 74 | uint32_t pid, tid; /* if PERF_SAMPLE_TID */ 75 | uint64_t time; /* if PERF_SAMPLE_TIME */ 76 | uint64_t addr; /* if PERF_SAMPLE_ADDR */ 77 | uint64_t id; /* if PERF_SAMPLE_ID */ 78 | uint64_t stream_id; /* if PERF_SAMPLE_STREAM_ID */ 79 | uint32_t cpu, res; /* if PERF_SAMPLE_CPU */ 80 | uint64_t period; /* if PERF_SAMPLE_PERIOD */ 81 | //struct read_format v; /* if PERF_SAMPLE_READ */ 82 | uint64_t nr; /* if PERF_SAMPLE_CALLCHAIN */ 83 | uint64_t *ips; /* if PERF_SAMPLE_CALLCHAIN */ 84 | uint32_t raw_size; /* if PERF_SAMPLE_RAW */ 85 | char *raw_data; /* if PERF_SAMPLE_RAW */ 86 | uint64_t bnr; /* if PERF_SAMPLE_BRANCH_STACK */ 87 | //struct perf_branch_entry *lbr; /* if PERF_SAMPLE_BRANCH_STACK */ 88 | uint64_t abi; /* if PERF_SAMPLE_REGS_USER */ 89 | uint64_t *regs; /* if PERF_SAMPLE_REGS_USER */ 90 | uint64_t stack_size; /* if PERF_SAMPLE_STACK_USER */ 91 | char *stack_data; /* if PERF_SAMPLE_STACK_USER */ 92 | uint64_t dyn_size; /* if PERF_SAMPLE_STACK_USER */ 93 | uint64_t weight; /* if PERF_SAMPLE_WEIGHT */ 94 | uint64_t data_src; /* if PERF_SAMPLE_DATA_SRC */ 95 | uint64_t transaction; /* if PERF_SAMPLE_TRANSACTION */ 96 | 97 | size_t data_size; 98 | size_t num_dims; 99 | size_t access_index[3]; 100 | const char *data_symbol; 101 | }; 102 | 103 | struct mitos_output 104 | { 105 | mitos_output() 106 | { memset(this,0,sizeof(this)); ok=false; } 107 | 108 | bool ok; 109 | 110 | char *dname_topdir; 111 | char *dname_datadir; 112 | char *dname_srcdir; 113 | 114 | char *fname_raw; 115 | char *fname_processed; 116 | 117 | FILE *fout_raw; 118 | FILE *fout_processed; 119 | }; 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /src/mitosrun.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Mitos.h" 11 | 12 | size_t bufsz; 13 | uint64_t period; 14 | uint64_t thresh; 15 | 16 | #define DEFAULT_BUFSZ 4096 17 | #define DEFAULT_THRESH 10 18 | #define DEFAULT_PERIOD 4000 19 | 20 | mitos_output mout; 21 | std::vector samples; 22 | 23 | void dump_samples() 24 | { 25 | for(size_t i=0; i= bufsz) 35 | dump_samples(); 36 | } 37 | 38 | void usage(char **argv) 39 | { 40 | std::cerr << "Usage:" << std::endl; 41 | std::cerr << argv[0] << " [options] [args]" << std::endl; 42 | std::cerr << " [options]:" << std::endl; 43 | std::cerr << " -b sample buffer size (default 4096)" << std::endl; 44 | std::cerr << " -p sample period (default 4000)" << std::endl; 45 | std::cerr << " -t sample latency threshold (default 10)" << std::endl; 46 | std::cerr << " : command to sample on (required)" << std::endl; 47 | std::cerr << " [args]: command arguments" << std::endl; 48 | } 49 | 50 | void set_defaults() 51 | { 52 | bufsz = DEFAULT_BUFSZ; 53 | period = DEFAULT_PERIOD; 54 | thresh = DEFAULT_THRESH; 55 | } 56 | 57 | int parse_args(int argc, char **argv) 58 | { 59 | set_defaults(); 60 | 61 | int c; 62 | while((c=getopt(argc, argv, "b:p:t:")) != -1) 63 | { 64 | switch(c) 65 | { 66 | case 'b': 67 | bufsz = atoi(optarg); 68 | break; 69 | case 'p': 70 | period = atoi(optarg); 71 | break; 72 | case 't': 73 | thresh = atoi(optarg); 74 | break; 75 | case '?': 76 | usage(argv); 77 | return 1; 78 | default: 79 | abort(); 80 | } 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | int findCmdArgId(int argc, char **argv) 87 | { 88 | // case 1: argv[0] -f1000 cmd 89 | // case 2: argv[0] -f 1000 cmd 90 | int cmdarg = -1; 91 | bool isarg = false; 92 | for(int i=1; i 2) 104 | isarg = false; 105 | else 106 | isarg = true; 107 | } 108 | } 109 | return cmdarg; 110 | } 111 | 112 | int main(int argc, char **argv) 113 | { 114 | int cmdarg = findCmdArgId(argc,argv); 115 | 116 | if(cmdarg == -1) 117 | { 118 | usage(argv); 119 | return 1; 120 | } 121 | 122 | if(parse_args(cmdarg,argv)) 123 | return 1; 124 | 125 | pid_t child = fork(); 126 | 127 | if(child == 0) 128 | { 129 | ptrace(PTRACE_TRACEME,0,0,0); 130 | int err = execvp(argv[cmdarg],&argv[cmdarg]); 131 | if(err) 132 | { 133 | perror("execvp"); 134 | } 135 | } 136 | else if(child < 0) 137 | { 138 | std::cerr << "Error forking!" << std::endl; 139 | } 140 | else 141 | { 142 | int status; 143 | wait(&status); 144 | 145 | int err = Mitos_create_output(&mout); 146 | if(err) 147 | { 148 | kill(child, SIGKILL); 149 | return 1; 150 | } 151 | 152 | err = Mitos_pre_process(&mout); 153 | if(err) 154 | { 155 | kill(child, SIGKILL); 156 | return 1; 157 | } 158 | 159 | Mitos_set_sample_mode(SMPL_MEMORY); 160 | 161 | Mitos_set_sample_period(period); 162 | Mitos_set_sample_threshold(thresh); 163 | 164 | Mitos_set_handler_fn(&sample_handler,NULL); 165 | 166 | Mitos_prepare(child); 167 | 168 | Mitos_begin_sampler(); 169 | { 170 | ptrace(PTRACE_CONT,child,0,0); 171 | 172 | // Wait until process exits 173 | do { wait(&status); } 174 | while(!WIFEXITED(status)); 175 | } 176 | Mitos_end_sampler(); 177 | 178 | dump_samples(); // anything left over 179 | 180 | std::cout << "Command completed! Processing samples...\n" << std::endl; 181 | 182 | err = Mitos_post_process(argv[cmdarg],&mout); 183 | if(err) 184 | return 1; 185 | 186 | std::cout << "Done!\n" << std::endl; 187 | } 188 | 189 | return 0; 190 | } 191 | -------------------------------------------------------------------------------- /examples/mpi_matmul.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * FILE: mpi_mm.c 3 | * * DESCRIPTION: 4 | * * MPI Matrix Multiply - C Version 5 | * * In this code, the master task distributes a matrix multiply 6 | * * operation to numtasks-1 worker tasks. 7 | * * NOTE: C and Fortran versions of this code differ because of the way 8 | * * arrays are stored/passed. C arrays are row-major order but Fortran 9 | * * arrays are column-major order. 10 | * * AUTHOR: Blaise Barney. Adapted from Ros Leibensperger, Cornell Theory 11 | * * Center. Converted to MPI: George L. Gusciora, MHPCC (1/95) 12 | * * LAST REVISED: 04/13/05 13 | * ******************************************************************************/ 14 | #include "mpi.h" 15 | #include 16 | #include 17 | 18 | #define NRA 1024 /* number of rows in matrix A */ 19 | #define NCA 1024 /* number of columns in matrix A */ 20 | #define NCB 512 /* number of columns in matrix B */ 21 | #define MASTER 0 /* taskid of first task */ 22 | #define FROM_MASTER 1 /* setting a message type */ 23 | #define FROM_WORKER 2 /* setting a message type */ 24 | 25 | int main (int argc, char *argv[]) 26 | { 27 | int numtasks, /* number of tasks in partition */ 28 | taskid, /* a task identifier */ 29 | numworkers, /* number of worker tasks */ 30 | source, /* task id of message source */ 31 | dest, /* task id of message destination */ 32 | mtype, /* message type */ 33 | rows, /* rows of matrix A sent to each worker */ 34 | averow, extra, offset, /* used to determine rows sent to each worker */ 35 | i, j, k, rc; /* misc */ 36 | double a[NRA][NCA], /* matrix A to be multiplied */ 37 | b[NCA][NCB], /* matrix B to be multiplied */ 38 | c[NRA][NCB]; /* result matrix C */ 39 | MPI_Status status; 40 | 41 | MPI_Init(&argc,&argv); 42 | MPI_Comm_rank(MPI_COMM_WORLD,&taskid); 43 | MPI_Comm_size(MPI_COMM_WORLD,&numtasks); 44 | if (numtasks < 2 ) { 45 | fprintf(stderr,"Need at least two MPI tasks. Quitting...\n"); 46 | MPI_Abort(MPI_COMM_WORLD, rc); 47 | exit(1); 48 | } 49 | numworkers = numtasks-1; 50 | 51 | 52 | /**************************** master task ************************************/ 53 | if (taskid == MASTER) 54 | { 55 | printf("mpi_mm has started with %d tasks.\n",numtasks); 56 | printf("Initializing arrays...\n"); 57 | for (i=0; i MASTER) 111 | { 112 | mtype = FROM_MASTER; 113 | MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status); 114 | MPI_Recv(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status); 115 | MPI_Recv(&a, rows*NCA, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status); 116 | MPI_Recv(&b, NCA*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status); 117 | 118 | for (k=0; k 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include // symtabAPI 10 | #include // parseAPI 11 | #include // instructionAPI 12 | using namespace Dyninst; 13 | using namespace SymtabAPI; 14 | using namespace ParseAPI; 15 | using namespace InstructionAPI; 16 | 17 | #include "hwloc_dump.h" 18 | #include "x86_util.h" 19 | 20 | #include "Mitos.h" 21 | 22 | int Mitos_create_output(mitos_output *mout) 23 | { 24 | // Set top directory name 25 | std::stringstream ss_dname_topdir; 26 | ss_dname_topdir << "mitos_" << std::time(NULL); 27 | mout->dname_topdir = strdup(ss_dname_topdir.str().c_str()); 28 | 29 | // Set data directory name 30 | std::stringstream ss_dname_datadir; 31 | ss_dname_datadir << ss_dname_topdir.str() << "/data"; 32 | mout->dname_datadir = strdup(ss_dname_datadir.str().c_str()); 33 | 34 | // Set src directory name 35 | std::stringstream ss_dname_srcdir; 36 | ss_dname_srcdir << ss_dname_topdir.str() << "/src"; 37 | mout->dname_srcdir = strdup(ss_dname_srcdir.str().c_str()); 38 | 39 | // Create the directories 40 | int err; 41 | err = mkdir(mout->dname_topdir,0777); 42 | err |= mkdir(mout->dname_datadir,0777); 43 | err |= mkdir(mout->dname_srcdir,0777); 44 | 45 | if(err) 46 | { 47 | std::cerr << "Mitos: Failed to create output directories!\n"; 48 | return 1; 49 | } 50 | 51 | // Create file for raw sample output 52 | mout->fname_raw = strdup(std::string(std::string(mout->dname_datadir) + "/raw_samples.csv").c_str()); 53 | mout->fout_raw = fopen(mout->fname_raw,"w"); 54 | if(!mout->fout_raw) 55 | { 56 | std::cerr << "Mitos: Failed to create raw output file!\n"; 57 | return 1; 58 | } 59 | 60 | // Create file for processed sample output 61 | mout->fname_processed = strdup(std::string(std::string(mout->dname_datadir) + "/samples.csv").c_str()); 62 | mout->fout_processed = fopen(mout->fname_processed,"w"); 63 | if(!mout->fout_processed) 64 | { 65 | std::cerr << "Mitos: Failed to create processed output file!\n"; 66 | return 1; 67 | } 68 | 69 | mout->ok = true; 70 | 71 | return 0; 72 | } 73 | 74 | int Mitos_pre_process(mitos_output *mout) 75 | { 76 | // Create hardware topology file for current hardware 77 | std::string fname_hardware = std::string(mout->dname_topdir) + "/hardware.xml"; 78 | int err = dump_hardware_xml(fname_hardware.c_str()); 79 | if(err) 80 | { 81 | std::cerr << "Mitos: Failed to create hardware topology file!\n"; 82 | return 1; 83 | } 84 | 85 | // hwloc puts the file in the current directory, need to move it 86 | err = rename("hardware.xml", fname_hardware.c_str()); 87 | if(err) 88 | { 89 | std::cerr << "Mitos: Failed to move hardware topology file to output directory!\n"; 90 | return 1; 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | int Mitos_write_sample(perf_event_sample *sample, mitos_output *mout) 97 | { 98 | if(!mout->ok) 99 | return 1; 100 | 101 | Mitos_resolve_symbol(sample); 102 | 103 | fprintf(mout->fout_raw, 104 | "%llu,%s,%llu,%llu,%llu,%llu,%llu,%u,%u,%llu,%llu,%u,%llu,%llu\n", 105 | sample->ip, 106 | sample->data_symbol, 107 | sample->data_size, 108 | sample->num_dims, 109 | sample->access_index[0], 110 | sample->access_index[1], 111 | sample->access_index[2], 112 | sample->pid, 113 | sample->tid, 114 | sample->time, 115 | sample->addr, 116 | sample->cpu, 117 | sample->weight, 118 | sample->data_src); 119 | 120 | return 0; 121 | } 122 | 123 | int Mitos_post_process(char *bin_name, mitos_output *mout) 124 | { 125 | // Open Symtab object and code source object 126 | Symtab *symtab_obj; 127 | SymtabCodeSource *symtab_code_src; 128 | 129 | int sym_success = Symtab::openFile(symtab_obj,bin_name); 130 | if(!sym_success) 131 | { 132 | std::cerr << "Mitos: Failed to open Symtab object for " << bin_name << std::endl; 133 | return 1; 134 | } 135 | 136 | symtab_code_src = new SymtabCodeSource(bin_name); 137 | 138 | // Get machine information 139 | unsigned int inst_length = InstructionDecoder::maxInstructionLength; 140 | Architecture arch = symtab_obj->getArchitecture(); 141 | 142 | // Open input/output files 143 | std::ifstream fraw(mout->fname_raw); 144 | std::ofstream fproc(mout->fname_processed); 145 | 146 | // Write header for processed samples 147 | fproc << "source,line,instruction,bytes,ip,variable,buffer_size,dims,xidx,yidx,zidx,pid,tid,time,addr,cpu,latency,data_src\n"; 148 | 149 | // Read raw samples one by one and get attribute from ip 150 | uint64_t ip; 151 | size_t ip_endpos; 152 | std::string line, ip_str; 153 | while(std::getline(fraw, line).good()) 154 | { 155 | // Unknown values 156 | std::stringstream source; 157 | std::stringstream line_num; 158 | std::stringstream instruction; 159 | std::stringstream bytes; 160 | 161 | // Extract ip 162 | size_t ip_endpos = line.find(','); 163 | std::string ip_str = line.substr(0,ip_endpos); 164 | ip = (uint64_t)strtoull(ip_str.c_str(),NULL,0); 165 | 166 | // Parse ip for source line info 167 | std::vector stats; 168 | sym_success = symtab_obj->getSourceLines(stats,ip); 169 | if(sym_success) 170 | { 171 | source << stats[0]->getFile(); 172 | line_num << stats[0]->getLine(); 173 | } 174 | 175 | // Parse ip for instruction info 176 | void *inst_raw = NULL; 177 | if(symtab_code_src->isValidAddress(ip)) 178 | { 179 | inst_raw = symtab_code_src->getPtrToInstruction(ip); 180 | 181 | if(inst_raw) 182 | { 183 | // Get instruction 184 | InstructionDecoder dec(inst_raw,inst_length,arch); 185 | Instruction::Ptr inst = dec.decode(); 186 | Operation op = inst->getOperation(); 187 | entryID eid = op.getID(); 188 | 189 | instruction << NS_x86::entryNames_IAPI[eid]; 190 | 191 | // Get bytes read 192 | if(inst->readsMemory()) 193 | bytes << getReadSize(inst); 194 | } 195 | } 196 | 197 | // Write out the sample 198 | fproc << (source.str().empty() ? "??" : source.str() ) << "," 199 | << (line_num.str().empty() ? "??" : line_num.str() ) << "," 200 | << (instruction.str().empty() ? "??" : instruction.str() ) << "," 201 | << (bytes.str().empty() ? "??" : bytes.str() ) << "," 202 | << line << std::endl; 203 | } 204 | 205 | fproc.close(); 206 | fraw.close(); 207 | 208 | int err = remove(mout->fname_raw); 209 | if(err) 210 | { 211 | std::cerr << "Mitos: Failed to delete raw sample file!\n"; 212 | return 1; 213 | } 214 | 215 | return 0; 216 | } 217 | 218 | -------------------------------------------------------------------------------- /src/perfsmpl.cpp: -------------------------------------------------------------------------------- 1 | #include "perfsmpl.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | perfsmpl *psmpl; 8 | pthread_mutex_t sample_mutex; 9 | 10 | void signal_thread_handler(int sig, siginfo_t *info, void *extra) 11 | { 12 | // Block incoming signals 13 | sigset_t blocksig; 14 | sigemptyset(&blocksig); 15 | sigaddset(&blocksig,SIGIO); 16 | sigprocmask(SIG_BLOCK,&blocksig,NULL); 17 | 18 | // Process 19 | pthread_mutex_lock(&sample_mutex); 20 | psmpl->process_sample_buffer(); 21 | pthread_mutex_unlock(&sample_mutex); 22 | 23 | // Unblock 24 | sigprocmask(SIG_UNBLOCK,&blocksig,NULL); 25 | } 26 | 27 | perfsmpl::perfsmpl() 28 | { 29 | // Defaults 30 | mmap_pages = 1; 31 | sample_period = 4000; 32 | sample_threshold = 7; 33 | pgsz = sysconf(_SC_PAGESIZE); 34 | mmap_size = (mmap_pages+1)*pgsz; 35 | pgmsk = mmap_pages*pgsz-1; 36 | 37 | ret = 0; 38 | ready = 0; 39 | stop = 0; 40 | 41 | mPID = 0; 42 | handler_fn_defined = 0; 43 | end_fn_defined = 0; 44 | 45 | collected_samples = 0; 46 | lost_samples = 0; 47 | } 48 | 49 | perfsmpl::~perfsmpl() 50 | { 51 | close(fd); 52 | munmap(mmap_buf,mmap_size); 53 | } 54 | 55 | void perfsmpl::init_attr() 56 | { 57 | // event attr 58 | memset(&pe, 0, sizeof(struct perf_event_attr)); 59 | pe.size = sizeof(struct perf_event_attr); 60 | 61 | pe.mmap = 1; 62 | pe.mmap_data = 1; 63 | pe.comm = 1; 64 | pe.disabled = 1; 65 | pe.exclude_user = 0; 66 | pe.exclude_kernel = 0; 67 | pe.exclude_hv = 0; 68 | pe.exclude_idle = 0; 69 | pe.exclude_host = 0; 70 | pe.exclude_guest = 1; 71 | pe.pinned = 0; 72 | pe.sample_id_all = 0; 73 | pe.wakeup_events = 1; 74 | 75 | pe.sample_period = sample_period; 76 | pe.freq = 0; 77 | 78 | if(mode == SMPL_MEMORY) 79 | { 80 | // TODO: look this up in libpfm 81 | pe.type = PERF_TYPE_RAW; 82 | pe.config = 0x5101cd; 83 | pe.config1 = sample_threshold; // ldlat 84 | pe.sample_type = 85 | PERF_SAMPLE_IP | 86 | //PERF_SAMPLE_CALLCHAIN | 87 | PERF_SAMPLE_ID | 88 | PERF_SAMPLE_STREAM_ID | 89 | PERF_SAMPLE_TIME | 90 | PERF_SAMPLE_TID | 91 | PERF_SAMPLE_PERIOD | 92 | PERF_SAMPLE_CPU | 93 | PERF_SAMPLE_ADDR | 94 | PERF_SAMPLE_WEIGHT | 95 | PERF_SAMPLE_DATA_SRC; 96 | pe.precise_ip = 2; 97 | } 98 | 99 | if(mode == SMPL_INSTRUCTIONS) 100 | { 101 | pe.type = PERF_TYPE_HARDWARE; 102 | pe.config = PERF_COUNT_SW_DUMMY; 103 | pe.sample_type = 104 | PERF_SAMPLE_IP | 105 | //PERF_SAMPLE_CALLCHAIN | 106 | PERF_SAMPLE_ID | 107 | PERF_SAMPLE_STREAM_ID | 108 | PERF_SAMPLE_TIME | 109 | PERF_SAMPLE_TID | 110 | PERF_SAMPLE_PERIOD | 111 | PERF_SAMPLE_CPU; 112 | } 113 | } 114 | 115 | int perfsmpl::init_perf() 116 | { 117 | // Create attr according to sample mode 118 | fd = syscall(__NR_perf_event_open, &pe,mPID,-1,-1,0); 119 | 120 | if(fd == -1) 121 | { 122 | perror("perf_event_open"); 123 | return 1; 124 | } 125 | 126 | // Create mmap buffer for samples 127 | mmap_buf = (struct perf_event_mmap_page*) 128 | mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 129 | 130 | if(mmap_buf == MAP_FAILED) 131 | { 132 | perror("mmap"); 133 | return 1; 134 | } 135 | 136 | return 0; 137 | } 138 | 139 | int perfsmpl::init_sighandler() 140 | { 141 | psmpl = this; 142 | pthread_mutex_init(&sample_mutex, NULL); 143 | 144 | // Set up signal handler 145 | struct sigaction sact; 146 | memset(&sact, 0, sizeof(sact)); 147 | sact.sa_sigaction = &signal_thread_handler; 148 | sact.sa_flags = SA_SIGINFO; 149 | 150 | int ret = sigaction(SIGIO, &sact, NULL); 151 | if(ret) 152 | { 153 | perror("sigaction"); 154 | return 1; 155 | } 156 | 157 | sigset_t sold, snew; 158 | sigemptyset(&sold); 159 | sigemptyset(&snew); 160 | sigaddset(&snew, SIGIO); 161 | 162 | ret = sigprocmask(SIG_SETMASK, NULL, &sold); 163 | if(ret) 164 | { 165 | perror("sigaction"); 166 | return 1; 167 | } 168 | 169 | if(sigismember(&sold, SIGIO)) 170 | { 171 | ret = sigprocmask(SIG_UNBLOCK, &snew, NULL); 172 | if(ret) 173 | { 174 | perror("sigaction"); 175 | return 1; 176 | } 177 | } 178 | 179 | // Set perf event fd to signal 180 | ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_ASYNC); 181 | if(ret) 182 | { 183 | perror("fcntl"); 184 | return 1; 185 | } 186 | ret = fcntl(fd, F_SETSIG, SIGIO); 187 | if(ret) 188 | { 189 | perror("fcntl"); 190 | return 1; 191 | } 192 | ret = fcntl(fd, F_SETOWN, getpid()); 193 | if(ret) 194 | { 195 | perror("fcntl"); 196 | return 1; 197 | } 198 | 199 | return 0; 200 | } 201 | 202 | int perfsmpl::prepare(pid_t p) 203 | { 204 | mPID = p; 205 | 206 | init_attr(); 207 | 208 | ret = init_perf(); 209 | if(ret != 0) 210 | { 211 | ready = 0; 212 | return ret; 213 | } 214 | 215 | ret = init_sighandler(); 216 | if(ret != 0) 217 | { 218 | ready = 0; 219 | return ret; 220 | } 221 | 222 | ready = 1; 223 | 224 | return 0; 225 | } 226 | 227 | int perfsmpl::begin_sampler() 228 | { 229 | if(!ready) 230 | { 231 | std::cerr << "Not ready to begin sampling!" << std::endl; 232 | return -1; 233 | } 234 | 235 | ioctl(fd, PERF_EVENT_IOC_RESET, 0); 236 | ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); 237 | 238 | return ret; 239 | } 240 | 241 | void perfsmpl::end_sampler() 242 | { 243 | stop = 1; 244 | 245 | ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); 246 | read(fd, &counter_value, sizeof(uint64_t)); 247 | 248 | process_sample_buffer(); // flush out remaining samples 249 | 250 | if(end_fn_defined) 251 | { 252 | end_fn(end_fn_args); 253 | } 254 | } 255 | 256 | int perfsmpl::process_single_sample(struct perf_event_mmap_page *mmap_buf) 257 | { 258 | collected_samples++; 259 | 260 | // Fill up our sample 261 | memset(&pes,0,sizeof(pes)); 262 | 263 | if(has_attribute(PERF_SAMPLE_IP)) 264 | { 265 | read_mmap_buffer(mmap_buf,(char*)&pes.ip,sizeof(uint64_t)); 266 | } 267 | 268 | if(has_attribute(PERF_SAMPLE_TID)) 269 | { 270 | read_mmap_buffer(mmap_buf,(char*)&pes.pid,sizeof(uint32_t)); 271 | read_mmap_buffer(mmap_buf,(char*)&pes.tid,sizeof(uint32_t)); 272 | } 273 | 274 | if(has_attribute(PERF_SAMPLE_TIME)) 275 | { 276 | read_mmap_buffer(mmap_buf,(char*)&pes.time,sizeof(uint64_t)); 277 | } 278 | 279 | if(has_attribute(PERF_SAMPLE_ADDR)) 280 | { 281 | read_mmap_buffer(mmap_buf,(char*)&pes.addr,sizeof(uint64_t)); 282 | } 283 | 284 | if(has_attribute(PERF_SAMPLE_ID)) 285 | { 286 | read_mmap_buffer(mmap_buf,(char*)&pes.id,sizeof(uint64_t)); 287 | } 288 | 289 | if(has_attribute(PERF_SAMPLE_STREAM_ID)) 290 | { 291 | read_mmap_buffer(mmap_buf,(char*)&pes.stream_id,sizeof(uint64_t)); 292 | } 293 | 294 | if(has_attribute(PERF_SAMPLE_CPU)) 295 | { 296 | read_mmap_buffer(mmap_buf,(char*)&pes.cpu,sizeof(uint32_t)); 297 | read_mmap_buffer(mmap_buf,(char*)&pes.res,sizeof(uint32_t)); 298 | } 299 | 300 | if(has_attribute(PERF_SAMPLE_PERIOD)) 301 | { 302 | read_mmap_buffer(mmap_buf,(char*)&pes.period,sizeof(uint64_t)); 303 | } 304 | 305 | /* 306 | if(has_attribute(PERF_SAMPLE_CALLCHAIN)) 307 | { 308 | read_mmap_buffer(mmap_buf,(char*)&pes.nr,sizeof(uint64_t)); 309 | pes.ips = (uint64_t*)malloc(pes.nr*sizeof(uint64_t)); 310 | read_mmap_buffer(mmap_buf,(char*)pes.ips,pes.nr*sizeof(uint64_t)); 311 | } 312 | */ 313 | 314 | if(has_attribute(PERF_SAMPLE_WEIGHT)) 315 | { 316 | read_mmap_buffer(mmap_buf,(char*)&pes.weight,sizeof(uint64_t)); 317 | } 318 | 319 | if(has_attribute(PERF_SAMPLE_DATA_SRC)) 320 | { 321 | read_mmap_buffer(mmap_buf,(char*)&pes.data_src,sizeof(uint64_t)); 322 | } 323 | 324 | if(handler_fn_defined) 325 | { 326 | handler_fn(&pes,handler_fn_args); 327 | } 328 | 329 | return ret; 330 | } 331 | 332 | int perfsmpl::process_sample_buffer() 333 | { 334 | struct perf_event_header ehdr; 335 | int ret; 336 | 337 | 338 | for(;;) 339 | { 340 | ret = read_mmap_buffer(mmap_buf,(char*)&ehdr,sizeof(ehdr)); 341 | if(ret) 342 | return 0; // no more samples 343 | 344 | switch(ehdr.type) 345 | { 346 | case PERF_RECORD_SAMPLE: 347 | process_single_sample(mmap_buf); 348 | break; 349 | case PERF_RECORD_EXIT: 350 | process_exit_sample(mmap_buf); 351 | break; 352 | case PERF_RECORD_LOST: 353 | process_lost_sample(mmap_buf); 354 | break; 355 | case PERF_RECORD_THROTTLE: 356 | process_freq_sample(mmap_buf); 357 | break; 358 | case PERF_RECORD_UNTHROTTLE: 359 | process_freq_sample(mmap_buf); 360 | break; 361 | default: 362 | //std::cerr << "Unknown sample type "; 363 | //std::cerr << ehdr.type << std::endl; 364 | skip_mmap_buffer(mmap_buf,sizeof(ehdr)); 365 | } 366 | } 367 | 368 | } 369 | 370 | int perfsmpl::read_mmap_buffer(struct perf_event_mmap_page *mmap_buf, char *out, size_t sz) 371 | { 372 | char *data; 373 | unsigned long tail; 374 | size_t avail_sz, m, c; 375 | 376 | data = ((char *)mmap_buf)+sysconf(_SC_PAGESIZE); 377 | tail = mmap_buf->data_tail & pgmsk; 378 | avail_sz = mmap_buf->data_head - mmap_buf->data_tail; 379 | if (sz > avail_sz) 380 | return -1; 381 | c = pgmsk + 1 - tail; 382 | m = c < sz ? c : sz; 383 | memcpy(out, data+tail, m); 384 | if ((sz - m) > 0) 385 | memcpy(out+m, data, sz - m); 386 | mmap_buf->data_tail += sz; 387 | 388 | return 0; 389 | } 390 | 391 | void perfsmpl::skip_mmap_buffer(struct perf_event_mmap_page *mmap_buf, size_t sz) 392 | { 393 | if ((mmap_buf->data_tail + sz) > mmap_buf->data_head) 394 | sz = mmap_buf->data_head - mmap_buf->data_tail; 395 | 396 | mmap_buf->data_tail += sz; 397 | } 398 | 399 | void perfsmpl::process_lost_sample(struct perf_event_mmap_page *mmap_buf) 400 | { 401 | struct { uint64_t id, lost; } lost; 402 | ret = read_mmap_buffer(mmap_buf,(char*)&lost,sizeof(lost)); 403 | 404 | lost_samples += lost.lost; 405 | } 406 | 407 | void perfsmpl::process_exit_sample(struct perf_event_mmap_page *mmap_buf) 408 | { 409 | struct { pid_t pid, ppid, tid, ptid; } grp; 410 | int ret; 411 | 412 | ret = read_mmap_buffer(mmap_buf,(char*)&grp,sizeof(grp)); 413 | } 414 | 415 | void perfsmpl::process_freq_sample(struct perf_event_mmap_page *mmap_buf) 416 | { 417 | struct { uint64_t time, id, stream_id; } thr; 418 | int ret; 419 | 420 | ret = read_mmap_buffer(mmap_buf,(char*)&thr, sizeof(thr)); 421 | } 422 | 423 | const char* Mitos_hit_type(struct perf_event_sample *s) 424 | { 425 | uint64_t lvl_bits = s->data_src >> PERF_MEM_LVL_SHIFT; 426 | 427 | if(lvl_bits & PERF_MEM_LVL_NA) 428 | return "Not Available"; 429 | else if(lvl_bits & PERF_MEM_LVL_HIT) 430 | return "Hit"; 431 | else if(lvl_bits & PERF_MEM_LVL_MISS) 432 | return "Miss"; 433 | 434 | return "Invalid Data Source"; 435 | } 436 | 437 | const char* Mitos_data_source(struct perf_event_sample *s) 438 | { 439 | uint64_t lvl_bits = s->data_src >> PERF_MEM_LVL_SHIFT; 440 | 441 | if(lvl_bits & PERF_MEM_LVL_NA) 442 | return "Not Available"; 443 | else if(lvl_bits & PERF_MEM_LVL_L1) 444 | return "L1"; 445 | else if(lvl_bits & PERF_MEM_LVL_LFB) 446 | return "LFB"; 447 | else if(lvl_bits & PERF_MEM_LVL_L2) 448 | return "L2"; 449 | else if(lvl_bits & PERF_MEM_LVL_L3) 450 | return "L3"; 451 | else if(lvl_bits & PERF_MEM_LVL_LOC_RAM) 452 | return "Local RAM"; 453 | else if(lvl_bits & PERF_MEM_LVL_REM_RAM1) 454 | return "Remote RAM 1 Hop"; 455 | else if(lvl_bits & PERF_MEM_LVL_REM_RAM2) 456 | return "Remote RAM 2 Hops"; 457 | else if(lvl_bits & PERF_MEM_LVL_REM_CCE1) 458 | return "Remote Cache 1 Hops"; 459 | else if(lvl_bits & PERF_MEM_LVL_REM_CCE2) 460 | return "Remote Cache 2 Hops"; 461 | else if(lvl_bits & PERF_MEM_LVL_IO) 462 | return "I/O Memory"; 463 | else if(lvl_bits & PERF_MEM_LVL_UNC) 464 | return "Uncached Memory"; 465 | 466 | return "Invalid Data Source"; 467 | } 468 | 469 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | 205 | --- LLVM Exceptions to the Apache 2.0 License ---- 206 | 207 | As an exception, if, as a result of your compiling your source code, portions 208 | of this Software are embedded into an Object form of such source code, you 209 | may redistribute such embedded portions in such Object form without complying 210 | with the conditions of Sections 4(a), 4(b) and 4(d) of the License. 211 | 212 | In addition, if you combine or link compiled forms of this Software with 213 | software that is licensed under the GPLv2 ("Combined Software") and if a 214 | court of competent jurisdiction determines that the patent provision (Section 215 | 3), the indemnity provision (Section 9) or other Section of the License 216 | conflicts with the conditions of the GPLv2, you may retroactively and 217 | prospectively choose to deem waived or otherwise exclude such Section(s) of 218 | the License, but only in their entirety and only with respect to the Combined 219 | Software. 220 | --------------------------------------------------------------------------------