[PATCH 10/18] perf tools: Create ordered-events object

2014-06-18 Thread Jiri Olsa
Move ordered events code into separated object ordered-events.[ch].

Cc: Arnaldo Carvalho de Melo 
Cc: Corey Ashford 
Cc: David Ahern 
Cc: Frederic Weisbecker 
Cc: Ingo Molnar 
Cc: Jean Pihet 
Cc: Namhyung Kim 
Cc: Paul Mackerras 
Cc: Peter Zijlstra 
Signed-off-by: Jiri Olsa 
---
 tools/perf/Makefile.perf |   2 +
 tools/perf/util/ordered-events.c | 195 +
 tools/perf/util/ordered-events.h |  43 
 tools/perf/util/session.c| 205 ---
 tools/perf/util/session.h|  17 +---
 5 files changed, 241 insertions(+), 221 deletions(-)
 create mode 100644 tools/perf/util/ordered-events.c
 create mode 100644 tools/perf/util/ordered-events.h

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16..1351cfe 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -263,6 +263,7 @@ LIB_H += util/xyarray.h
 LIB_H += util/header.h
 LIB_H += util/help.h
 LIB_H += util/session.h
+LIB_H += util/ordered-events.h
 LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
 LIB_H += util/strfilter.h
@@ -345,6 +346,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
 LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
+LIB_OBJS += $(OUTPUT)util/ordered-events.o
 LIB_OBJS += $(OUTPUT)util/comm.o
 LIB_OBJS += $(OUTPUT)util/thread.o
 LIB_OBJS += $(OUTPUT)util/thread_map.o
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000..2e89bea
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,195 @@
+#include 
+#include "ordered-events.h"
+#include "evlist.h"
+#include "session.h"
+#include "asm/bug.h"
+
+static void queue_event(struct ordered_events_queue *q, struct ordered_event 
*new)
+{
+   struct ordered_event *last = q->last;
+   u64 timestamp = new->timestamp;
+   struct list_head *p;
+
+   ++q->nr_events;
+   q->last = new;
+
+   if (!last) {
+   list_add(>list, >events);
+   q->max_timestamp = timestamp;
+   return;
+   }
+
+   /*
+* last event might point to some random place in the list as it's
+* the last queued event. We expect that the new event is clqe to
+* this.
+*/
+   if (last->timestamp <= timestamp) {
+   while (last->timestamp <= timestamp) {
+   p = last->list.next;
+   if (p == >events) {
+   list_add_tail(>list, >events);
+   q->max_timestamp = timestamp;
+   return;
+   }
+   last = list_entry(p, struct ordered_event, list);
+   }
+   list_add_tail(>list, >list);
+   } else {
+   while (last->timestamp > timestamp) {
+   p = last->list.prev;
+   if (p == >events) {
+   list_add(>list, >events);
+   return;
+   }
+   last = list_entry(p, struct ordered_event, list);
+   }
+   list_add(>list, >list);
+   }
+}
+
+#define MAX_SAMPLE_BUFFER  (64 * 1024 / sizeof(struct ordered_event))
+static struct ordered_event *alloc_event(struct ordered_events_queue *q)
+{
+   struct list_head *cache = >cache;
+   struct ordered_event *new = NULL;
+
+   if (!list_empty(cache)) {
+   new = list_entry(cache->next, struct ordered_event, list);
+   list_del(>list);
+   } else if (q->buffer) {
+   new = q->buffer + q->buffer_idx;
+   if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
+   q->buffer = NULL;
+   } else if (q->cur_alloc_size < q->max_alloc_size) {
+   size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
+
+   q->buffer = malloc(size);
+   if (!q->buffer)
+   return NULL;
+
+   q->cur_alloc_size += size;
+   list_add(>buffer->list, >to_free);
+
+   /* First entry is abused to maintain the to_free list. */
+   q->buffer_idx = 2;
+   new = q->buffer + 1;
+   }
+
+   return new;
+}
+
+struct ordered_event*
+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
+{
+   struct ordered_event *new;
+
+   new = alloc_event(q);
+   if (new) {
+   new->timestamp = timestamp;
+   queue_event(q, new);
+   }
+
+   return new;
+}
+
+void
+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
+{
+   list_del(>list);
+   list_add(>list, >cache);
+   q->nr_events--;
+}
+
+static int __ordered_events_flush(struct perf_session *s,
+ struct perf_tool *tool)
+{
+   struct ordered_events_queue *q = >ordered_events;

[PATCH 10/18] perf tools: Create ordered-events object

2014-06-18 Thread Jiri Olsa
Move ordered events code into separated object ordered-events.[ch].

Cc: Arnaldo Carvalho de Melo a...@kernel.org
Cc: Corey Ashford cjash...@linux.vnet.ibm.com
Cc: David Ahern dsah...@gmail.com
Cc: Frederic Weisbecker fweis...@gmail.com
Cc: Ingo Molnar mi...@kernel.org
Cc: Jean Pihet jean.pi...@linaro.org
Cc: Namhyung Kim namhy...@kernel.org
Cc: Paul Mackerras pau...@samba.org
Cc: Peter Zijlstra a.p.zijls...@chello.nl
Signed-off-by: Jiri Olsa jo...@kernel.org
---
 tools/perf/Makefile.perf |   2 +
 tools/perf/util/ordered-events.c | 195 +
 tools/perf/util/ordered-events.h |  43 
 tools/perf/util/session.c| 205 ---
 tools/perf/util/session.h|  17 +---
 5 files changed, 241 insertions(+), 221 deletions(-)
 create mode 100644 tools/perf/util/ordered-events.c
 create mode 100644 tools/perf/util/ordered-events.h

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16..1351cfe 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -263,6 +263,7 @@ LIB_H += util/xyarray.h
 LIB_H += util/header.h
 LIB_H += util/help.h
 LIB_H += util/session.h
+LIB_H += util/ordered-events.h
 LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
 LIB_H += util/strfilter.h
@@ -345,6 +346,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
 LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
+LIB_OBJS += $(OUTPUT)util/ordered-events.o
 LIB_OBJS += $(OUTPUT)util/comm.o
 LIB_OBJS += $(OUTPUT)util/thread.o
 LIB_OBJS += $(OUTPUT)util/thread_map.o
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000..2e89bea
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,195 @@
+#include linux/list.h
+#include ordered-events.h
+#include evlist.h
+#include session.h
+#include asm/bug.h
+
+static void queue_event(struct ordered_events_queue *q, struct ordered_event 
*new)
+{
+   struct ordered_event *last = q-last;
+   u64 timestamp = new-timestamp;
+   struct list_head *p;
+
+   ++q-nr_events;
+   q-last = new;
+
+   if (!last) {
+   list_add(new-list, q-events);
+   q-max_timestamp = timestamp;
+   return;
+   }
+
+   /*
+* last event might point to some random place in the list as it's
+* the last queued event. We expect that the new event is clqe to
+* this.
+*/
+   if (last-timestamp = timestamp) {
+   while (last-timestamp = timestamp) {
+   p = last-list.next;
+   if (p == q-events) {
+   list_add_tail(new-list, q-events);
+   q-max_timestamp = timestamp;
+   return;
+   }
+   last = list_entry(p, struct ordered_event, list);
+   }
+   list_add_tail(new-list, last-list);
+   } else {
+   while (last-timestamp  timestamp) {
+   p = last-list.prev;
+   if (p == q-events) {
+   list_add(new-list, q-events);
+   return;
+   }
+   last = list_entry(p, struct ordered_event, list);
+   }
+   list_add(new-list, last-list);
+   }
+}
+
+#define MAX_SAMPLE_BUFFER  (64 * 1024 / sizeof(struct ordered_event))
+static struct ordered_event *alloc_event(struct ordered_events_queue *q)
+{
+   struct list_head *cache = q-cache;
+   struct ordered_event *new = NULL;
+
+   if (!list_empty(cache)) {
+   new = list_entry(cache-next, struct ordered_event, list);
+   list_del(new-list);
+   } else if (q-buffer) {
+   new = q-buffer + q-buffer_idx;
+   if (++q-buffer_idx == MAX_SAMPLE_BUFFER)
+   q-buffer = NULL;
+   } else if (q-cur_alloc_size  q-max_alloc_size) {
+   size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
+
+   q-buffer = malloc(size);
+   if (!q-buffer)
+   return NULL;
+
+   q-cur_alloc_size += size;
+   list_add(q-buffer-list, q-to_free);
+
+   /* First entry is abused to maintain the to_free list. */
+   q-buffer_idx = 2;
+   new = q-buffer + 1;
+   }
+
+   return new;
+}
+
+struct ordered_event*
+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
+{
+   struct ordered_event *new;
+
+   new = alloc_event(q);
+   if (new) {
+   new-timestamp = timestamp;
+   queue_event(q, new);
+   }
+
+   return new;
+}
+
+void
+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
+{
+   list_del(iter-list);
+   list_add(iter-list, q-cache);
+