linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] tools/lib/traceevent: make libtraceevent thread safe
@ 2018-11-23 13:41 Tzvetomir Stoyanov
  2018-11-23 16:23 ` Steven Rostedt
  0 siblings, 1 reply; 2+ messages in thread
From: Tzvetomir Stoyanov @ 2018-11-23 13:41 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

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>
---
 tools/lib/traceevent/event-parse-local.h  | 17 ++++++++++---
 tools/lib/traceevent/event-parse-thread.c | 29 +++++++++++++++++++++++
 tools/lib/traceevent/event-parse.c        | 23 ++++++++++--------
 3 files changed, 56 insertions(+), 13 deletions(-)
 create mode 100644 tools/lib/traceevent/event-parse-thread.c

diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h
index 9a092dd4a86d..11f71ef8850b 100644
--- a/tools/lib/traceevent/event-parse-local.h
+++ b/tools/lib/traceevent/event-parse-local.h
@@ -14,6 +14,17 @@ struct func_list;
 struct event_handler;
 struct func_resolver;
 
+/* cache */
+struct tep_thread_data {
+	struct tep_event *last_event;
+};
+
+struct tep_thread_data_list {
+	pid_t tid;
+	struct tep_thread_data thr_data;
+	struct tep_thread_data_pool *next;
+};
+
 struct tep_handle {
 	int ref_count;
 
@@ -83,9 +94,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 +104,7 @@ 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);
 
+struct tep_thread_data *tep_get_thread_local();
+void tep_destroy_thread_local();
+
 #endif /* _PARSE_EVENTS_INT_H */
diff --git a/tools/lib/traceevent/event-parse-thread.c b/tools/lib/traceevent/event-parse-thread.c
new file mode 100644
index 000000000000..775d953041ab
--- /dev/null
+++ b/tools/lib/traceevent/event-parse-thread.c
@@ -0,0 +1,29 @@
+// 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;
+
+
+struct tep_thread_data *tep_get_thread_local(struct tep_handle *tep __maybe_unused)
+{
+	if (tep_thread_local)
+		return tep_thread_local;
+
+	tep_thread_local = calloc(1, sizeof(struct tep_thread_data));
+	return tep_thread_local;
+}
+
+
+void tep_destroy_thread_local()
+{
+	free(tep_thread_local);
+	tep_thread_local = NULL;
+}
+
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index a5048c1b9bec..25f4ceab9a58 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -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_thread_data *local = tep_get_thread_local(pevent);
 	/* Check cache first */
-	if (pevent->last_event && pevent->last_event->id == id)
-		return pevent->last_event;
+
+	if (local && local->last_event && local->last_event->id == id)
+		return local->last_event;
 
 	key.id = id;
 
@@ -3496,7 +3497,8 @@ struct tep_event *tep_find_event(struct tep_handle *pevent, int id)
 			   sizeof(*pevent->events), events_id_cmp);
 
 	if (eventptr) {
-		pevent->last_event = *eventptr;
+		if (local)
+			local->last_event = *eventptr;
 		return *eventptr;
 	}
 
@@ -3516,13 +3518,14 @@ struct tep_event *
 tep_find_event_by_name(struct tep_handle *pevent,
 		       const char *sys, const char *name)
 {
+	struct tep_thread_data *local = tep_get_thread_local(pevent);
 	struct tep_event *event = NULL;
 	int i;
 
-	if (pevent->last_event &&
-	    strcmp(pevent->last_event->name, name) == 0 &&
-	    (!sys || strcmp(pevent->last_event->system, sys) == 0))
-		return pevent->last_event;
+	if (local && local->last_event &&
+	    strcmp(local->last_event->name, name) == 0 &&
+	    (!sys || strcmp(local->last_event->system, sys) == 0))
+		return local->last_event;
 
 	for (i = 0; i < pevent->nr_events; i++) {
 		event = pevent->events[i];
@@ -3535,8 +3538,8 @@ tep_find_event_by_name(struct tep_handle *pevent,
 	}
 	if (i == pevent->nr_events)
 		event = NULL;
-
-	pevent->last_event = event;
+	if (local)
+		local->last_event = event;
 	return event;
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] tools/lib/traceevent: make libtraceevent thread safe
  2018-11-23 13:41 [PATCH] tools/lib/traceevent: make libtraceevent thread safe Tzvetomir Stoyanov
@ 2018-11-23 16:23 ` Steven Rostedt
  0 siblings, 0 replies; 2+ messages in thread
From: Steven Rostedt @ 2018-11-23 16:23 UTC (permalink / raw)
  To: Tzvetomir Stoyanov; +Cc: linux-trace-devel


I'm not officially working, but as my wife is not currently home, I
decided to sneak a peek at this patch ;-)

On Fri, 23 Nov 2018 13:41:40 +0000
Tzvetomir Stoyanov <tstoyanov@vmware.com> wrote:

> 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>
> ---
>  tools/lib/traceevent/event-parse-local.h  | 17 ++++++++++---
>  tools/lib/traceevent/event-parse-thread.c | 29 +++++++++++++++++++++++
>  tools/lib/traceevent/event-parse.c        | 23 ++++++++++--------
>  3 files changed, 56 insertions(+), 13 deletions(-)
>  create mode 100644 tools/lib/traceevent/event-parse-thread.c
> 
> diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h
> index 9a092dd4a86d..11f71ef8850b 100644
> --- a/tools/lib/traceevent/event-parse-local.h
> +++ b/tools/lib/traceevent/event-parse-local.h
> @@ -14,6 +14,17 @@ struct func_list;
>  struct event_handler;
>  struct func_resolver;
>  
> +/* cache */
> +struct tep_thread_data {
> +	struct tep_event *last_event;

We need to add a pointer to the tep handle itself. We don't want to use
the last event if it belonged to a different tep handle. Yes a thread
may have access to more than one tep handle at a time. Especially when
we start to do virt-server work.

> +};
> +
> +struct tep_thread_data_list {
> +	pid_t tid;
> +	struct tep_thread_data thr_data;
> +	struct tep_thread_data_pool *next;
> +};
> +

I'm thinking that we should not add the "tep_" prefix for anything
that's not exposed outside the library. This can help us know what's
local and what's not. I know there's some things currently like that,
but perhaps we should change them too.

>  struct tep_handle {
>  	int ref_count;
>  
> @@ -83,9 +94,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 +104,7 @@ 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);
>  
> +struct tep_thread_data *tep_get_thread_local();
> +void tep_destroy_thread_local();
> +
>  #endif /* _PARSE_EVENTS_INT_H */
> diff --git a/tools/lib/traceevent/event-parse-thread.c b/tools/lib/traceevent/event-parse-thread.c
> new file mode 100644
> index 000000000000..775d953041ab
> --- /dev/null
> +++ b/tools/lib/traceevent/event-parse-thread.c
> @@ -0,0 +1,29 @@
> +// 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;
> +
> +
> +struct tep_thread_data *tep_get_thread_local(struct tep_handle *tep __maybe_unused)
> +{
> +	if (tep_thread_local)
> +		return tep_thread_local;
> +
> +	tep_thread_local = calloc(1, sizeof(struct tep_thread_data));
> +	return tep_thread_local;
> +}
> +
> +
> +void tep_destroy_thread_local()
> +{
> +	free(tep_thread_local);
> +	tep_thread_local = NULL;
> +}
> +
> diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
> index a5048c1b9bec..25f4ceab9a58 100644
> --- a/tools/lib/traceevent/event-parse.c
> +++ b/tools/lib/traceevent/event-parse.c
> @@ -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_thread_data *local = tep_get_thread_local(pevent);
>  	/* Check cache first */
> -	if (pevent->last_event && pevent->last_event->id == id)
> -		return pevent->last_event;
> +
> +	if (local && local->last_event && local->last_event->id == id)

		&& local->tep == pevent &&

(but we should also rename pevent to tep, but that's another patch
series ;-)

> +		return local->last_event;
>  
>  	key.id = id;
>  
> @@ -3496,7 +3497,8 @@ struct tep_event *tep_find_event(struct tep_handle *pevent, int id)
>  			   sizeof(*pevent->events), events_id_cmp);
>  
>  	if (eventptr) {
> -		pevent->last_event = *eventptr;
> +		if (local)
 			{
> +			local->last_event = *eventptr;

			local->tep = pevent;
		}

>  		return *eventptr;
>  	}
>  
> @@ -3516,13 +3518,14 @@ struct tep_event *
>  tep_find_event_by_name(struct tep_handle *pevent,
>  		       const char *sys, const char *name)
>  {
> +	struct tep_thread_data *local = tep_get_thread_local(pevent);
>  	struct tep_event *event = NULL;
>  	int i;
>  
> -	if (pevent->last_event &&
> -	    strcmp(pevent->last_event->name, name) == 0 &&
> -	    (!sys || strcmp(pevent->last_event->system, sys) == 0))
> -		return pevent->last_event;
> +	if (local && local->last_event &&
> +	    strcmp(local->last_event->name, name) == 0 &&
> +	    (!sys || strcmp(local->last_event->system, sys) == 0))
> +		return local->last_event;
>  
>  	for (i = 0; i < pevent->nr_events; i++) {
>  		event = pevent->events[i];
> @@ -3535,8 +3538,8 @@ tep_find_event_by_name(struct tep_handle *pevent,
>  	}
>  	if (i == pevent->nr_events)
>  		event = NULL;
> -
> -	pevent->last_event = event;
> +	if (local)
> +		local->last_event = event;

Same here.

-- Steve

>  	return event;
>  }
>  

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-11-24  3:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-23 13:41 [PATCH] tools/lib/traceevent: make libtraceevent thread safe Tzvetomir Stoyanov
2018-11-23 16:23 ` Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).