This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch v9 02/23] linux, btrace: perf_event based branch tracing


> From: Markus Metzger <markus.t.metzger@intel.com>
> Date: Mon,  4 Mar 2013 18:05:49 +0100
> 
> Implement branch tracing on Linux based on perf_event such taht it
> can be shared between gdb and gdbserver.
> 
> The actual btrace target ops will be implemented on top.
> 
> 2013-03-04  Markus Metzger  <markus.t.metzger@intel.com>
> 
> 	* common/linux_btrace.h: New file.
> 	* common/linux_btrace.c: New file.
> 	* Makefile.in (SFILES): Add btrace.c.
> 	(HFILES_NO_SRCDIR): Add common/linux-btrace.h.
> 	(COMMON_OBS): Add btrace.o.
> 	(linux-btrace.o): New rule.
> 
> gdbserver/
> 	* Makefile.in (SFILES): Add $(srcdir)/common/linux-btrace.c.
> 	(linux_btrace_h): New variable.
> 	(linux-btrace.o): New rule.

> +/* See linux-btrace.h.  */
> +
> +VEC (btrace_block_s) *
> +linux_read_btrace (struct btrace_target_info *tinfo)
> +{
> +  VEC (btrace_block_s) *btrace = NULL;
> +  volatile struct perf_event_mmap_page *header;
> +  const uint8_t *begin, *end, *start;
> +  unsigned long data_head, retries = 5;
> +  size_t buffer_size;
> +
> +  header = perf_event_header (tinfo);
> +  buffer_size = perf_event_buffer_size (tinfo);
> +
> +  /* We may need to retry reading the trace.  See below.  */
> +  while (retries--)
> +    {
> +      data_head = header->data_head;
> +
> +      /* Make sure the trace data is up-to-date.  */
> +      memory_barrier ();

The barrier here makes absolutely no sense to me.  It's only a
compiler barrier and declaring header as volatile should be enough to
force the compiler to fetch HEADER->data_head from memory.

> +
> +      /* If there's new trace, let's read it.  */
> +      if (data_head != tinfo->data_head)
> +	{
> +	  /* Data_head keeps growing; the buffer itself is circular.  */
> +	  begin = perf_event_buffer_begin (tinfo);
> +	  start = begin + data_head % buffer_size;
> +
> +	  if (data_head <= buffer_size)
> +	    end = start;
> +	  else
> +	    end = perf_event_buffer_end (tinfo);
> +
> +	  btrace = perf_event_read_bts (tinfo, begin, end, start);
> +	}
> +
> +      /* The stopping thread notifies its ptracer before it is scheduled out.
> +	 On multi-core systems, the debugger might therefore run while the
> +	 kernel might be writing the last branch trace records.
> +
> +	 Let's check whether the data head moved while we read the trace.  */
> +      if (data_head == header->data_head)
> +	break;
> +    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]