]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'perf/test' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
authorIngo Molnar <mingo@elte.hu>
Mon, 10 May 2010 06:20:19 +0000 (08:20 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 10 May 2010 06:20:19 +0000 (08:20 +0200)
include/trace/events/lock.h
kernel/lockdep.c
tools/perf/builtin-lock.c
tools/perf/builtin-record.c
tools/perf/util/event.h
tools/perf/util/session.c
tools/perf/util/session.h

index 5c1dcfc16c6037019d8bcecf4e7c2fa4f3649505..2821b86de63b9674d6ed3a68c7496f022b3cdff6 100644 (file)
@@ -35,15 +35,15 @@ TRACE_EVENT(lock_acquire,
                  __get_str(name))
 );
 
-TRACE_EVENT(lock_release,
+DECLARE_EVENT_CLASS(lock,
 
-       TP_PROTO(struct lockdep_map *lock, int nested, unsigned long ip),
+       TP_PROTO(struct lockdep_map *lock, unsigned long ip),
 
-       TP_ARGS(lock, nested, ip),
+       TP_ARGS(lock, ip),
 
        TP_STRUCT__entry(
-               __string(name, lock->name)
-               __field(void *, lockdep_addr)
+               __string(       name,   lock->name      )
+               __field(        void *, lockdep_addr    )
        ),
 
        TP_fast_assign(
@@ -51,51 +51,30 @@ TRACE_EVENT(lock_release,
                __entry->lockdep_addr = lock;
        ),
 
-       TP_printk("%p %s",
-                 __entry->lockdep_addr, __get_str(name))
+       TP_printk("%p %s",  __entry->lockdep_addr, __get_str(name))
 );
 
-#ifdef CONFIG_LOCK_STAT
-
-TRACE_EVENT(lock_contended,
+DEFINE_EVENT(lock, lock_release,
 
        TP_PROTO(struct lockdep_map *lock, unsigned long ip),
 
-       TP_ARGS(lock, ip),
+       TP_ARGS(lock, ip)
+);
 
-       TP_STRUCT__entry(
-               __string(name, lock->name)
-               __field(void *, lockdep_addr)
-       ),
+#ifdef CONFIG_LOCK_STAT
 
-       TP_fast_assign(
-               __assign_str(name, lock->name);
-               __entry->lockdep_addr = lock;
-       ),
+DEFINE_EVENT(lock, lock_contended,
 
-       TP_printk("%p %s",
-                 __entry->lockdep_addr, __get_str(name))
-);
+       TP_PROTO(struct lockdep_map *lock, unsigned long ip),
 
-TRACE_EVENT(lock_acquired,
-       TP_PROTO(struct lockdep_map *lock, unsigned long ip, s64 waittime),
+       TP_ARGS(lock, ip)
+);
 
-       TP_ARGS(lock, ip, waittime),
+DEFINE_EVENT(lock, lock_acquired,
 
-       TP_STRUCT__entry(
-               __string(name, lock->name)
-               __field(s64, wait_nsec)
-               __field(void *, lockdep_addr)
-       ),
+       TP_PROTO(struct lockdep_map *lock, unsigned long ip),
 
-       TP_fast_assign(
-               __assign_str(name, lock->name);
-               __entry->wait_nsec = waittime;
-               __entry->lockdep_addr = lock;
-       ),
-       TP_printk("%p %s (%llu ns)", __entry->lockdep_addr,
-                 __get_str(name),
-                 __entry->wait_nsec)
+       TP_ARGS(lock, ip)
 );
 
 #endif
index 2594e1ce41cbf12889b44deb3fc202c0a5c30fa2..e9c759f06c1d114d5ab3d1bda286b5f30c6b194b 100644 (file)
@@ -3227,7 +3227,7 @@ void lock_release(struct lockdep_map *lock, int nested,
        raw_local_irq_save(flags);
        check_flags(flags);
        current->lockdep_recursion = 1;
-       trace_lock_release(lock, nested, ip);
+       trace_lock_release(lock, ip);
        __lock_release(lock, nested, ip);
        current->lockdep_recursion = 0;
        raw_local_irq_restore(flags);
@@ -3380,7 +3380,7 @@ found_it:
                hlock->holdtime_stamp = now;
        }
 
-       trace_lock_acquired(lock, ip, waittime);
+       trace_lock_acquired(lock, ip);
 
        stats = get_lock_stats(hlock_class(hlock));
        if (waittime) {
index 6605000ed73d0b8c7a56d4319e34fbbf351b880e..e18dfdc2948aedf862c51092001388ddb7bc0e5c 100644 (file)
@@ -387,7 +387,20 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr)
        return seq;
 }
 
-static int bad_hist[4];
+enum broken_state {
+       BROKEN_ACQUIRE,
+       BROKEN_ACQUIRED,
+       BROKEN_CONTENDED,
+       BROKEN_RELEASE,
+       BROKEN_MAX,
+};
+
+static int bad_hist[BROKEN_MAX];
+
+enum acquire_flags {
+       TRY_LOCK = 1,
+       READ_LOCK = 2,
+};
 
 static void
 report_lock_acquire_event(struct trace_acquire_event *acquire_event,
@@ -413,9 +426,9 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
                if (!acquire_event->flag) {
                        seq->state = SEQ_STATE_ACQUIRING;
                } else {
-                       if (acquire_event->flag & 1)
+                       if (acquire_event->flag & TRY_LOCK)
                                ls->nr_trylock++;
-                       if (acquire_event->flag & 2)
+                       if (acquire_event->flag & READ_LOCK)
                                ls->nr_readlock++;
                        seq->state = SEQ_STATE_READ_ACQUIRED;
                        seq->read_count = 1;
@@ -423,7 +436,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
                }
                break;
        case SEQ_STATE_READ_ACQUIRED:
-               if (acquire_event->flag & 2) {
+               if (acquire_event->flag & READ_LOCK) {
                        seq->read_count++;
                        ls->nr_acquired++;
                        goto end;
@@ -437,7 +450,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
 broken:
                /* broken lock sequence, discard it */
                ls->discard = 1;
-               bad_hist[0]++;
+               bad_hist[BROKEN_ACQUIRE]++;
                list_del(&seq->list);
                free(seq);
                goto end;
@@ -481,10 +494,9 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
        case SEQ_STATE_CONTENDED:
                contended_term = timestamp - seq->prev_event_time;
                ls->wait_time_total += contended_term;
-
                if (contended_term < ls->wait_time_min)
                        ls->wait_time_min = contended_term;
-               else if (ls->wait_time_max < contended_term)
+               if (ls->wait_time_max < contended_term)
                        ls->wait_time_max = contended_term;
                break;
        case SEQ_STATE_RELEASED:
@@ -492,7 +504,7 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
        case SEQ_STATE_READ_ACQUIRED:
                /* broken lock sequence, discard it */
                ls->discard = 1;
-               bad_hist[1]++;
+               bad_hist[BROKEN_ACQUIRED]++;
                list_del(&seq->list);
                free(seq);
                goto end;
@@ -540,7 +552,7 @@ report_lock_contended_event(struct trace_contended_event *contended_event,
        case SEQ_STATE_CONTENDED:
                /* broken lock sequence, discard it */
                ls->discard = 1;
-               bad_hist[2]++;
+               bad_hist[BROKEN_CONTENDED]++;
                list_del(&seq->list);
                free(seq);
                goto end;
@@ -594,7 +606,7 @@ report_lock_release_event(struct trace_release_event *release_event,
        case SEQ_STATE_RELEASED:
                /* broken lock sequence, discard it */
                ls->discard = 1;
-               bad_hist[3]++;
+               bad_hist[BROKEN_RELEASE]++;
                goto free_seq;
                break;
        default:
@@ -713,6 +725,21 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
                process_lock_release_event(data, event, cpu, timestamp, thread);
 }
 
+static void print_bad_events(int bad, int total)
+{
+       /* Output for debug, this have to be removed */
+       int i;
+       const char *name[4] =
+               { "acquire", "acquired", "contended", "release" };
+
+       pr_info("\n=== output for debug===\n\n");
+       pr_info("bad: %d, total: %d\n", bad, total);
+       pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100);
+       pr_info("histogram of events caused bad sequence\n");
+       for (i = 0; i < BROKEN_MAX; i++)
+               pr_info(" %10s: %d\n", name[i], bad_hist[i]);
+}
+
 /* TODO: various way to print, coloring, nano or milli sec */
 static void print_result(void)
 {
@@ -720,15 +747,15 @@ static void print_result(void)
        char cut_name[20];
        int bad, total;
 
-       printf("%20s ", "Name");
-       printf("%10s ", "acquired");
-       printf("%10s ", "contended");
+       pr_info("%20s ", "Name");
+       pr_info("%10s ", "acquired");
+       pr_info("%10s ", "contended");
 
-       printf("%15s ", "total wait (ns)");
-       printf("%15s ", "max wait (ns)");
-       printf("%15s ", "min wait (ns)");
+       pr_info("%15s ", "total wait (ns)");
+       pr_info("%15s ", "max wait (ns)");
+       pr_info("%15s ", "min wait (ns)");
 
-       printf("\n\n");
+       pr_info("\n\n");
 
        bad = total = 0;
        while ((st = pop_from_result())) {
@@ -741,7 +768,7 @@ static void print_result(void)
 
                if (strlen(st->name) < 16) {
                        /* output raw name */
-                       printf("%20s ", st->name);
+                       pr_info("%20s ", st->name);
                } else {
                        strncpy(cut_name, st->name, 16);
                        cut_name[16] = '.';
@@ -749,33 +776,40 @@ static void print_result(void)
                        cut_name[18] = '.';
                        cut_name[19] = '\0';
                        /* cut off name for saving output style */
-                       printf("%20s ", cut_name);
+                       pr_info("%20s ", cut_name);
                }
 
-               printf("%10u ", st->nr_acquired);
-               printf("%10u ", st->nr_contended);
+               pr_info("%10u ", st->nr_acquired);
+               pr_info("%10u ", st->nr_contended);
 
-               printf("%15llu ", st->wait_time_total);
-               printf("%15llu ", st->wait_time_max);
-               printf("%15llu ", st->wait_time_min == ULLONG_MAX ?
+               pr_info("%15llu ", st->wait_time_total);
+               pr_info("%15llu ", st->wait_time_max);
+               pr_info("%15llu ", st->wait_time_min == ULLONG_MAX ?
                       0 : st->wait_time_min);
-               printf("\n");
+               pr_info("\n");
        }
 
-       {
-               /* Output for debug, this have to be removed */
-               int i;
-               const char *name[4] =
-                       { "acquire", "acquired", "contended", "release" };
+       print_bad_events(bad, total);
+}
 
-               printf("\n=== output for debug===\n\n");
-               printf("bad:%d, total:%d\n", bad, total);
-               printf("bad rate:%f\n", (double)(bad / total));
+static int                     info_threads;
+static int                     info_map;
 
-               printf("histogram of events caused bad sequence\n");
-               for (i = 0; i < 4; i++)
-                       printf(" %10s: %d\n", name[i], bad_hist[i]);
-       }
+static void dump_threads(void)
+{
+       struct thread_stat *st;
+       struct rb_node *node;
+       struct thread *t;
+
+       pr_info("%10s: comm\n", "Thread ID");
+
+       node = rb_first(&thread_stats);
+       while (node) {
+               st = container_of(node, struct thread_stat, rb);
+               t = perf_session__findnew(session, st->tid);
+               pr_info("%10d: %s\n", st->tid, t->comm);
+               node = rb_next(node);
+       };
 }
 
 static void dump_map(void)
@@ -783,13 +817,24 @@ static void dump_map(void)
        unsigned int i;
        struct lock_stat *st;
 
+       pr_info("Address of instance: name of class\n");
        for (i = 0; i < LOCKHASH_SIZE; i++) {
                list_for_each_entry(st, &lockhash_table[i], hash_entry) {
-                       printf("%p: %s\n", st->addr, st->name);
+                       pr_info(" %p: %s\n", st->addr, st->name);
                }
        }
 }
 
+static void dump_info(void)
+{
+       if (info_threads)
+               dump_threads();
+       else if (info_map)
+               dump_map();
+       else
+               die("Unknown type of information\n");
+}
+
 static int process_sample_event(event_t *self, struct perf_session *s)
 {
        struct sample_data data;
@@ -858,6 +903,19 @@ static const struct option report_options[] = {
        OPT_END()
 };
 
+static const char * const info_usage[] = {
+       "perf lock info [<options>]",
+       NULL
+};
+
+static const struct option info_options[] = {
+       OPT_BOOLEAN('t', "threads", &info_threads,
+                   "dump thread list in perf.data"),
+       OPT_BOOLEAN('m', "map", &info_map,
+                   "map of lock instances (name:address table)"),
+       OPT_END()
+};
+
 static const char * const lock_usage[] = {
        "perf lock [<options>] {record|trace|report}",
        NULL
@@ -872,7 +930,6 @@ static const struct option lock_options[] = {
 
 static const char *record_args[] = {
        "record",
-       "-a",
        "-R",
        "-f",
        "-m", "1024",
@@ -929,12 +986,18 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used)
        } else if (!strcmp(argv[0], "trace")) {
                /* Aliased to 'perf trace' */
                return cmd_trace(argc, argv, prefix);
-       } else if (!strcmp(argv[0], "map")) {
+       } else if (!strcmp(argv[0], "info")) {
+               if (argc) {
+                       argc = parse_options(argc, argv,
+                                            info_options, info_usage, 0);
+                       if (argc)
+                               usage_with_options(info_usage, info_options);
+               }
                /* recycling report_lock_ops */
                trace_handler = &report_lock_ops;
                setup_pager();
                read_events();
-               dump_map();
+               dump_info();
        } else {
                usage_with_options(lock_usage, lock_options);
        }
index d3981ac50e1dc08142b6b5a329401916d6b537cc..6b77b285fe10735719dc42891c779c688369cf12 100644 (file)
@@ -494,6 +494,29 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
                       " relocation symbol.\n", machine->pid);
 }
 
+static struct perf_event_header finished_round_event = {
+       .size = sizeof(struct perf_event_header),
+       .type = PERF_RECORD_FINISHED_ROUND,
+};
+
+static void mmap_read_all(void)
+{
+       int i, counter, thread;
+
+       for (i = 0; i < nr_cpu; i++) {
+               for (counter = 0; counter < nr_counters; counter++) {
+                       for (thread = 0; thread < thread_num; thread++) {
+                               if (mmap_array[i][counter][thread].base)
+                                       mmap_read(&mmap_array[i][counter][thread]);
+                       }
+
+               }
+       }
+
+       if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
+               write_output(&finished_round_event, sizeof(finished_round_event));
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
        int i, counter;
@@ -726,16 +749,7 @@ static int __cmd_record(int argc, const char **argv)
                int hits = samples;
                int thread;
 
-               for (i = 0; i < nr_cpu; i++) {
-                       for (counter = 0; counter < nr_counters; counter++) {
-                               for (thread = 0;
-                                       thread < thread_num; thread++) {
-                                       if (mmap_array[i][counter][thread].base)
-                                               mmap_read(&mmap_array[i][counter][thread]);
-                               }
-
-                       }
-               }
+               mmap_read_all();
 
                if (hits == samples) {
                        if (done)
index b364da5b0cbf27029a3a8620caee32c583779840..6cc1b1dced55e97b7caf6648f9394bf8a1778b3e 100644 (file)
@@ -84,11 +84,12 @@ struct build_id_event {
        char                     filename[];
 };
 
-enum perf_header_event_type { /* above any possible kernel type */
+enum perf_user_event_type { /* above any possible kernel type */
        PERF_RECORD_HEADER_ATTR                 = 64,
        PERF_RECORD_HEADER_EVENT_TYPE           = 65,
        PERF_RECORD_HEADER_TRACING_DATA         = 66,
        PERF_RECORD_HEADER_BUILD_ID             = 67,
+       PERF_RECORD_FINISHED_ROUND              = 68,
        PERF_RECORD_HEADER_MAX
 };
 
index 71bc608e0ec6328828030a9a37aef249f19a7726..c088d8f9b51cc9fcfd259019c9bb7c3d6c204a7e 100644 (file)
@@ -98,7 +98,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
        self->unknown_events = 0;
        self->machines = RB_ROOT;
        self->repipe = repipe;
-       self->ordered_samples.flush_limit = ULLONG_MAX;
        INIT_LIST_HEAD(&self->ordered_samples.samples_head);
        machine__init(&self->host_machine, "", HOST_KERNEL_ID);
 
@@ -195,6 +194,18 @@ static int process_event_stub(event_t *event __used,
        return 0;
 }
 
+static int process_finished_round_stub(event_t *event __used,
+                                      struct perf_session *session __used,
+                                      struct perf_event_ops *ops __used)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
+static int process_finished_round(event_t *event,
+                                 struct perf_session *session,
+                                 struct perf_event_ops *ops);
+
 static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 {
        if (handler->sample == NULL)
@@ -223,6 +234,12 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
                handler->tracing_data = process_event_stub;
        if (handler->build_id == NULL)
                handler->build_id = process_event_stub;
+       if (handler->finished_round == NULL) {
+               if (handler->ordered_samples)
+                       handler->finished_round = process_finished_round;
+               else
+                       handler->finished_round = process_finished_round_stub;
+       }
 }
 
 static const char *event__name[] = {
@@ -360,16 +377,14 @@ struct sample_queue {
        struct list_head        list;
 };
 
-#define FLUSH_PERIOD   (2 * NSEC_PER_SEC)
-
 static void flush_sample_queue(struct perf_session *s,
                               struct perf_event_ops *ops)
 {
        struct list_head *head = &s->ordered_samples.samples_head;
-       u64 limit = s->ordered_samples.flush_limit;
+       u64 limit = s->ordered_samples.next_flush;
        struct sample_queue *tmp, *iter;
 
-       if (!ops->ordered_samples)
+       if (!ops->ordered_samples || !limit)
                return;
 
        list_for_each_entry_safe(iter, tmp, head, list) {
@@ -388,6 +403,55 @@ static void flush_sample_queue(struct perf_session *s,
        }
 }
 
+/*
+ * When perf record finishes a pass on every buffers, it records this pseudo
+ * event.
+ * We record the max timestamp t found in the pass n.
+ * Assuming these timestamps are monotonic across cpus, we know that if
+ * a buffer still has events with timestamps below t, they will be all
+ * available and then read in the pass n + 1.
+ * Hence when we start to read the pass n + 2, we can safely flush every
+ * events with timestamps below t.
+ *
+ *    ============ PASS n =================
+ *       CPU 0         |   CPU 1
+ *                     |
+ *    cnt1 timestamps  |   cnt2 timestamps
+ *          1          |         2
+ *          2          |         3
+ *          -          |         4  <--- max recorded
+ *
+ *    ============ PASS n + 1 ==============
+ *       CPU 0         |   CPU 1
+ *                     |
+ *    cnt1 timestamps  |   cnt2 timestamps
+ *          3          |         5
+ *          4          |         6
+ *          5          |         7 <---- max recorded
+ *
+ *      Flush every events below timestamp 4
+ *
+ *    ============ PASS n + 2 ==============
+ *       CPU 0         |   CPU 1
+ *                     |
+ *    cnt1 timestamps  |   cnt2 timestamps
+ *          6          |         8
+ *          7          |         9
+ *          -          |         10
+ *
+ *      Flush every events below timestamp 7
+ *      etc...
+ */
+static int process_finished_round(event_t *event __used,
+                                 struct perf_session *session,
+                                 struct perf_event_ops *ops)
+{
+       flush_sample_queue(session, ops);
+       session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
+
+       return 0;
+}
+
 static void __queue_sample_end(struct sample_queue *new, struct list_head *head)
 {
        struct sample_queue *iter;
@@ -456,17 +520,12 @@ static void __queue_sample_event(struct sample_queue *new,
 }
 
 static int queue_sample_event(event_t *event, struct sample_data *data,
-                             struct perf_session *s,
-                             struct perf_event_ops *ops)
+                             struct perf_session *s)
 {
        u64 timestamp = data->time;
        struct sample_queue *new;
-       u64 flush_limit;
 
 
-       if (s->ordered_samples.flush_limit == ULLONG_MAX)
-               s->ordered_samples.flush_limit = timestamp + FLUSH_PERIOD;
-
        if (timestamp < s->ordered_samples.last_flush) {
                printf("Warning: Timestamp below last timeslice flush\n");
                return -EINVAL;
@@ -489,23 +548,8 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
        __queue_sample_event(new, s);
        s->ordered_samples.last_inserted = new;
 
-       /*
-        * We want to have a slice of events covering 2 * FLUSH_PERIOD
-        * If FLUSH_PERIOD is big enough, it ensures every events that occured
-        * in the first half of the timeslice have all been buffered and there
-        * are none remaining (we need that because of the weakly ordered
-        * event recording we have). Then once we reach the 2 * FLUSH_PERIOD
-        * timeslice, we flush the first half to be gentle with the memory
-        * (the second half can still get new events in the middle, so wait
-        * another period to flush it)
-        */
-       flush_limit = s->ordered_samples.flush_limit;
-
-       if (new->timestamp > flush_limit &&
-               new->timestamp - flush_limit > FLUSH_PERIOD) {
-               s->ordered_samples.flush_limit += FLUSH_PERIOD;
-               flush_sample_queue(s, ops);
-       }
+       if (new->timestamp > s->ordered_samples.max_timestamp)
+               s->ordered_samples.max_timestamp = new->timestamp;
 
        return 0;
 }
@@ -521,7 +565,7 @@ static int perf_session__process_sample(event_t *event, struct perf_session *s,
        bzero(&data, sizeof(struct sample_data));
        event__parse_sample(event, s->sample_type, &data);
 
-       queue_sample_event(event, &data, s, ops);
+       queue_sample_event(event, &data, s);
 
        return 0;
 }
@@ -573,6 +617,8 @@ static int perf_session__process_event(struct perf_session *self,
                return ops->tracing_data(event, self);
        case PERF_RECORD_HEADER_BUILD_ID:
                return ops->build_id(event, self);
+       case PERF_RECORD_FINISHED_ROUND:
+               return ops->finished_round(event, self, ops);
        default:
                self->unknown_events++;
                return -1;
@@ -651,15 +697,18 @@ more:
        p = &event;
        p += sizeof(struct perf_event_header);
 
-       err = do_read(self->fd, p, size - sizeof(struct perf_event_header));
-       if (err <= 0) {
-               if (err == 0) {
-                       pr_err("unexpected end of event stream\n");
-                       goto done;
-               }
+       if (size - sizeof(struct perf_event_header)) {
+               err = do_read(self->fd, p,
+                             size - sizeof(struct perf_event_header));
+               if (err <= 0) {
+                       if (err == 0) {
+                               pr_err("unexpected end of event stream\n");
+                               goto done;
+                       }
 
-               pr_err("failed to read event data\n");
-               goto out_err;
+                       pr_err("failed to read event data\n");
+                       goto out_err;
+               }
        }
 
        if (size == 0 ||
@@ -787,7 +836,7 @@ more:
 done:
        err = 0;
        /* do the final flush for ordered samples */
-       self->ordered_samples.flush_limit = ULLONG_MAX;
+       self->ordered_samples.next_flush = ULLONG_MAX;
        flush_sample_queue(self, ops);
 out_err:
        ui_progress__delete(progress);
index eb9f179376a5629c798ca44e5b4a6658408a51c4..242d528bfae24120140f9d1b7d597abace860f5a 100644 (file)
@@ -14,7 +14,8 @@ struct thread;
 
 struct ordered_samples {
        u64                     last_flush;
-       u64                     flush_limit;
+       u64                     next_flush;
+       u64                     max_timestamp;
        struct list_head        samples_head;
        struct sample_queue     *last_inserted;
 };
@@ -42,23 +43,28 @@ struct perf_session {
        char filename[0];
 };
 
+struct perf_event_ops;
+
 typedef int (*event_op)(event_t *self, struct perf_session *session);
+typedef int (*event_op2)(event_t *self, struct perf_session *session,
+                        struct perf_event_ops *ops);
 
 struct perf_event_ops {
-       event_op sample,
-                mmap,
-                comm,
-                fork,
-                exit,
-                lost,
-                read,
-                throttle,
-                unthrottle,
-                attr,
-                event_type,
-                tracing_data,
-                build_id;
-       bool    ordered_samples;
+       event_op        sample,
+                       mmap,
+                       comm,
+                       fork,
+                       exit,
+                       lost,
+                       read,
+                       throttle,
+                       unthrottle,
+                       attr,
+                       event_type,
+                       tracing_data,
+                       build_id;
+       event_op2       finished_round;
+       bool            ordered_samples;
 };
 
 struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe);