typedef struct { unsigned long long __attribute__((aligned(8))) counter; } atomic64_t; struct list_head { struct list_head *next, *prev; }; typedef struct { atomic64_t a; } local64_t; struct mutex { }; struct perf_event_attr { unsigned int type; unsigned int size; unsigned long long config; union { unsigned long long sample_period; unsigned long long sample_freq; }; unsigned long long sample_type; unsigned long long read_format; unsigned long long disabled : 1, inherit : 1, pinned : 1, exclusive : 1, exclude_user : 1, exclude_kernel : 1, exclude_hv : 1, exclude_idle : 1, mmap : 1, comm : 1, freq : 1, inherit_stat : 1, enable_on_exec : 1, task : 1, watermark : 1, precise_ip : 2, mmap_data : 1, sample_id_all : 1, __reserved_1 : 45; union { unsigned int wakeup_events; unsigned int wakeup_watermark; }; unsigned int bp_type; union { unsigned long long bp_addr; unsigned long long config1; }; union { unsigned long long bp_len; unsigned long long config2; }; }; static inline __attribute__((always_inline)) unsigned long long atomic64_read(atomic64_t *v) { unsigned long long result; __asm__ __volatile__("@ atomic64_read\n" " ldrexd %0, %H0, [%1]" : "=&r" (result) : "r" (&v->counter), "Qo" (v->counter) ); return result; } struct hw_perf_event { union { struct { unsigned long long config; unsigned long long last_tag; unsigned long config_base; unsigned long event_base; int idx; int last_cpu; unsigned int extra_reg; unsigned long long extra_config; int extra_alloc; }; }; int state; local64_t prev_count; unsigned long long sample_period; unsigned long long last_period; local64_t period_left; unsigned long long interrupts; unsigned long long freq_time_stamp; unsigned long long freq_count_stamp; }; struct perf_event { atomic64_t child_count; unsigned long long total_time_enabled; unsigned long long total_time_running; unsigned long long tstamp_enabled; unsigned long long tstamp_running; unsigned long long tstamp_stopped; unsigned long long shadow_ctx_time; struct perf_event_attr attr; unsigned short header_size; struct hw_perf_event hw; struct perf_event_context *ctx; atomic64_t child_total_time_enabled; atomic64_t child_total_time_running; struct mutex child_mutex; struct list_head child_list; struct mutex mmap_mutex; }; unsigned long long perf_event_read_value(struct perf_event *event, unsigned long long *enabled, unsigned long long *running) { struct perf_event *child; unsigned long long total = 0; *enabled = 0; *running = 0; mutex_lock(&event->child_mutex); total += perf_event_read(event); *enabled += event->total_time_enabled + atomic64_read(&event->child_total_time_enabled); *running += event->total_time_running + atomic64_read(&event->child_total_time_running); for (child = ({ const typeof( ((typeof(*child) *)0)->child_list ) *__mptr = ((&event->child_list)->next); (typeof(*child) *)( (char *)__mptr - __builtin_offsetof(typeof(*child),child_list) );}); &child->child_list != (&event->child_list); child = ({ const typeof( ((typeof(*child) *)0)->child_list ) *__mptr = (child->child_list.next); (typeof(*child) *)( (char *)__mptr - __builtin_offsetof(typeof(*child),child_list) );})) { total += perf_event_read(child); *enabled += child->total_time_enabled; *running += child->total_time_running; } mutex_unlock(&event->child_mutex); return total; }