1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
#ifndef UFTRACE_FSTACK_H
#define UFTRACE_FSTACK_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "uftrace.h"
#include "utils/filter.h"
struct uftrace_symbol;
enum uftrace_fstack_flag {
FSTACK_FL_FILTERED = (1U << 0),
FSTACK_FL_NOTRACE = (1U << 1),
FSTACK_FL_NORECORD = (1U << 2),
FSTACK_FL_EXEC = (1U << 3),
FSTACK_FL_LONGJMP = (1U << 4),
};
enum uftrace_fstack_context {
FSTACK_CTX_UNKNOWN = 0,
FSTACK_CTX_USER = 1,
FSTACK_CTX_KERNEL = 2,
};
struct uftrace_task_filter_stack {
struct uftrace_task_filter_stack *next;
uint64_t threshold;
int depth;
unsigned size;
enum uftrace_fstack_context context;
};
struct uftrace_task_reader {
int tid;
bool valid;
bool done;
bool lost_seen;
bool sched_out_seen;
bool fork_handled;
bool fstack_set;
bool display_depth_set;
bool fstack_warned;
FILE *fp;
struct uftrace_symbol *func;
struct uftrace_task *t;
struct uftrace_data *h;
struct uftrace_record ustack;
struct uftrace_record kstack;
struct uftrace_record estack;
struct uftrace_record xstack;
struct uftrace_record *rstack;
struct uftrace_rstack_list rstack_list;
struct uftrace_rstack_list event_list;
int stack_count;
int lost_count;
int user_stack_count;
int display_depth;
int user_display_depth;
int fork_display_depth;
int column_index;
int event_color;
int sched_cpu;
enum uftrace_fstack_context ctx;
uint64_t timestamp;
uint64_t timestamp_last;
uint64_t timestamp_next;
uint64_t timestamp_estimate;
struct {
int in_count;
int out_count;
int depth;
struct uftrace_task_filter_stack *stack;
} filter;
struct uftrace_fstack {
uint64_t addr;
bool valid;
int orig_depth;
unsigned long flags;
uint64_t total_time;
uint64_t child_time;
} * func_stack;
struct uftrace_fstack_args args;
bool sched_preempt_seen;
};
enum uftrace_argspec_string_bits {
/* bit index */
NEEDS_PAREN_BIT,
NEEDS_SEMI_COLON_BIT,
HAS_MORE_BIT,
IS_RETVAL_BIT,
NEEDS_ASSIGNMENT_BIT,
NEEDS_JSON_BIT,
/* bit mask */
NEEDS_PAREN = (1U << NEEDS_PAREN_BIT),
NEEDS_SEMI_COLON = (1U << NEEDS_SEMI_COLON_BIT),
HAS_MORE = (1U << HAS_MORE_BIT),
IS_RETVAL = (1U << IS_RETVAL_BIT),
NEEDS_ASSIGNMENT = (1U << NEEDS_ASSIGNMENT_BIT),
NEEDS_JSON = (1U << NEEDS_JSON_BIT),
};
extern bool fstack_enabled;
extern bool live_disabled;
struct uftrace_task_reader *get_task_handle(struct uftrace_data *handle, int tid);
void reset_task_handle(struct uftrace_data *handle);
void fstack_setup_task(char *tid_filter, struct uftrace_data *handle);
int read_rstack(struct uftrace_data *handle, struct uftrace_task_reader **task);
int peek_rstack(struct uftrace_data *handle, struct uftrace_task_reader **task);
void fstack_consume(struct uftrace_data *handle, struct uftrace_task_reader *task);
int read_task_ustack(struct uftrace_data *handle, struct uftrace_task_reader *task);
int read_task_args(struct uftrace_task_reader *task, struct uftrace_record *rstack, bool is_retval);
static inline bool is_user_record(struct uftrace_task_reader *task, struct uftrace_record *rec)
{
return rec == &task->ustack;
}
static inline bool is_kernel_record(struct uftrace_task_reader *task, struct uftrace_record *rec)
{
return rec == &task->kstack;
}
static inline bool is_event_record(struct uftrace_task_reader *task, struct uftrace_record *rec)
{
return rec == &task->estack;
}
static inline bool is_extern_record(struct uftrace_task_reader *task, struct uftrace_record *rec)
{
return rec == &task->xstack;
}
void setup_fstack_args(char *argspec, char *retspec, struct uftrace_data *handle,
struct uftrace_filter_setting *setting);
int fstack_setup_filters(struct uftrace_opts *opts, struct uftrace_data *handle);
struct uftrace_fstack *fstack_get(struct uftrace_task_reader *task, int idx);
int fstack_entry(struct uftrace_task_reader *task, struct uftrace_record *rstack,
struct uftrace_trigger *tr);
void fstack_exit(struct uftrace_task_reader *task);
int fstack_update(int type, struct uftrace_task_reader *task, struct uftrace_fstack *fstack);
struct uftrace_task_reader *fstack_skip(struct uftrace_data *handle,
struct uftrace_task_reader *task, int curr_depth,
struct uftrace_opts *opts);
bool fstack_check_filter(struct uftrace_task_reader *task);
bool fstack_check_opts(struct uftrace_task_reader *task, struct uftrace_opts *opts);
void fstack_check_filter_done(struct uftrace_task_reader *task);
bool is_sched_event(uint64_t addr);
bool is_sched_preempt_event(struct uftrace_task_reader *task, uint64_t addr);
void get_argspec_string(struct uftrace_task_reader *task, char *args, size_t len,
enum uftrace_argspec_string_bits str_mode);
#define EXTERN_DATA_MAX 1024
struct uftrace_extern_reader {
FILE *fp;
bool valid;
uint64_t time;
char msg[EXTERN_DATA_MAX];
struct uftrace_record rec;
};
int setup_extern_data(struct uftrace_data *handle, struct uftrace_opts *opts);
int read_extern_data(struct uftrace_data *handle, struct uftrace_extern_reader *extn);
struct uftrace_record *get_extern_record(struct uftrace_extern_reader *extn,
struct uftrace_record *rec);
int finish_extern_data(struct uftrace_data *handle);
static inline bool has_extern_data(struct uftrace_data *handle)
{
return handle->extn != NULL;
}
#endif /* UFTRACE_FSTACK_H */
|