mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	When ordering events, we use preallocated buffers to store separate
events.  Those buffers currently don't have their own struct, but since
they are basically an array of 'struct ordered_event' objects, we use
the first event to hold buffers data - list head, that holds all buffers
together:
   struct ordered_events {
     ...
     struct ordered_event *buffer;
     ...
   };
   struct ordered_event {
     u64               timestamp;
     u64               file_offset;
     union perf_event  *event;
     struct list_head  list;
   };
This is quite convoluted and error prone as demonstrated by free-ing
issue discovered and fixed by Stephane in here [1].
This patch adds the 'struct ordered_events_buffer' object, that holds
the buffer data and frees it up properly.
[1] - https://marc.info/?l=linux-kernel&m=153376761329335&w=2
Reported-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Stephane Eranian <eranian@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180907102455.7030-1-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
		
	
			
		
			
				
	
	
		
			71 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0 */
 | 
						|
#ifndef __ORDERED_EVENTS_H
 | 
						|
#define __ORDERED_EVENTS_H
 | 
						|
 | 
						|
#include <linux/types.h>
 | 
						|
 | 
						|
struct perf_sample;
 | 
						|
 | 
						|
struct ordered_event {
 | 
						|
	u64			timestamp;
 | 
						|
	u64			file_offset;
 | 
						|
	union perf_event	*event;
 | 
						|
	struct list_head	list;
 | 
						|
};
 | 
						|
 | 
						|
enum oe_flush {
 | 
						|
	OE_FLUSH__NONE,
 | 
						|
	OE_FLUSH__FINAL,
 | 
						|
	OE_FLUSH__ROUND,
 | 
						|
	OE_FLUSH__HALF,
 | 
						|
};
 | 
						|
 | 
						|
struct ordered_events;
 | 
						|
 | 
						|
typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
 | 
						|
					 struct ordered_event *event);
 | 
						|
 | 
						|
struct ordered_events_buffer {
 | 
						|
	struct list_head	list;
 | 
						|
	struct ordered_event	event[0];
 | 
						|
};
 | 
						|
 | 
						|
struct ordered_events {
 | 
						|
	u64				 last_flush;
 | 
						|
	u64				 next_flush;
 | 
						|
	u64				 max_timestamp;
 | 
						|
	u64				 max_alloc_size;
 | 
						|
	u64				 cur_alloc_size;
 | 
						|
	struct list_head		 events;
 | 
						|
	struct list_head		 cache;
 | 
						|
	struct list_head		 to_free;
 | 
						|
	struct ordered_events_buffer	*buffer;
 | 
						|
	struct ordered_event		*last;
 | 
						|
	ordered_events__deliver_t	 deliver;
 | 
						|
	int				 buffer_idx;
 | 
						|
	unsigned int			 nr_events;
 | 
						|
	enum oe_flush			 last_flush_type;
 | 
						|
	u32				 nr_unordered_events;
 | 
						|
	bool				 copy_on_queue;
 | 
						|
};
 | 
						|
 | 
						|
int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
 | 
						|
			  u64 timestamp, u64 file_offset);
 | 
						|
void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
 | 
						|
int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
 | 
						|
void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
 | 
						|
void ordered_events__free(struct ordered_events *oe);
 | 
						|
void ordered_events__reinit(struct ordered_events *oe);
 | 
						|
 | 
						|
static inline
 | 
						|
void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
 | 
						|
{
 | 
						|
	oe->max_alloc_size = size;
 | 
						|
}
 | 
						|
 | 
						|
static inline
 | 
						|
void ordered_events__set_copy_on_queue(struct ordered_events *oe, bool copy)
 | 
						|
{
 | 
						|
	oe->copy_on_queue = copy;
 | 
						|
}
 | 
						|
#endif /* __ORDERED_EVENTS_H */
 |