]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
tools lib traceevent: Implement a new API, tep_list_events_copy()
authorTzvetomir Stoyanov <tstoyanov@vmware.com>
Mon, 1 Apr 2019 16:43:08 +0000 (12:43 -0400)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 1 Apr 2019 18:18:09 +0000 (15:18 -0300)
Existing API tep_list_events() is not thread safe, it uses the internal
array sort_events to keep cache of the sorted events and reuses it. This
patch implements a new API, tep_list_events_copy(), which allocates new
sorted array each time it is called. It could be used when a sorted
events functionality is needed in thread safe use cases. It is up to the
caller to free the array.

Signed-off-by: Tzvetomir Stoyanov <tstoyanov@vmware.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lore.kernel.org/linux-trace-devel/20181218133013.31094-1-tstoyanov@vmware.com
Link: http://lkml.kernel.org/r/20190401164343.117437443@goodmis.org
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h

index 666e23ded6ed453f136a2e7e99dce8b54ba2650e..c00aebab3c3359160e3d73c3c3f73a0f29b63b5a 100644 (file)
@@ -5651,32 +5651,26 @@ static int events_system_cmp(const void *a, const void *b)
        return events_id_cmp(a, b);
 }
 
-struct tep_event **tep_list_events(struct tep_handle *pevent, enum tep_event_sort_type sort_type)
+static struct tep_event **list_events_copy(struct tep_handle *tep)
 {
        struct tep_event **events;
-       int (*sort)(const void *a, const void *b);
-
-       events = pevent->sort_events;
-
-       if (events && pevent->last_type == sort_type)
-               return events;
 
-       if (!events) {
-               events = malloc(sizeof(*events) * (pevent->nr_events + 1));
-               if (!events)
-                       return NULL;
+       if (!tep)
+               return NULL;
 
-               memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
-               events[pevent->nr_events] = NULL;
+       events = malloc(sizeof(*events) * (tep->nr_events + 1));
+       if (!events)
+               return NULL;
 
-               pevent->sort_events = events;
+       memcpy(events, tep->events, sizeof(*events) * tep->nr_events);
+       events[tep->nr_events] = NULL;
+       return events;
+}
 
-               /* the internal events are sorted by id */
-               if (sort_type == TEP_EVENT_SORT_ID) {
-                       pevent->last_type = sort_type;
-                       return events;
-               }
-       }
+static void list_events_sort(struct tep_event **events, int nr_events,
+                            enum tep_event_sort_type sort_type)
+{
+       int (*sort)(const void *a, const void *b);
 
        switch (sort_type) {
        case TEP_EVENT_SORT_ID:
@@ -5689,11 +5683,82 @@ struct tep_event **tep_list_events(struct tep_handle *pevent, enum tep_event_sor
                sort = events_system_cmp;
                break;
        default:
+               sort = NULL;
+       }
+
+       if (sort)
+               qsort(events, nr_events, sizeof(*events), sort);
+}
+
+/**
+ * tep_list_events - Get events, sorted by given criteria.
+ * @tep: a handle to the tep context
+ * @sort_type: desired sort order of the events in the array
+ *
+ * Returns an array of pointers to all events, sorted by the given
+ * @sort_type criteria. The last element of the array is NULL. The returned
+ * memory must not be freed, it is managed by the library.
+ * The function is not thread safe.
+ */
+struct tep_event **tep_list_events(struct tep_handle *tep,
+                                  enum tep_event_sort_type sort_type)
+{
+       struct tep_event **events;
+
+       if (!tep)
+               return NULL;
+
+       events = tep->sort_events;
+       if (events && tep->last_type == sort_type)
                return events;
+
+       if (!events) {
+               events = list_events_copy(tep);
+               if (!events)
+                       return NULL;
+
+               tep->sort_events = events;
+
+               /* the internal events are sorted by id */
+               if (sort_type == TEP_EVENT_SORT_ID) {
+                       tep->last_type = sort_type;
+                       return events;
+               }
        }
 
-       qsort(events, pevent->nr_events, sizeof(*events), sort);
-       pevent->last_type = sort_type;
+       list_events_sort(events, tep->nr_events, sort_type);
+       tep->last_type = sort_type;
+
+       return events;
+}
+
+
+/**
+ * tep_list_events_copy - Thread safe version of tep_list_events()
+ * @tep: a handle to the tep context
+ * @sort_type: desired sort order of the events in the array
+ *
+ * Returns an array of pointers to all events, sorted by the given
+ * @sort_type criteria. The last element of the array is NULL. The returned
+ * array is newly allocated inside the function and must be freed by the caller
+ */
+struct tep_event **tep_list_events_copy(struct tep_handle *tep,
+                                       enum tep_event_sort_type sort_type)
+{
+       struct tep_event **events;
+
+       if (!tep)
+               return NULL;
+
+       events = list_events_copy(tep);
+       if (!events)
+               return NULL;
+
+       /* the internal events are sorted by id */
+       if (sort_type == TEP_EVENT_SORT_ID)
+               return events;
+
+       list_events_sort(events, tep->nr_events, sort_type);
 
        return events;
 }
index aec48f2aea8af6647225ef622c22a5efa6e26e6f..41159358abc2171e83cf463789246239da397aea 100644 (file)
@@ -544,7 +544,10 @@ void tep_event_info(struct trace_seq *s, struct tep_event *event,
 int tep_strerror(struct tep_handle *pevent, enum tep_errno errnum,
                 char *buf, size_t buflen);
 
-struct tep_event **tep_list_events(struct tep_handle *pevent, enum tep_event_sort_type);
+struct tep_event **tep_list_events(struct tep_handle *tep,
+                                  enum tep_event_sort_type);
+struct tep_event **tep_list_events_copy(struct tep_handle *tep,
+                                       enum tep_event_sort_type);
 struct tep_format_field **tep_event_common_fields(struct tep_event *event);
 struct tep_format_field **tep_event_fields(struct tep_event *event);