| /* SPDX-License-Identifier: LGPL-2.1 */ |
| |
| /* |
| * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com> |
| */ |
| |
| /** |
| * @file libkshark.h |
| * @brief API for processing of FTRACE (trace-cmd) data. |
| */ |
| |
| #ifndef _LIB_KSHARK_H |
| #define _LIB_KSHARK_H |
| |
| // C |
| #include <stdint.h> |
| #include <pthread.h> |
| #include <errno.h> |
| |
| // Json-C |
| #include <json.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // trace-cmd |
| #include "trace-cmd.h" |
| #include "trace-filter-hash.h" |
| #include "event-parse.h" |
| #include "trace-filter-hash.h" |
| |
| // KernelShark |
| #include "libkshark-plugin.h" |
| |
| /** |
| * Kernel Shark entry contains all information from one trace record needed |
| * in order to visualize the time-series of trace records. The part of the |
| * data which is not directly required for the visualization (latency, record |
| * info etc.) is available on-demand via the offset into the trace file. |
| */ |
| struct kshark_entry { |
| /** Pointer to the next (in time) kshark_entry on the same CPU core. */ |
| struct kshark_entry *next; /* MUST BE FIRST ENTRY */ |
| |
| /** |
| * A bit mask controlling the visibility of the entry. A value of OxFF |
| * would mean that the entry is visible everywhere. Use |
| * kshark_filter_masks to check the level of visibility/invisibility |
| * of the entry. |
| */ |
| uint16_t visible; |
| |
| /** The CPU core of the record. */ |
| int16_t cpu; |
| |
| /** The PID of the task the record was generated. */ |
| int32_t pid; |
| |
| /** Unique Id ot the trace event type. */ |
| int32_t event_id; |
| |
| /** The offset into the trace file, used to find the record. */ |
| uint64_t offset; |
| |
| /** |
| * The time of the record in nano seconds. The value is taken from |
| * the timestamps within the trace data file, which are architecture |
| * dependent. The time usually is the timestamp from when the system |
| * started. |
| */ |
| uint64_t ts; |
| }; |
| |
| /** Size of the task's hash table. */ |
| #define KS_TASK_HASH_SIZE 256 |
| |
| /** Linked list of tasks. */ |
| struct kshark_task_list { |
| /** Pointer to the next task's PID. */ |
| struct kshark_task_list *next; |
| |
| /** PID of a task. */ |
| int pid; |
| }; |
| |
| /** Structure representing a kshark session. */ |
| struct kshark_context { |
| /** Input handle for the trace data file. */ |
| struct tracecmd_input *handle; |
| |
| /** Page event used to parse the page. */ |
| struct tep_handle *pevent; |
| |
| /** Hash table of task PIDs. */ |
| struct kshark_task_list *tasks[KS_TASK_HASH_SIZE]; |
| |
| /** A mutex, used to protect the access to the input file. */ |
| pthread_mutex_t input_mutex; |
| |
| /** Hash of tasks to filter on. */ |
| struct tracecmd_filter_id *show_task_filter; |
| |
| /** Hash of tasks to not display. */ |
| struct tracecmd_filter_id *hide_task_filter; |
| |
| /** Hash of events to filter on. */ |
| struct tracecmd_filter_id *show_event_filter; |
| |
| /** Hash of events to not display. */ |
| struct tracecmd_filter_id *hide_event_filter; |
| |
| /** Hash of CPUs to filter on. */ |
| struct tracecmd_filter_id *show_cpu_filter; |
| |
| /** Hash of CPUs to not display. */ |
| struct tracecmd_filter_id *hide_cpu_filter; |
| |
| /** |
| * Bit mask, controlling the visibility of the entries after filtering. |
| * If given bit is set here, all entries which are filtered-out will |
| * have this bit unset in their "visible" fields. |
| */ |
| uint8_t filter_mask; |
| |
| /** |
| * Filter allowing sophisticated filtering based on the content of |
| * the event. |
| */ |
| struct tep_event_filter *advanced_event_filter; |
| |
| /** List of Data collections. */ |
| struct kshark_entry_collection *collections; |
| |
| /** List of Plugins. */ |
| struct kshark_plugin_list *plugins; |
| |
| /** List of Plugin Event handlers. */ |
| struct kshark_event_handler *event_handlers; |
| }; |
| |
| bool kshark_instance(struct kshark_context **kshark_ctx); |
| |
| bool kshark_open(struct kshark_context *kshark_ctx, const char *file); |
| |
| ssize_t kshark_load_data_entries(struct kshark_context *kshark_ctx, |
| struct kshark_entry ***data_rows); |
| |
| ssize_t kshark_load_data_records(struct kshark_context *kshark_ctx, |
| struct tep_record ***data_rows); |
| |
| ssize_t kshark_get_task_pids(struct kshark_context *kshark_ctx, int **pids); |
| |
| void kshark_close(struct kshark_context *kshark_ctx); |
| |
| void kshark_free(struct kshark_context *kshark_ctx); |
| |
| int kshark_get_pid_easy(struct kshark_entry *entry); |
| |
| const char *kshark_get_task_easy(struct kshark_entry *entry); |
| |
| const char *kshark_get_latency_easy(struct kshark_entry *entry); |
| |
| int kshark_get_event_id_easy(struct kshark_entry *entry); |
| |
| const char *kshark_get_event_name_easy(struct kshark_entry *entry); |
| |
| const char *kshark_get_info_easy(struct kshark_entry *entry); |
| |
| void kshark_convert_nano(uint64_t time, uint64_t *sec, uint64_t *usec); |
| |
| char* kshark_dump_entry(const struct kshark_entry *entry); |
| |
| /** |
| * Custom entry info function type. To be user for dumping info for custom |
| * KernelShark entryes. |
| */ |
| typedef const char *(kshark_custom_info_func)(struct kshark_context *, |
| const struct kshark_entry *, |
| bool); |
| |
| char* kshark_dump_custom_entry(struct kshark_context *kshark_ctx, |
| const struct kshark_entry *entry, |
| kshark_custom_info_func info_func); |
| |
| /** Bit masks used to control the visibility of the entry after filtering. */ |
| enum kshark_filter_masks { |
| /** |
| * Use this mask to check the visibility of the entry in the text |
| * view. |
| */ |
| KS_TEXT_VIEW_FILTER_MASK = 1 << 0, |
| |
| /** |
| * Use this mask to check the visibility of the entry in the graph |
| * view. |
| */ |
| KS_GRAPH_VIEW_FILTER_MASK = 1 << 1, |
| |
| /** Special mask used whene filtering events. */ |
| KS_EVENT_VIEW_FILTER_MASK = 1 << 2, |
| |
| /* The next 4 bits are reserved for more KS_X_VIEW_FILTER_MASKs. */ |
| |
| /** |
| * Use this mask to check if the content of the entry has been accessed |
| * by a plugin-defined function. |
| */ |
| KS_PLUGIN_UNTOUCHED_MASK = 1 << 7 |
| }; |
| |
| /** Filter type identifier. */ |
| enum kshark_filter_type { |
| /** Dummy filter identifier reserved for future use. */ |
| KS_NO_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the events to be shown. |
| */ |
| KS_SHOW_EVENT_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the events to be |
| * filtered-out. |
| */ |
| KS_HIDE_EVENT_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the tasks to be shown. |
| */ |
| KS_SHOW_TASK_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the tasks to be |
| * filtered-out. |
| */ |
| KS_HIDE_TASK_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the CPUs to be shown. |
| */ |
| KS_SHOW_CPU_FILTER, |
| |
| /** |
| * Identifier of the filter, used to specified the CPUs to be |
| * filtered-out. |
| */ |
| KS_HIDE_CPU_FILTER, |
| }; |
| |
| void kshark_filter_add_id(struct kshark_context *kshark_ctx, |
| int filter_id, int id); |
| |
| void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id); |
| |
| bool kshark_filter_is_set(struct kshark_context *kshark_ctx); |
| |
| void kshark_filter_entries(struct kshark_context *kshark_ctx, |
| struct kshark_entry **data, |
| size_t n_entries); |
| |
| void kshark_clear_all_filters(struct kshark_context *kshark_ctx, |
| struct kshark_entry **data, |
| size_t n_entries); |
| |
| /** Search failed identifiers. */ |
| enum kshark_search_failed { |
| /** All entries have timestamps greater timestamps. */ |
| BSEARCH_ALL_GREATER = -1, |
| |
| /** All entries have timestamps smaller timestamps. */ |
| BSEARCH_ALL_SMALLER = -2, |
| }; |
| |
| /** General purpose Binary search macro. */ |
| #define BSEARCH(h, l, cond) \ |
| ({ \ |
| while (h - l > 1) { \ |
| mid = (l + h) / 2; \ |
| if (cond) \ |
| l = mid; \ |
| else \ |
| h = mid; \ |
| } \ |
| }) |
| |
| ssize_t kshark_find_entry_by_time(uint64_t time, |
| struct kshark_entry **data_rows, |
| size_t l, size_t h); |
| |
| ssize_t kshark_find_record_by_time(uint64_t time, |
| struct tep_record **data_rows, |
| size_t l, size_t h); |
| |
| bool kshark_match_pid(struct kshark_context *kshark_ctx, |
| struct kshark_entry *e, int pid); |
| |
| bool kshark_match_cpu(struct kshark_context *kshark_ctx, |
| struct kshark_entry *e, int cpu); |
| |
| /** |
| * Empty bin identifier. |
| * KS_EMPTY_BIN is used to reset entire arrays to empty with memset(), thus it |
| * must be -1 for that to work. |
| */ |
| #define KS_EMPTY_BIN -1 |
| |
| /** Filtered bin identifier. */ |
| #define KS_FILTERED_BIN -2 |
| |
| /** Overflow Event identifier. */ |
| #define KS_EVENT_OVERFLOW (-EOVERFLOW) |
| |
| /** Matching condition function type. To be user for data requests */ |
| typedef bool (matching_condition_func)(struct kshark_context*, |
| struct kshark_entry*, |
| int); |
| |
| /** |
| * Data request structure, defining the properties of the required |
| * kshark_entry. |
| */ |
| struct kshark_entry_request { |
| /** Pointer to the next Data request. */ |
| struct kshark_entry_request *next; |
| |
| /** |
| * Array index specifying the position inside the array from where |
| * the search starts. |
| */ |
| size_t first; |
| |
| /** Number of array elements to search in. */ |
| size_t n; |
| |
| /** Matching condition function. */ |
| matching_condition_func *cond; |
| |
| /** |
| * Matching condition value, used by the Matching condition function. |
| */ |
| int val; |
| |
| /** If true, a visible entry is requested. */ |
| bool vis_only; |
| |
| /** |
| * If "vis_only" is true, use this mask to specify the level of |
| * visibility of the requested entry. |
| */ |
| uint8_t vis_mask; |
| }; |
| |
| struct kshark_entry_request * |
| kshark_entry_request_alloc(size_t first, size_t n, |
| matching_condition_func cond, int val, |
| bool vis_only, int vis_mask); |
| |
| void kshark_free_entry_request(struct kshark_entry_request *req); |
| |
| const struct kshark_entry * |
| kshark_get_entry_front(const struct kshark_entry_request *req, |
| struct kshark_entry **data, |
| ssize_t *index); |
| |
| const struct kshark_entry * |
| kshark_get_entry_back(const struct kshark_entry_request *req, |
| struct kshark_entry **data, |
| ssize_t *index); |
| |
| /** |
| * Data collections are used to optimize the search for an entry having an |
| * abstract property, defined by a Matching condition function and a value. |
| * When a collection is processed, the data which is relevant for the |
| * collection is enclosed in "Data intervals", defined by pairs of "Resume" and |
| * "Break" points. It is guaranteed that the data outside of the intervals |
| * contains no entries satisfying the abstract matching condition. However, the |
| * intervals may (will) contain data that do not satisfy the matching condition. |
| * Once defined, the Data collection can be used when searching for an entry |
| * having the same (ore related) abstract property. The collection allows to |
| * ignore the irrelevant data, thus it eliminates the linear worst-case time |
| * complexity of the search. |
| */ |
| struct kshark_entry_collection { |
| /** Pointer to the next Data collection. */ |
| struct kshark_entry_collection *next; |
| |
| /** Matching condition function, used to define the collections. */ |
| matching_condition_func *cond; |
| |
| /** |
| * Matching condition value, used by the Matching condition finction |
| * to define the collections. |
| */ |
| int val; |
| |
| /** |
| * Array of indexes defining the beginning of each individual data |
| * interval. |
| */ |
| size_t *resume_points; |
| |
| /** |
| * Array of indexes defining the end of each individual data interval. |
| */ |
| size_t *break_points; |
| |
| /** Number of data intervals in this collection. */ |
| size_t size; |
| }; |
| |
| struct kshark_entry_collection * |
| kshark_add_collection_to_list(struct kshark_context *kshark_ctx, |
| struct kshark_entry_collection **col_list, |
| struct kshark_entry **data, |
| size_t n_rows, |
| matching_condition_func cond, |
| int val, |
| size_t margin); |
| |
| struct kshark_entry_collection * |
| kshark_register_data_collection(struct kshark_context *kshark_ctx, |
| struct kshark_entry **data, size_t n_rows, |
| matching_condition_func cond, int val, |
| size_t margin); |
| |
| void kshark_unregister_data_collection(struct kshark_entry_collection **col, |
| matching_condition_func cond, |
| int val); |
| |
| struct kshark_entry_collection * |
| kshark_find_data_collection(struct kshark_entry_collection *col, |
| matching_condition_func cond, |
| int val); |
| |
| void kshark_reset_data_collection(struct kshark_entry_collection *col); |
| |
| void kshark_free_collection_list(struct kshark_entry_collection *col); |
| |
| const struct kshark_entry * |
| kshark_get_collection_entry_front(struct kshark_entry_request **req, |
| struct kshark_entry **data, |
| const struct kshark_entry_collection *col, |
| ssize_t *index); |
| |
| const struct kshark_entry * |
| kshark_get_collection_entry_back(struct kshark_entry_request **req, |
| struct kshark_entry **data, |
| const struct kshark_entry_collection *col, |
| ssize_t *index); |
| |
| /** Structure representing a KernelShark Configuration document. */ |
| struct kshark_config_doc { |
| /** Document format identifier. */ |
| int format; |
| |
| /** Configuration document instance. */ |
| void *conf_doc; |
| }; |
| |
| /** Configuration format identifiers. */ |
| enum kshark_config_formats { |
| /** Unformatted Configuration document identifier. */ |
| KS_CONFIG_AUTO = 0, |
| |
| /** |
| * String Configuration document identifier. The String format is |
| * meant to be used only by kshark_config_doc_add() and |
| * kshark_config_doc_get(), when adding/getting simple string fields. |
| */ |
| KS_CONFIG_STRING, |
| |
| /** Json Configuration document identifier. */ |
| KS_CONFIG_JSON, |
| }; |
| |
| /** |
| * Field name for the Configuration document describing the Hide Event filter. |
| */ |
| #define KS_HIDE_EVENT_FILTER_NAME "hide event filter" |
| |
| /** |
| * Field name for the Configuration document describing the Show Event filter. |
| */ |
| #define KS_SHOW_EVENT_FILTER_NAME "show event filter" |
| |
| /** |
| * Field name for the Configuration document describing the Hide Task filter. |
| */ |
| #define KS_HIDE_TASK_FILTER_NAME "hide task filter" |
| |
| /** |
| * Field name for the Configuration document describing the Show Task filter. |
| */ |
| #define KS_SHOW_TASK_FILTER_NAME "show task filter" |
| |
| /** |
| * Field name for the Configuration document describing the Hide Task filter. |
| */ |
| #define KS_HIDE_CPU_FILTER_NAME "hide cpu filter" |
| |
| /** |
| * Field name for the Configuration document describing the Show Task filter. |
| */ |
| #define KS_SHOW_CPU_FILTER_NAME "show cpu filter" |
| |
| /** |
| * Field name for the Configuration document describing the Advanced event |
| * filter. |
| */ |
| #define KS_ADV_EVENT_FILTER_NAME "adv event filter" |
| |
| /** |
| * Field name for the Configuration document describing user-specified filter |
| * mask. |
| */ |
| #define KS_USER_FILTER_MASK_NAME "filter mask" |
| /** |
| * Field name for the Configuration document describing the state of the Vis. |
| * model. |
| */ |
| #define KS_HISTO_NAME "vis. model" |
| |
| /** |
| * Field name for the Configuration document describing the currently loaded |
| * trace data file. |
| */ |
| #define KS_DATA_SOURCE_NAME "trace data" |
| |
| struct kshark_config_doc * |
| kshark_config_alloc(enum kshark_config_formats); |
| |
| struct kshark_config_doc * |
| kshark_config_new(const char *type, enum kshark_config_formats); |
| |
| void kshark_free_config_doc(struct kshark_config_doc *conf); |
| |
| struct kshark_config_doc * |
| kshark_record_config_new(enum kshark_config_formats); |
| |
| struct kshark_config_doc * |
| kshark_filter_config_new(enum kshark_config_formats); |
| |
| struct kshark_config_doc *kshark_string_config_alloc(); |
| |
| bool kshark_type_check(struct kshark_config_doc *conf, const char *type); |
| |
| bool kshark_config_doc_add(struct kshark_config_doc *conf, |
| const char *key, |
| struct kshark_config_doc *val); |
| |
| bool kshark_config_doc_get(struct kshark_config_doc *conf, |
| const char *key, |
| struct kshark_config_doc *val); |
| |
| struct kshark_trace_histo; |
| |
| struct kshark_config_doc * |
| kshark_export_trace_file(const char *file, |
| enum kshark_config_formats format); |
| |
| const char *kshark_import_trace_file(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| struct kshark_config_doc * |
| kshark_export_model(struct kshark_trace_histo *histo, |
| enum kshark_config_formats format); |
| |
| |
| bool kshark_import_model(struct kshark_trace_histo *histo, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_export_adv_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf); |
| |
| bool kshark_import_adv_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_export_event_filter(struct tep_handle *pevent, |
| struct tracecmd_filter_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_import_event_filter(struct tep_handle *pevent, |
| struct tracecmd_filter_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_export_user_mask(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf); |
| |
| bool kshark_import_user_mask(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_export_filter_array(struct tracecmd_filter_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_import_filter_array(struct tracecmd_filter_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_export_all_event_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf); |
| |
| bool kshark_export_all_task_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf); |
| |
| bool kshark_export_all_cpu_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf); |
| |
| struct kshark_config_doc * |
| kshark_export_all_filters(struct kshark_context *kshark_ctx, |
| enum kshark_config_formats format); |
| |
| bool kshark_import_all_event_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_import_all_task_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_import_all_cpu_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_import_all_filters(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf); |
| |
| bool kshark_save_config_file(const char *file_name, |
| struct kshark_config_doc *conf); |
| |
| struct kshark_config_doc *kshark_open_config_file(const char *file_name, |
| const char *type); |
| |
| struct kshark_config_doc *kshark_json_to_conf(struct json_object *jobj); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // _LIB_KSHARK_H |