1/** 2 * @file cpu_buffer.h 3 * 4 * @remark Copyright 2002-2009 OProfile authors 5 * @remark Read the file COPYING 6 * 7 * @author John Levon <levon@movementarian.org> 8 * @author Robert Richter <robert.richter@amd.com> 9 */ 10 11#ifndef OPROFILE_CPU_BUFFER_H 12#define OPROFILE_CPU_BUFFER_H 13 14#include <linux/types.h> 15#include <linux/spinlock.h> 16#include <linux/workqueue.h> 17#include <linux/cache.h> 18#include <linux/sched.h> 19#include <linux/ring_buffer.h> 20 21struct task_struct; 22 23int alloc_cpu_buffers(void); 24void free_cpu_buffers(void); 25 26void start_cpu_work(void); 27void end_cpu_work(void); 28void flush_cpu_work(void); 29 30/* CPU buffer is composed of such entries (which are 31 * also used for context switch notes) 32 */ 33struct op_sample { 34 unsigned long eip; 35 unsigned long event; 36 unsigned long data[0]; 37}; 38 39struct op_entry; 40 41struct oprofile_cpu_buffer { 42 unsigned long buffer_size; 43 struct task_struct *last_task; 44 int last_is_kernel; 45 int tracing; 46 unsigned long sample_received; 47 unsigned long sample_lost_overflow; 48 unsigned long backtrace_aborted; 49 unsigned long sample_invalid_eip; 50 int cpu; 51 struct delayed_work work; 52}; 53 54DECLARE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); 55 56/* 57 * Resets the cpu buffer to a sane state. 58 * 59 * reset these to invalid values; the next sample collected will 60 * populate the buffer with proper values to initialize the buffer 61 */ 62static inline void op_cpu_buffer_reset(int cpu) 63{ 64 struct oprofile_cpu_buffer *cpu_buf = &per_cpu(op_cpu_buffer, cpu); 65 66 cpu_buf->last_is_kernel = -1; 67 cpu_buf->last_task = NULL; 68} 69 70/* 71 * op_cpu_buffer_add_data() and op_cpu_buffer_write_commit() may be 72 * called only if op_cpu_buffer_write_reserve() did not return NULL or 73 * entry->event != NULL, otherwise entry->size or entry->event will be 74 * used uninitialized. 75 */ 76 77struct op_sample 78*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size); 79int op_cpu_buffer_write_commit(struct op_entry *entry); 80struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu); 81unsigned long op_cpu_buffer_entries(int cpu); 82 83/* returns the remaining free size of data in the entry */ 84static inline 85int op_cpu_buffer_add_data(struct op_entry *entry, unsigned long val) 86{ 87 if (!entry->size) 88 return 0; 89 *entry->data = val; 90 entry->size--; 91 entry->data++; 92 return entry->size; 93} 94 95/* returns the size of data in the entry */ 96static inline 97int op_cpu_buffer_get_size(struct op_entry *entry) 98{ 99 return entry->size; 100} 101 102/* returns 0 if empty or the size of data including the current value */ 103static inline 104int op_cpu_buffer_get_data(struct op_entry *entry, unsigned long *val) 105{ 106 int size = entry->size; 107 if (!size) 108 return 0; 109 *val = *entry->data; 110 entry->size--; 111 entry->data++; 112 return size; 113} 114 115/* extra data flags */ 116#define KERNEL_CTX_SWITCH (1UL << 0) 117#define IS_KERNEL (1UL << 1) 118#define TRACE_BEGIN (1UL << 2) 119#define USER_CTX_SWITCH (1UL << 3) 120 121#endif /* OPROFILE_CPU_BUFFER_H */ 122