Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76369139 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Ingo Molnar
Browse files

perf: Split up buffer handling from core code



And create the internal perf events header.

v2: Keep an internal inlined perf_output_copy()

Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Stephane Eranian <eranian@google.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1305827704-5607-1-git-send-email-fweisbec@gmail.com


[ v3: use clearer 'ring_buffer' and 'rb' naming ]
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b58f6b0d
Loading
Loading
Loading
Loading
+4 −29
Original line number Diff line number Diff line
@@ -680,33 +680,6 @@ enum perf_event_active_state {
};

struct file;

#define PERF_BUFFER_WRITABLE		0x01

struct perf_buffer {
	atomic_t			refcount;
	struct rcu_head			rcu_head;
#ifdef CONFIG_PERF_USE_VMALLOC
	struct work_struct		work;
	int				page_order;	/* allocation order  */
#endif
	int				nr_pages;	/* nr of data pages  */
	int				writable;	/* are we writable   */

	atomic_t			poll;		/* POLL_ for wakeups */

	local_t				head;		/* write position    */
	local_t				nest;		/* nested writers    */
	local_t				events;		/* event limit       */
	local_t				wakeup;		/* wakeup stamp      */
	local_t				lost;		/* nr records lost   */

	long				watermark;	/* wakeup watermark  */

	struct perf_event_mmap_page	*user_page;
	void				*data_pages[0];
};

struct perf_sample_data;

typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
@@ -745,6 +718,8 @@ struct perf_cgroup {
};
#endif

struct ring_buffer;

/**
 * struct perf_event - performance event kernel representation:
 */
@@ -834,7 +809,7 @@ struct perf_event {
	atomic_t			mmap_count;
	int				mmap_locked;
	struct user_struct		*mmap_user;
	struct perf_buffer		*buffer;
	struct ring_buffer		*rb;

	/* poll related */
	wait_queue_head_t		waitq;
@@ -945,7 +920,7 @@ struct perf_cpu_context {

struct perf_output_handle {
	struct perf_event		*event;
	struct perf_buffer		*buffer;
	struct ring_buffer		*rb;
	unsigned long			wakeup;
	unsigned long			size;
	void				*addr;
+1 −1
Original line number Diff line number Diff line
@@ -2,5 +2,5 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_core.o = -pg
endif

obj-y := core.o
obj-y := core.o ring_buffer.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
+71 −497

File changed.

Preview size limit exceeded, changes collapsed.

+97 −0
Original line number Diff line number Diff line
#ifndef _KERNEL_EVENTS_INTERNAL_H
#define _KERNEL_EVENTS_INTERNAL_H

#define RING_BUFFER_WRITABLE		0x01

struct ring_buffer {
	atomic_t			refcount;
	struct rcu_head			rcu_head;
#ifdef CONFIG_PERF_USE_VMALLOC
	struct work_struct		work;
	int				page_order;	/* allocation order  */
#endif
	int				nr_pages;	/* nr of data pages  */
	int				writable;	/* are we writable   */

	atomic_t			poll;		/* POLL_ for wakeups */

	local_t				head;		/* write position    */
	local_t				nest;		/* nested writers    */
	local_t				events;		/* event limit       */
	local_t				wakeup;		/* wakeup stamp      */
	local_t				lost;		/* nr records lost   */

	long				watermark;	/* wakeup watermark  */

	struct perf_event_mmap_page	*user_page;
	void				*data_pages[0];
};


extern void rb_free(struct ring_buffer *rb);
extern struct ring_buffer *
rb_alloc(int nr_pages, long watermark, int cpu, int flags);
extern void perf_event_wakeup(struct perf_event *event);

extern void
perf_event_header__init_id(struct perf_event_header *header,
			   struct perf_sample_data *data,
			   struct perf_event *event);
extern void
perf_event__output_id_sample(struct perf_event *event,
			     struct perf_output_handle *handle,
			     struct perf_sample_data *sample);

extern struct page *
perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff);

#ifdef CONFIG_PERF_USE_VMALLOC
/*
 * Back perf_mmap() with vmalloc memory.
 *
 * Required for architectures that have d-cache aliasing issues.
 */

static inline int page_order(struct ring_buffer *rb)
{
	return rb->page_order;
}

#else

static inline int page_order(struct ring_buffer *rb)
{
	return 0;
}
#endif

static unsigned long perf_data_size(struct ring_buffer *rb)
{
	return rb->nr_pages << (PAGE_SHIFT + page_order(rb));
}

static inline void
__output_copy(struct perf_output_handle *handle,
		   const void *buf, unsigned int len)
{
	do {
		unsigned long size = min_t(unsigned long, handle->size, len);

		memcpy(handle->addr, buf, size);

		len -= size;
		handle->addr += size;
		buf += size;
		handle->size -= size;
		if (!handle->size) {
			struct ring_buffer *rb = handle->rb;

			handle->page++;
			handle->page &= rb->nr_pages - 1;
			handle->addr = rb->data_pages[handle->page];
			handle->size = PAGE_SIZE << page_order(rb);
		}
	} while (len);
}

#endif /* _KERNEL_EVENTS_INTERNAL_H */
+399 −0

File added.

Preview size limit exceeded, changes collapsed.