/* -*- linux-c -*- * Perf Functions * Copyright (C) 2006 Red Hat Inc. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #ifndef _PERF_C_ #define _PERF_C_ #include #include "perf.h" /** @file perf.c * @brief Implements performance monitoring hardware support */ /** Initialize performance sampling * Call this during probe initialization to set up performance event sampling * * @param attr description of event to sample * @param callback function to call when perf event overflows */ static Perf _stp_perf_init (struct perf_event_attr *attr, perf_overflow_handler_t callback) { int cpu; Perf pe; pe = (Perf) _stp_kmalloc (sizeof(struct _Perf)); if (pe == NULL) return NULL; pe->callback = callback; /* allocate space for the event descriptor for each cpu */ pe->pd = (struct perf_event **) _stp_alloc_percpu (sizeof(struct perf_event *)); if (pe->pd == NULL) goto exit1; /* initialize event on each processor */ stp_for_each_cpu(cpu) { struct perf_event **event = per_cpu_ptr (pe->pd, cpu); *event = perf_event_create_kernel_counter(attr, cpu, -1, callback); if (IS_ERR(*event)) { *event = NULL; goto exit2; } } return pe; exit2: stp_for_each_cpu(cpu) { struct perf_event **event = per_cpu_ptr (pe->pd, cpu); if (*event) perf_event_release_kernel(*event); } _stp_free_percpu(pe->pd); exit1: _stp_kfree(pe); return NULL; } /** Delete performance event. * Call this to shutdown performance event sampling * * @param pe */ static void _stp_perf_del (Perf pe) { if (pe) { int cpu; /* shut down performance event sampling */ stp_for_each_cpu(cpu) { struct perf_event **event = per_cpu_ptr (pe->pd, cpu); if (*event) { perf_event_release_kernel(*event); } } _stp_free_percpu (pe->pd); _stp_kfree (pe); } } #endif /* _PERF_C_ */