@@ -14,6 +14,13 @@ struct func_list;
struct event_handler;
struct func_resolver;
+/* cache */
+struct tep_thread_data {
+ struct tep_handle *tep;
+
+ struct tep_event *last_event;
+};
+
struct tep_handle {
int ref_count;
@@ -83,9 +90,6 @@ struct tep_handle {
struct event_handler *handlers;
struct tep_function_handler *func_handlers;
- /* cache */
- struct tep_event *last_event;
-
char *trace_clock;
};
@@ -96,4 +100,10 @@ unsigned short tep_data2host2(struct tep_handle *pevent, unsigned short data);
unsigned int tep_data2host4(struct tep_handle *pevent, unsigned int data);
unsigned long long tep_data2host8(struct tep_handle *pevent, unsigned long long data);
+/* tep cache per thread */
+struct tep_event *get_thread_local_event_by_id(struct tep_handle *tep, int id);
+struct tep_event *
+get_thread_local_event_by_name(struct tep_handle *tep, const char *name, const char *sys);
+void set_thread_local_event_cache(struct tep_handle *tep, struct tep_event *event);
+
#endif /* _PARSE_EVENTS_INT_H */
new file mode 100644
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ */
+
+#include "event-parse.h"
+#include "event-parse-local.h"
+#include "event-utils.h"
+
+static __thread struct tep_thread_data tep_thread_local;
+
+/**
+ * get_thread_local_event_by_id - Find event with given id in the cache
+ * @tep: a handle to the tep context
+ * @id: event's id
+ *
+ * Searches in the cache for event with given id
+ */
+struct tep_event *get_thread_local_event_by_id(struct tep_handle *tep, int id)
+{
+
+ if (tep_thread_local->last_event && tep_thread_local->tep == tep &&
+ tep_thread_local->last_event->id == id)
+ return tep_thread_local->last_event;
+
+ return NULL;
+}
+
+/**
+ * get_thread_local_event_by_name - Find event with given name and sys in the cache
+ * @tep: a handle to the tep context
+ * @name: event's name
+ * @sys: event's system
+ *
+ * Searches in the cache for event with given name and system
+ */
+struct tep_event *
+get_thread_local_event_by_name(struct tep_handle *tep, const char *name, const char *sys)
+{
+ if (tep_thread_local->last_event &&
+ tep_thread_local->tep == tep &&
+ strcmp(tep_thread_local->last_event->name, name) == 0 &&
+ (!sys || strcmp(tep_thread_local->last_event->system, sys) == 0))
+ return tep_thread_local->last_event;
+
+ return NULL;
+}
+
+/**
+ * set_thread_local_event_cache - set last used event in the cache
+ * @tep: a handle to the tep context
+ * @event: pointer to the last used event
+ *
+ * Sets last used event in the cache, to speed up the next searches
+ */
+void set_thread_local_event_cache(struct tep_handle *tep, struct tep_event *event)
+{
+ tep_thread_local->last_event = event;
+}
+
+
@@ -3485,10 +3485,11 @@ struct tep_event *tep_find_event(struct tep_handle *pevent, int id)
struct tep_event **eventptr;
struct tep_event key;
struct tep_event *pkey = &key;
+ struct tep_event *event_cache = get_thread_local_event_by_id(pevent, id);
/* Check cache first */
- if (pevent->last_event && pevent->last_event->id == id)
- return pevent->last_event;
+ if (event_cache)
+ return event_cache;
key.id = id;
@@ -3496,7 +3497,7 @@ struct tep_event *tep_find_event(struct tep_handle *pevent, int id)
sizeof(*pevent->events), events_id_cmp);
if (eventptr) {
- pevent->last_event = *eventptr;
+ set_thread_local_event_cache(pevent, *eventptr);
return *eventptr;
}
@@ -3516,13 +3517,13 @@ struct tep_event *
tep_find_event_by_name(struct tep_handle *pevent,
const char *sys, const char *name)
{
- struct tep_event *event = NULL;
int i;
+ struct tep_event *event = NULL;
+ struct tep_event *event_cache = get_thread_local_event_by_name(pevent, name, sys);
- if (pevent->last_event &&
- strcmp(pevent->last_event->name, name) == 0 &&
- (!sys || strcmp(pevent->last_event->system, sys) == 0))
- return pevent->last_event;
+ /* Check cache first */
+ if (event_cache)
+ return event_cache;
for (i = 0; i < pevent->nr_events; i++) {
event = pevent->events[i];
@@ -3533,10 +3534,12 @@ tep_find_event_by_name(struct tep_handle *pevent,
break;
}
}
+
if (i == pevent->nr_events)
event = NULL;
+ if (event)
+ set_thread_local_event_cache(pevent, event);
- pevent->last_event = event;
return event;
}
This patch is a PoC about transforming libtraceevent into a thread safe library. It implements per thread local storage and internal APIs to access it. It covers only tep->last_event cache, but easily can be extended with all library's thread sensitive data. Signed-off-by: Tzvetomir Stoyanov <tstoyanov@vmware.com> --- v2: Added local thread data per tep context v3: Implemented APIs to access specific tread local data, instead of the whole struct tep_thread_data. v4: Simplify the implementation to keep cache only for the last used tep context in current thread, instead to track cache for all tep contexts. Remove "tep_" prefix of functions, as these are internal APIs and are not going to be exposed to the library users. --- tools/lib/traceevent/event-parse-local.h | 16 ++++-- tools/lib/traceevent/event-parse-thread.c | 62 +++++++++++++++++++++++ tools/lib/traceevent/event-parse.c | 21 ++++---- 3 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 tools/lib/traceevent/event-parse-thread.c