@@ -157,6 +157,8 @@ EXAMPLE
#include <tracefs.h>
#include <traceeval.h>
+#define DELTA_NAME "delta"
+
struct data {
struct traceeval *teval_wakeup;
struct traceeval *teval_sched;
@@ -172,7 +174,6 @@ struct traceeval_type wakeup_keys[] = {
struct traceeval_type wakeup_vals[] = {
{
.name = "timestamp",
- .flags = TRACEEVAL_FL_TIMESTAMP,
.type = TRACEEVAL_TYPE_NUMBER_64,
}
};
@@ -190,14 +191,8 @@ struct traceeval_type sched_keys[] = {
struct traceeval_type sched_vals[] = {
{
- .name = "timestamp",
- .flags = TRACEEVAL_FL_TIMESTAMP,
- .type = TRACEEVAL_TYPE_NUMBER_64,
- },
- {
- .name = "delta",
- .flags = TRACEEVAL_FL_STAT,
- .type = TRACEEVAL_TYPE_NUMBER_64,
+ .name = DELTA_NAME,
+ .type = TRACEEVAL_TYPE_DELTA,
}
};
@@ -234,7 +229,7 @@ static int sched_callback(struct tep_event *event, struct tep_record *record, in
long pid;
struct traceeval_data wakeup_keys[1];
struct traceeval_data keys[2];
- struct traceeval_data vals[2];
+ struct traceeval_data vals[1];
const struct traceeval_data *results;
if (!next_pid_field) {
@@ -253,11 +248,10 @@ static int sched_callback(struct tep_event *event, struct tep_record *record, in
delta = record->ts - results[0].number_64;
traceeval_results_release(data->teval_wakeup, results);
- TRACEEVAL_SET_CSTRING(keys[0], record->data + next_comm_field->offset);
+ TRACEEVAL_SET_CSTRING(keys[0], (char *)record->data + next_comm_field->offset);
TRACEEVAL_SET_NUMBER(keys[1], pid);
- TRACEEVAL_SET_NUMBER_64(vals[0], record->ts);
- TRACEEVAL_SET_NUMBER_64(vals[1], delta);
+ TRACEEVAL_SET_DELTA(vals[0], delta, record->ts);
traceeval_insert(data->teval_sched, keys, vals);
@@ -292,7 +286,7 @@ static void show_latency(struct data *data)
while (traceeval_iterator_next(iter, &keys) > 0) {
struct traceeval_stat *stat;
- stat = traceeval_iterator_stat(iter, sched_vals[1].name);
+ stat = traceeval_iterator_stat(iter, DELTA_NAME);
if (!stat)
continue;
@@ -356,6 +350,9 @@ int main (int argc, char **argv)
show_latency(&data);
+ traceeval_release(data.teval_wakeup);
+ traceeval_release(data.teval_sched);
+
return 0;
}
--
@@ -132,6 +132,15 @@ and idle.
#include <trace-cmd.h>
#include <traceeval.h>
+enum sched_state {
+ RUNNING,
+ BLOCKED,
+ PREEMPT,
+ SLEEP,
+ IDLE,
+ OTHER
+};
+
static struct traceeval_type cpu_keys[] = {
{
.type = TRACEEVAL_TYPE_NUMBER,
@@ -143,7 +152,56 @@ static struct traceeval_type cpu_keys[] = {
},
};
-static struct traceeval_type process_keys[] = {
+static void add_cpu_data(struct traceeval *teval, int cpu, int state,
+ unsigned long long delta, unsigned long long ts)
+{
+ struct traceeval_data keys[2];
+ struct traceeval_data vals[1];
+
+ TRACEEVAL_SET_NUMBER(keys[0], cpu);
+ TRACEEVAL_SET_NUMBER(keys[1], state);
+
+ TRACEEVAL_SET_DELTA(vals[0], delta, ts);
+
+ traceeval_insert(teval, keys, vals);
+}
+
+static struct traceeval_type cpu_delta_keys[] = {
+ {
+ .type = TRACEEVAL_TYPE_NUMBER,
+ .name = "CPU",
+ },
+};
+
+static void start_cpu_data(struct traceeval *teval, int cpu, unsigned long long ts)
+{
+ struct traceeval_data keys[1];
+
+ TRACEEVAL_SET_NUMBER(keys[0], cpu);
+
+ traceeval_delta_start(teval, keys, NULL, ts);
+}
+
+static void continue_cpu_data(struct traceeval *teval, int cpu, unsigned long long ts)
+{
+ struct traceeval_data keys[1];
+
+ TRACEEVAL_SET_NUMBER(keys[0], cpu);
+
+ traceeval_delta_continue(teval, keys, NULL, ts);
+}
+
+static int stop_cpu_data(struct traceeval *teval, int cpu, unsigned long long ts,
+ unsigned long long *delta)
+{
+ struct traceeval_data keys[1];
+
+ TRACEEVAL_SET_NUMBER(keys[0], cpu);
+
+ return traceeval_delta_stop(teval, keys, NULL, ts, delta, NULL);
+}
+
+static struct traceeval_type task_keys[] = {
{
.type = TRACEEVAL_TYPE_STRING,
.name = "COMM"
@@ -154,122 +212,160 @@ static struct traceeval_type process_keys[] = {
},
};
-static struct traceeval_type process_data_vals[] = {
+static void release_pdata(const struct traceeval_type *type,
+ struct traceeval_data *data);
+
+static int copy_pdata(const struct traceeval_type *type,
+ struct traceeval_data *dst,
+ const struct traceeval_data *src)
+{
+ /* This prevents the release function getting called */
+ *dst = *src;
+ return 0;
+}
+
+static struct traceeval_type task_vals[] = {
{
.type = TRACEEVAL_TYPE_POINTER,
.name = "data",
+ .copy = copy_pdata,
+ .release = release_pdata,
+ },
+ {
+ .type = TRACEEVAL_TYPE_DELTA,
+ .name = "delta",
},
};
-static struct traceeval_type thread_keys[] = {
+static void add_task_data(struct traceeval *teval, const char *comm,
+ int state, void *pdata,
+ unsigned long long delta, unsigned long long ts)
+{
+ struct traceeval_data keys[2];
+ struct traceeval_data vals[2];
+
+ TRACEEVAL_SET_CSTRING(keys[0], comm);
+ TRACEEVAL_SET_NUMBER(keys[1], state);
+
+ /* Only save pdata for the running event (no duplicates) */
+ if (state != RUNNING)
+ pdata = NULL;
+
+ TRACEEVAL_SET_POINTER(vals[0], pdata);
+ TRACEEVAL_SET_DELTA(vals[1], delta, ts);
+
+ traceeval_insert(teval, keys, vals);
+}
+
+static struct traceeval_type task_delta_keys[] = {
{
.type = TRACEEVAL_TYPE_NUMBER,
- .name = "TID",
+ .name = "PID"
},
+};
+
+static struct traceeval_type task_delta_vals[] = {
{
.type = TRACEEVAL_TYPE_NUMBER,
- .name = "Schedule state",
+ .name = "Schedule state"
},
};
-static struct traceeval_type timestamp_vals[] = {
+static void start_task_data(struct traceeval *teval, int pid,
+ int state, unsigned long long ts)
+{
+ struct traceeval_data keys[1];
+ struct traceeval_data vals[1];
+
+ TRACEEVAL_SET_NUMBER(keys[0], pid);
+
+ TRACEEVAL_SET_NUMBER(vals[0], state);
+
+ traceeval_delta_start(teval, keys, vals, ts);
+}
+
+static int stop_task_data(struct traceeval *teval, int pid, unsigned long long ts,
+ unsigned long long *delta, int *state)
+{
+ struct traceeval_data keys[1];
+ const struct traceeval_data *results;
+ int ret;
+
+ TRACEEVAL_SET_NUMBER(keys[0], pid);
+
+ ret = traceeval_delta_stop(teval, keys, &results, ts, delta, NULL);
+ if (ret < 1)
+ return ret;
+
+ if (state)
+ *state = results[0].number;
+
+ traceeval_results_release(teval, results);
+
+ return ret;
+}
+
+static struct traceeval_type thread_keys[] = {
+ {
+ .type = TRACEEVAL_TYPE_NUMBER,
+ .name = "TID",
+ },
{
- .type = TRACEEVAL_TYPE_NUMBER_64,
- .name = "Timestamp",
- .flags = TRACEEVAL_FL_TIMESTAMP,
+ .type = TRACEEVAL_TYPE_NUMBER,
+ .name = "Schedule state",
},
};
static struct traceeval_type delta_vals[] = {
{
- .type = TRACEEVAL_TYPE_NUMBER_64,
+ .type = TRACEEVAL_TYPE_DELTA,
.name = "delta",
- .flags = TRACEEVAL_FL_STAT,
},
};
-enum sched_state {
- RUNNING,
- BLOCKED,
- PREEMPT,
- SLEEP,
- IDLE,
- OTHER
-};
+static void add_thread_data(struct traceeval *teval, int pid, int state,
+ unsigned long long delta, unsigned long long ts)
+{
+ struct traceeval_data keys[2];
+ struct traceeval_data vals[1];
-struct teval_pair {
- struct traceeval *start;
- struct traceeval *stop;
-};
+ TRACEEVAL_SET_NUMBER(keys[0], pid);
+ TRACEEVAL_SET_NUMBER(keys[1], state);
+
+ TRACEEVAL_SET_DELTA(vals[0], delta, ts);
+
+ traceeval_insert(teval, keys, vals);
+}
struct process_data {
- struct teval_pair teval_cpus;
- struct teval_pair teval_threads;
- char *comm;
- int state;
+ struct traceeval *teval_cpus;
+ struct traceeval *teval_threads;
};
struct task_data {
- struct teval_pair teval_cpus;
- struct teval_pair teval_processes;
- struct traceeval *teval_processes_data;
- char *comm;
-};
-
-enum command {
- START,
- STOP
+ struct traceeval *teval_cpus;
+ struct traceeval *teval_tasks;
+ const char *comm;
};
-static void update_process(struct task_data *tdata, const char *comm,
- enum sched_state state, enum command cmd,
- unsigned long long ts)
+static void init_process_data(struct process_data *pdata)
{
- struct traceeval_data keys[] = {
- DEFINE_TRACEEVAL_CSTRING( comm ),
- DEFINE_TRACEEVAL_NUMBER( state ),
- };
- struct traceeval_data vals[] = {
- DEFINE_TRACEEVAL_NUMBER_64( ts ),
- };
- struct traceeval_data new_vals[1] = { };
- const struct traceeval_data *results;
- int ret;
-
- switch (cmd) {
- case START:
- ret = traceeval_insert(tdata->teval_processes.start, keys, vals);
- return;
- case STOP:
- ret = traceeval_query(tdata->teval_processes.start, keys, &results);
- if (ret == 0)
- return;
- if (!results[0].number_64)
- break;
-
- TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64);
- ret = traceeval_insert(tdata->teval_processes.stop, keys, new_vals);
+ pdata->teval_cpus = traceeval_init(cpu_keys, delta_vals);
+ traceeval_delta_create(pdata->teval_cpus, cpu_delta_keys, NULL);
- /* Reset the start */
- TRACEEVAL_SET_NUMBER_64(new_vals[0], 0);
-
- ret = traceeval_insert(tdata->teval_processes.start, keys, new_vals);
- break;
- }
- traceeval_results_release(tdata->teval_processes.start, results);
+ pdata->teval_threads = traceeval_init(thread_keys, delta_vals);
}
-static void start_process(struct task_data *tdata, const char *comm,
- enum sched_state state, unsigned long long ts)
+static struct process_data *alloc_pdata(struct task_data *tdata, const char *comm)
{
- update_process(tdata, comm, state, START, ts);
-}
+ struct process_data *pdata;
-static void stop_process(struct task_data *tdata, const char *comm,
- enum sched_state state, unsigned long long ts)
-{
- update_process(tdata, comm, state, STOP, ts);
+ pdata = calloc(1, sizeof(*pdata));
+ init_process_data(pdata);
+ add_task_data(tdata->teval_tasks, comm, RUNNING, pdata, 0, 0);
+
+ return pdata;
}
static struct process_data *
@@ -283,174 +379,24 @@ get_process_data(struct task_data *tdata, const char *comm)
void *data;
int ret;
- ret = traceeval_query(tdata->teval_processes_data, keys, &results);
+ ret = traceeval_query(tdata->teval_tasks, keys, &results);
if (ret == 0)
- return NULL;
+ return alloc_pdata(tdata, comm);
data = results[0].pointer;
- traceeval_results_release(tdata->teval_processes_data, results);
+ traceeval_results_release(tdata->teval_tasks, results);
return data;
}
-void set_process_data(struct task_data *tdata, const char *comm, void *data)
+static enum sched_state get_state(unsigned long long val)
{
- struct traceeval_data keys[] = {
- DEFINE_TRACEEVAL_CSTRING( comm ),
- DEFINE_TRACEEVAL_NUMBER( RUNNING ),
- };
- struct traceeval_data new_vals[1] = { };
- const struct traceeval_data *results;
- int ret;
-
- ret = traceeval_query(tdata->teval_processes_data, keys, &results);
- if (ret > 0)
- goto out; /* It already exists ? */
-
- TRACEEVAL_SET_POINTER(new_vals[0], data);
- ret = traceeval_insert(tdata->teval_processes_data, keys, new_vals);
-
- out:
- traceeval_results_release(tdata->teval_processes_data, results);
-}
-
-static void update_cpu(struct teval_pair *teval_pair, int cpu,
- enum sched_state state, enum command cmd,
- unsigned long long ts)
-{
- const struct traceeval_data *results;
- struct traceeval_data keys[] = {
- DEFINE_TRACEEVAL_NUMBER( cpu ),
- DEFINE_TRACEEVAL_NUMBER( state ),
- };
- struct traceeval_data vals[] = {
- DEFINE_TRACEEVAL_NUMBER_64( ts ),
- };
- struct traceeval_data new_vals[1] = { };
- int ret;
-
- switch (cmd) {
- case START:
- /* Only set if the timestamp is zero (or doesn't exist) */
- ret = traceeval_query(teval_pair->start, keys, &results);
- if (ret > 0) {
- if (results[0].number_64)
- break;
- }
- ret = traceeval_insert(teval_pair->start, keys, vals);
- break;
- case STOP:
- ret = traceeval_query(teval_pair->start, keys, &results);
- if (ret == 0)
- return;
-
- if (!results[0].number_64)
- break;
-
- TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64);
-
- ret = traceeval_insert(teval_pair->stop, keys, new_vals);
-
- /* Reset the start */
- TRACEEVAL_SET_NUMBER_64(new_vals[0], 0);
- ret = traceeval_insert(teval_pair->start, keys, new_vals);
-
- break;
- default:
- return;
- }
- traceeval_results_release(teval_pair->start, results);
-}
-
-static void start_cpu(struct teval_pair *teval_pair, int cpu,
- enum sched_state state, unsigned long long ts)
-{
- update_cpu(teval_pair, cpu, state, START, ts);
-}
-
-static void stop_cpu(struct teval_pair *teval_pair, int cpu,
- enum sched_state state, unsigned long long ts)
-{
- update_cpu(teval_pair, cpu, state, STOP, ts);
-}
-
-static void update_thread(struct process_data *pdata, int tid,
- enum sched_state state, enum command cmd,
- unsigned long long ts)
-{
- const struct traceeval_data *results;
- struct traceeval_data keys[] = {
- DEFINE_TRACEEVAL_NUMBER( tid ),
- DEFINE_TRACEEVAL_NUMBER( state ),
- };
- struct traceeval_data vals[] = {
- DEFINE_TRACEEVAL_NUMBER_64( ts ),
- };
- struct traceeval_data new_vals[1] = { };
- int ret;
-
- switch (cmd) {
- case START:
- ret = traceeval_insert(pdata->teval_threads.start, keys, vals);
- return;
- case STOP:
- ret = traceeval_query(pdata->teval_threads.start, keys, &results);
- if (ret == 0)
- return;
-
- TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64);
-
- ret = traceeval_insert(pdata->teval_threads.stop, keys, new_vals);
- traceeval_results_release(pdata->teval_threads.start, results);
- return;
- }
-}
-
-static void start_thread(struct process_data *pdata, int tid,
- enum sched_state state, unsigned long long ts)
-{
- update_thread(pdata, tid, state, START, ts);
-}
-
-static void stop_thread(struct process_data *pdata, int tid,
- enum sched_state state, unsigned long long ts)
-{
- update_thread(pdata, tid, state, STOP, ts);
-}
-
-static struct tep_format_field *get_field(struct tep_event *event, const char *name)
-{
- static struct tep_format_field *field;
-
- field = tep_find_field(event, name);
- if (!field) {
- fprintf(stderr, "Could not find field %s for %s",
- name, event->name);
- exit(-1);
- }
-
- return field;
-}
-
-static void init_process_data(struct process_data *pdata)
-{
-
- pdata->teval_cpus.start = traceeval_init(cpu_keys, timestamp_vals);
- pdata->teval_cpus.stop = traceeval_init(cpu_keys, delta_vals);
-
- pdata->teval_threads.start = traceeval_init(thread_keys, timestamp_vals);
-
- pdata->teval_threads.stop = traceeval_init(thread_keys, delta_vals);
-}
-
-static struct process_data *alloc_pdata(struct task_data *tdata, const char *comm)
-{
- struct process_data *pdata;
-
- pdata = calloc(1, sizeof(*pdata));
- init_process_data(pdata);
- set_process_data(tdata, comm, pdata);
-
- return pdata;
+ if (val & 1)
+ return SLEEP;
+ if (val & 2)
+ return BLOCKED;
+ if (val & 0xfff)
+ return OTHER;
+ return PREEMPT;
}
static void sched_out(struct task_data *tdata, const char *comm,
@@ -459,54 +405,41 @@ static void sched_out(struct task_data *tdata, const char *comm,
struct tep_format_field *prev_state)
{
struct process_data *pdata;
+ unsigned long long delta;
unsigned long long val;
+ int state;
int pid;
+ int ret;
tep_read_number_field(prev_pid, record->data, &val);
/* Ignore the idle task */
pid = val;
if (!pid) {
- /* Record the runtime for the process CPUs */
- stop_cpu(&tdata->teval_cpus, record->cpu, IDLE, record->ts);
+ /* Coming from idle */
+ ret = stop_cpu_data(tdata->teval_cpus, record->cpu, record->ts, &delta);
+ if (ret > 0)
+ add_cpu_data(tdata->teval_cpus, record->cpu, IDLE, delta,
+ record->ts);
return;
}
- /* The process is scheduling out. Stop the run time. */
- update_process(tdata, comm, RUNNING, STOP, record->ts);
-
- /* Get the process data from the process running state */
+ /* Get the process data for this task */
pdata = get_process_data(tdata, comm);
- if (!pdata)
- pdata = alloc_pdata(tdata, comm);
+
+ ret = stop_task_data(tdata->teval_tasks, pid, record->ts, &delta, NULL);
+
+ if (ret > 0) {
+ /* Record the running state */
+ add_task_data(tdata->teval_tasks, comm, RUNNING, pdata, delta, record->ts);
+ add_thread_data(pdata->teval_threads, pid, RUNNING, delta, record->ts);
+ }
tep_read_number_field(prev_state, record->data, &val);
- val &= 3;
- /*
- * Save the state the process is exiting with. Will need this
- * when scheduled back in.
- */
- if (!val)
- pdata->state = PREEMPT;
- else if (val & 1)
- pdata->state = SLEEP;
- else if (val & 2)
- pdata->state = BLOCKED;
-
- /* Record the state timings for the process */
- start_process(tdata, comm, pdata->state, record->ts);
-
- /* Record the state timings for the individual thread */
- stop_thread(pdata, pid, RUNNING, record->ts);
-
- /* Record the state timings for the individual thread */
- start_thread(pdata, pid, pdata->state, record->ts);
-
- /* Record the runtime for the process CPUs */
- stop_cpu(&pdata->teval_cpus, record->cpu, RUNNING, record->ts);
-
- /* Record the runtime for the all CPUs */
- stop_cpu(&tdata->teval_cpus, record->cpu, RUNNING, record->ts);
+ state = get_state(val);
+
+ /* Start the off-cpu time and record the state */
+ start_task_data(tdata->teval_tasks, pid, state, record->ts);
}
static void sched_in(struct task_data *tdata, const char *comm,
@@ -514,49 +447,58 @@ static void sched_in(struct task_data *tdata, const char *comm,
struct tep_record *record, struct tep_format_field *next_pid)
{
struct process_data *pdata;
+ unsigned long long delta;
unsigned long long val;
- bool is_new = false;
+ int state;
int pid;
+ int ret;
tep_read_number_field(next_pid, record->data, &val);
pid = val;
/* Ignore the idle task */
if (!pid) {
- /* Record the runtime for the process CPUs */
- start_cpu(&tdata->teval_cpus, record->cpu, IDLE, record->ts);
+
+ /* Going to idle, get the time the CPU was running */
+ ret = stop_cpu_data(tdata->teval_cpus, record->cpu, record->ts, &delta);
+ if (ret > 0)
+ add_cpu_data(tdata->teval_cpus, record->cpu, RUNNING,
+ delta, record->ts);
+
+ /* Start recording the time the CPU is idle */
+ start_cpu_data(tdata->teval_cpus, record->cpu, record->ts);
return;
}
- /* Start recording the running time of this process */
- start_process(tdata, comm, RUNNING, record->ts);
+ /* Continue the CPU as running */
+ continue_cpu_data(tdata->teval_cpus, record->cpu, record->ts);
pdata = get_process_data(tdata, comm);
- /* Start recording the running time of process CPUs */
- start_cpu(&tdata->teval_cpus, record->cpu, RUNNING, record->ts);
+ /* Record the time the task was off the CPU and why */
+ ret = stop_task_data(tdata->teval_tasks, pid, record->ts, &delta, &state);
- /* If there was no pdata, then this process did not go through sched out */
- if (!pdata) {
- pdata = alloc_pdata(tdata, comm);
- is_new = true;
+ if (ret > 0) {
+ add_task_data(tdata->teval_tasks, comm, state, pdata, delta, record->ts);
+ add_thread_data(pdata->teval_threads, pid, state, delta, record->ts);
}
- /* Record the state timings for the individual thread */
- start_thread(pdata, pid, RUNNING, record->ts);
-
- /* Start recording the running time of process CPUs */
- start_cpu(&pdata->teval_cpus, record->cpu, RUNNING, record->ts);
+ /* Start recording the running of this task */
+ start_task_data(tdata->teval_tasks, pid, RUNNING, record->ts);
+}
- /* If it was just created, there's nothing to stop */
- if (is_new)
- return;
+static struct tep_format_field *get_field(struct tep_event *event, const char *name)
+{
+ static struct tep_format_field *field;
- /* Stop recording the thread time for its scheduled out state */
- stop_thread(pdata, val, pdata->state, record->ts);
+ field = tep_find_field(event, name);
+ if (!field) {
+ fprintf(stderr, "Could not find field %s for %s",
+ name, event->name);
+ exit(-1);
+ }
- /* Stop recording the process time for its scheduled out state */
- stop_process(tdata, comm, pdata->state, record->ts);
+ return field;
}
static int switch_func(struct tracecmd_input *handle, struct tep_event *event,
@@ -747,8 +689,8 @@ static void display_threads(struct traceeval *teval)
static void display_process(struct process_data *pdata)
{
- display_threads(pdata->teval_threads.stop);
- display_cpus(pdata->teval_cpus.stop);
+ display_threads(pdata->teval_threads);
+ display_cpus(pdata->teval_cpus);
printf("\n");
}
@@ -773,10 +715,9 @@ static void display_process_stats(struct traceeval *teval,
}
}
-static void display_processes(struct traceeval *teval,
- struct traceeval *teval_data)
+static void display_processes(struct traceeval *teval)
{
- struct traceeval_iterator *iter = traceeval_iterator_get(teval_data);
+ struct traceeval_iterator *iter = traceeval_iterator_get(teval);
const struct traceeval_data *keys;
traceeval_iterator_sort_custom(iter, compare_pdata, teval);
@@ -788,7 +729,7 @@ static void display_processes(struct traceeval *teval,
traceeval_iterator_query(iter, &results);
pdata = results[0].pointer;
- traceeval_results_release(teval_data, results);
+ traceeval_results_release(teval, results);
if (!pdata)
continue;
@@ -804,17 +745,15 @@ static void display_processes(struct traceeval *teval,
static void display(struct task_data *tdata)
{
- struct traceeval *teval = tdata->teval_cpus.stop;
+ struct traceeval *teval = tdata->teval_cpus;
struct traceeval_iterator *iter = traceeval_iterator_get(teval);
const struct traceeval_data *keys;
struct traceeval_stat *stat;
unsigned long long total_time = 0;
unsigned long long idle_time = 0;
- if (tdata->comm) {
- return display_processes(tdata->teval_processes.stop,
- tdata->teval_processes_data);
- }
+ if (tdata->comm)
+ return display_processes(tdata->teval_tasks);
printf("Total:\n");
@@ -843,14 +782,30 @@ static void display(struct task_data *tdata)
printf(" Total idle time (us):");
print_microseconds(16, idle_time);
- display_cpus(tdata->teval_cpus.stop);
+ display_cpus(tdata->teval_cpus);
printf("\n");
- display_processes(tdata->teval_processes.stop, tdata->teval_processes_data);
+ display_processes(tdata->teval_tasks);
+}
+
+static void release_pdata(const struct traceeval_type *type,
+ struct traceeval_data *data)
+{
+ struct process_data *pdata;
+
+ if (!data || !data->pointer)
+ return;
+
+ pdata = data->pointer;
+ traceeval_release(pdata->teval_cpus);
+ traceeval_release(pdata->teval_threads);
+ free(pdata);
}
static void free_tdata(struct task_data *tdata)
{
+ traceeval_release(tdata->teval_tasks);
+ traceeval_release(tdata->teval_cpus);
}
int main (int argc, char **argv)
@@ -858,6 +813,8 @@ int main (int argc, char **argv)
struct tracecmd_input *handle;
struct task_data data;
+ traceeval_set_log_level(TEVAL_WARN);
+
memset(&data, 0, sizeof(data));
if (argc < 2) {
@@ -871,13 +828,11 @@ int main (int argc, char **argv)
exit(-1);
}
- data.teval_processes.start = traceeval_init(process_keys, timestamp_vals);
- data.teval_processes_data = traceeval_init(process_keys, process_data_vals);
- data.teval_processes.stop = traceeval_init(process_keys, delta_vals);
-
+ data.teval_tasks = traceeval_init(task_keys, task_vals);
+ traceeval_delta_create(data.teval_tasks, task_delta_keys, task_delta_vals);
- data.teval_cpus.start = traceeval_init(cpu_keys, timestamp_vals);
- data.teval_cpus.stop = traceeval_init(cpu_keys, delta_vals);
+ data.teval_cpus = traceeval_init(cpu_keys, delta_vals);
+ traceeval_delta_create(data.teval_cpus, cpu_delta_keys, NULL);
tracecmd_follow_event(handle, "sched", "sched_switch", switch_func, &data);
@@ -109,25 +109,7 @@ EXAMPLE
#include <trace-cmd.h>
#include <traceeval.h>
-struct data {
- struct traceeval *teval_wakeup;
- struct traceeval *teval_sched;
-};
-
-struct traceeval_type wakeup_keys[] = {
- {
- .name = "PID",
- .type = TRACEEVAL_TYPE_NUMBER,
- }
-};
-
-struct traceeval_type wakeup_vals[] = {
- {
- .name = "timestamp",
- .flags = TRACEEVAL_FL_TIMESTAMP,
- .type = TRACEEVAL_TYPE_NUMBER_64,
- }
-};
+#define DELTA_NAME "delta"
struct traceeval_type sched_keys[] = {
{
@@ -142,26 +124,27 @@ struct traceeval_type sched_keys[] = {
struct traceeval_type sched_vals[] = {
{
- .name = "timestamp",
- .flags = TRACEEVAL_FL_TIMESTAMP,
- .type = TRACEEVAL_TYPE_NUMBER_64,
- },
+ .name = DELTA_NAME,
+ .type = TRACEEVAL_TYPE_DELTA,
+ }
+};
+
+struct traceeval_type delta_keys[] = {
{
- .name = "delta",
- .flags = TRACEEVAL_FL_STAT,
- .type = TRACEEVAL_TYPE_NUMBER_64,
+ .name = "PID",
+ .type = TRACEEVAL_TYPE_NUMBER,
}
};
+
static int wakeup_callback(struct tracecmd_input *handle, struct tep_event *event,
- struct tep_record *record, int cpu, void *d)
+ struct tep_record *record, int cpu, void *data)
{
static struct tep_format_field *pid_field;
- struct data *data = d;
+ struct traceeval_data keys[1];
+ struct traceeval *teval = data;
unsigned long long val;
long pid;
- struct traceeval_data keys[1];
- struct traceeval_data vals[1];
if (!pid_field)
pid_field = tep_find_field(event, "pid");
@@ -170,26 +153,24 @@ static int wakeup_callback(struct tracecmd_input *handle, struct tep_event *even
pid = val;
TRACEEVAL_SET_NUMBER(keys[0], pid);
- TRACEEVAL_SET_NUMBER_64(vals[0], record->ts);
- traceeval_insert(data->teval_wakeup, keys, vals);
+ traceeval_delta_start(teval, keys, NULL, record->ts);
return 0;
}
static int sched_callback(struct tracecmd_input *handle, struct tep_event *event,
- struct tep_record *record, int cpu, void *d)
+ struct tep_record *record, int cpu, void *data)
{
static struct tep_format_field *next_pid_field;
static struct tep_format_field *next_comm_field;
- struct data *data = d;
+ struct traceeval_data delta_keys[1];
+ struct traceeval_data keys[2];
+ struct traceeval_data vals[1];
+ struct traceeval *teval = data;
unsigned long long delta;
unsigned long long val;
long pid;
- struct traceeval_data wakeup_keys[1];
- struct traceeval_data keys[2];
- struct traceeval_data vals[2];
- const struct traceeval_data *results;
if (!next_pid_field) {
next_pid_field = tep_find_field(event, "next_pid");
@@ -199,28 +180,24 @@ static int sched_callback(struct tracecmd_input *handle, struct tep_event *event
tep_read_number_field(next_pid_field, record->data, &val);
pid = val;
- TRACEEVAL_SET_NUMBER(wakeup_keys[0], pid);
+ TRACEEVAL_SET_NUMBER(delta_keys[0], pid);
- if (traceeval_query(data->teval_wakeup, wakeup_keys, &results) <= 0)
+ if (traceeval_delta_stop(teval, delta_keys, NULL, record->ts, &delta, NULL) < 1)
return 0;
- delta = record->ts - results[0].number_64;
- traceeval_results_release(data->teval_wakeup, results);
-
- TRACEEVAL_SET_CSTRING(keys[0], record->data + next_comm_field->offset);
+ TRACEEVAL_SET_CSTRING(keys[0], (char *)record->data + next_comm_field->offset);
TRACEEVAL_SET_NUMBER(keys[1], pid);
- TRACEEVAL_SET_NUMBER_64(vals[0], record->ts);
- TRACEEVAL_SET_NUMBER_64(vals[1], delta);
+ TRACEEVAL_SET_DELTA(vals[0], delta, record->ts);
- traceeval_insert(data->teval_sched, keys, vals);
+ traceeval_insert(teval, keys, vals);
return 0;
}
-static void show_latency(struct data *data)
+static void show_latency(struct traceeval *teval)
{
- struct traceeval_iterator *iter = traceeval_iterator_get(data->teval_sched);
+ struct traceeval_iterator *iter = traceeval_iterator_get(teval);
const struct traceeval_data *keys;
printf("\n");
@@ -229,7 +206,7 @@ static void show_latency(struct data *data)
unsigned long long val;
unsigned long long ts;
- stat = traceeval_iterator_stat(iter, sched_vals[1].name);
+ stat = traceeval_iterator_stat(iter, DELTA_NAME);
if (!stat)
continue;
@@ -251,15 +228,15 @@ static void show_latency(struct data *data)
int main (int argc, char **argv)
{
struct tracecmd_input *handle;
- struct data data;
+ struct traceeval *teval;
if (argc < 2) {
printf("usage: wake-lat trace.dat\n");
exit(-1);
}
- data.teval_wakeup = traceeval_init(wakeup_keys, wakeup_vals);
- data.teval_sched = traceeval_init(sched_keys, sched_vals);
+ teval = traceeval_init(sched_keys, sched_vals);
+ traceeval_delta_create(teval, delta_keys, NULL);
handle = tracecmd_open(argv[1], TRACECMD_FL_LOAD_NO_PLUGINS);
if (!handle) {
@@ -267,12 +244,14 @@ int main (int argc, char **argv)
exit(-1);
}
- tracecmd_follow_event(handle, "sched", "sched_waking", wakeup_callback, &data);
- tracecmd_follow_event(handle, "sched", "sched_switch", sched_callback, &data);
+ tracecmd_follow_event(handle, "sched", "sched_waking", wakeup_callback, teval);
+ tracecmd_follow_event(handle, "sched", "sched_switch", sched_callback, teval);
tracecmd_iterate_events(handle, NULL, 0, NULL, NULL);
- show_latency(&data);
+ show_latency(teval);
+
+ traceeval_release(teval);
return 0;
}