diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:35 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:35 -0800 |
commit | dfb3f050a7cebd2030ea23dc6fa8964530e4ddcc (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libop | |
parent | b9958da7adae1c7d4482e958b371401eef387a39 (diff) | |
download | oprofile-dfb3f050a7cebd2030ea23dc6fa8964530e4ddcc.tar.gz |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libop')
-rw-r--r-- | libop/Android.mk | 19 | ||||
-rw-r--r-- | libop/op_alloc_counter.c | 213 | ||||
-rw-r--r-- | libop/op_alloc_counter.h | 43 | ||||
-rw-r--r-- | libop/op_config.c | 77 | ||||
-rw-r--r-- | libop/op_config.h | 58 | ||||
-rw-r--r-- | libop/op_config_24.h | 79 | ||||
-rw-r--r-- | libop/op_cpu_type.c | 158 | ||||
-rw-r--r-- | libop/op_cpu_type.h | 139 | ||||
-rw-r--r-- | libop/op_events.c | 862 | ||||
-rw-r--r-- | libop/op_events.h | 125 | ||||
-rw-r--r-- | libop/op_get_interface.c | 32 | ||||
-rw-r--r-- | libop/op_hw_config.h | 30 | ||||
-rw-r--r-- | libop/op_interface.h | 87 | ||||
-rw-r--r-- | libop/op_mangle.c | 104 | ||||
-rw-r--r-- | libop/op_mangle.h | 66 | ||||
-rw-r--r-- | libop/op_parse_event.c | 120 | ||||
-rw-r--r-- | libop/op_parse_event.h | 42 | ||||
-rw-r--r-- | libop/op_sample_file.h | 42 |
18 files changed, 0 insertions, 2296 deletions
diff --git a/libop/Android.mk b/libop/Android.mk deleted file mode 100644 index 8fbd1e6..0000000 --- a/libop/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - op_alloc_counter.c \ - op_config.c \ - op_cpu_type.c \ - op_events.c \ - op_get_interface.c \ - op_mangle.c \ - op_parse_event.c - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/.. \ - $(LOCAL_PATH)/../libutil - -LOCAL_MODULE := libop - -include $(BUILD_STATIC_LIBRARY) diff --git a/libop/op_alloc_counter.c b/libop/op_alloc_counter.c deleted file mode 100644 index 353100a..0000000 --- a/libop/op_alloc_counter.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file op_alloc_counter.c - * hardware counter allocation - * - * You can have silliness here. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#include <stdlib.h> -#include <ctype.h> -#include <dirent.h> - -#include "op_events.h" -#include "op_libiberty.h" - - -typedef struct counter_arc_head { - /** the head of allowed counter for this event */ - struct list_head next; -} counter_arc_head; - - -typedef struct counter_arc { - /** counter nr */ - int counter; - /** the next counter allowed for this event */ - struct list_head next; -} counter_arc; - - -/** - * @param pev an array of event - * @param nr_events number of entry in pev - * - * build an array of counter list allowed for each events - * counter_arc_head[i] is the list of allowed counter for pev[i] events - * The returned pointer is an array of nr_events entry - */ -static counter_arc_head * -build_counter_arc(struct op_event const * pev[], int nr_events) -{ - counter_arc_head * ctr_arc; - int i; - - ctr_arc = xmalloc(nr_events * sizeof(*ctr_arc)); - - for (i = 0; i < nr_events; ++i) { - int j; - u32 mask = pev[i]->counter_mask; - - list_init(&ctr_arc[i].next); - for (j = 0; mask; ++j) { - if (mask & (1 << j)) { - counter_arc * arc = - xmalloc(sizeof(counter_arc)); - arc->counter = j; - /* we are looping by increasing counter number, - * allocation use a left to right tree walking - * so we add at end to ensure counter will - * be allocated by increasing number: it's not - * required but a bit less surprising when - * debugging code - */ - list_add_tail(&arc->next, &ctr_arc[i].next); - mask &= ~(1 << j); - } - } - } - - return ctr_arc; -} - - -/** - * @param ctr_arc the array to deallocate - * @param nr_events number of entry in array - * - * deallocate all previously allocated resource by build_counter_arc() - */ -static void delete_counter_arc(counter_arc_head * ctr_arc, int nr_events) -{ - int i; - for (i = 0; i < nr_events; ++i) { - struct list_head * pos, * pos2; - list_for_each_safe(pos, pos2, &ctr_arc[i].next) { - counter_arc * arc = list_entry(pos, counter_arc, next); - list_del(&arc->next); - free(arc); - } - } - free(ctr_arc); -} - - -/** - * @param ctr_arc tree description, ctr_arc[i] is the i-th level of tree. - * @param max_depth number of entry in array ctr_arc == depth of tree - * @param depth current level we are exploring - * @param allocated_mask current counter already allocated mask - * @param counter_map array of counter number mapping, returned results go - * here - * - * return non zero on succees, in this case counter_map is set to the counter - * mapping number. - * - * Solution is searched through a simple backtracking exploring recursively all - * possible solution until one is found, prunning is done in O(1) by tracking - * a bitmask of already allocated counter. Walking through node is done in - * preorder left to right. - * - * Possible improvment if neccessary: partition counters in class of counter, - * two counter belong to the same class if they allow exactly the same set of - * event. Now using a variant of the backtrack algo can works on class of - * counter rather on counter (this is not an improvment if each counter goes - * in it's own class) - */ -static int -allocate_counter(counter_arc_head const * ctr_arc, int max_depth, int depth, - u32 allocated_mask, size_t * counter_map) -{ - struct list_head * pos; - - if (depth == max_depth) - return 1; - - list_for_each(pos, &ctr_arc[depth].next) { - counter_arc const * arc = list_entry(pos, counter_arc, next); - - if (allocated_mask & (1 << arc->counter)) - continue; - - counter_map[depth] = arc->counter; - - if (allocate_counter(ctr_arc, max_depth, depth + 1, - allocated_mask | (1 << arc->counter), - counter_map)) - return 1; - } - - return 0; -} - -/* determine which directories are counter directories - */ -static int perfcounterdir(const struct dirent * entry) -{ - return (isdigit(entry->d_name[0])); -} - - -/** - * @param mask pointer where to place bit mask of unavailable counters - * - * return >= 0 number of counters that are available - * < 0 could not determine number of counters - * - */ -static int op_get_counter_mask(u32 * mask) -{ - struct dirent **counterlist; - int count, i; - /* assume nothing is available */ - u32 available=0; - - count = scandir("/dev/oprofile", &counterlist, perfcounterdir, alphasort); - if (count < 0) - /* unable to determine bit mask */ - return -1; - /* convert to bit map (0 where counter exists) */ - for (i=0; i<count; ++i) { - available |= 1 << atoi(counterlist[i]->d_name); - free(counterlist[i]); - } - *mask=~available; - free(counterlist); - return count; -} - -size_t * map_event_to_counter(struct op_event const * pev[], int nr_events, - op_cpu cpu_type) -{ - counter_arc_head * ctr_arc; - size_t * counter_map; - int nr_counters; - u32 unavailable_counters = 0; - - nr_counters = op_get_counter_mask(&unavailable_counters); - /* no counters then probably perfmon managing perfmon hw */ - if (nr_counters <= 0) { - nr_counters = op_get_nr_counters(cpu_type); - unavailable_counters = (~0) << nr_counters; - } - if (nr_counters < nr_events) - return 0; - - ctr_arc = build_counter_arc(pev, nr_events); - - counter_map = xmalloc(nr_counters * sizeof(size_t)); - - if (!allocate_counter(ctr_arc, nr_events, 0, unavailable_counters, - counter_map)) { - free(counter_map); - counter_map = 0; - } - - delete_counter_arc(ctr_arc, nr_events); - return counter_map; -} diff --git a/libop/op_alloc_counter.h b/libop/op_alloc_counter.h deleted file mode 100644 index 40b4ebf..0000000 --- a/libop/op_alloc_counter.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file op_alloc_counter.h - * hardware counter allocation - * - * You can have silliness here. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_ALLOC_COUNTER_H -#define OP_ALLOC_COUNTER_H - -#include <stddef.h> - -#include "op_cpu_type.h" - -struct op_event; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @param pev array of selected event we want to bind to counter - * @param nr_events size of pev array - * @param cpu_type cpu type - * - * Try to calculate a binding between passed event in pev and counter number. - * The binding is returned in a size_t * where returned ptr[i] is the counter - * number bound to pev[i] - */ -size_t * map_event_to_counter(struct op_event const * pev[], int nr_events, - op_cpu cpu_type); - -#ifdef __cplusplus -} -#endif - -#endif /* !OP_ALLOC_COUNTER_H */ diff --git a/libop/op_config.c b/libop/op_config.c deleted file mode 100644 index 837242b..0000000 --- a/libop/op_config.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file op_config.c - * Oprofile configuration parameters. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author Nathan Tallent - * @Modifications Daniel Hansel - */ - -#include "op_config.h" -#include "op_config_24.h" - -#include <limits.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -/* paths in op_config.h */ -char op_session_dir[PATH_MAX]; -char op_samples_dir[PATH_MAX]; -char op_samples_current_dir[PATH_MAX]; -char op_lock_file[PATH_MAX]; -char op_log_file[PATH_MAX]; -char op_pipe_file[PATH_MAX]; -char op_dump_status[PATH_MAX]; - -/* paths in op_config_24.h */ -char op_device[PATH_MAX]; -char op_note_device[PATH_MAX]; -char op_hash_device[PATH_MAX]; - -void -init_op_config_dirs(char const * session_dir) -{ - int session_dir_len; - - assert(session_dir); - session_dir_len = strlen(session_dir); - - if (session_dir_len + strlen("/samples/oprofiled.log") > PATH_MAX) { - fprintf(stderr, "Session_dir string \"%s\" is too large.\n", - session_dir); - exit(EXIT_FAILURE); - } - - strcpy(op_session_dir, session_dir); - - strcpy(op_samples_dir, op_session_dir); - strcat(op_samples_dir, "/samples/"); - - strcpy(op_samples_current_dir, op_samples_dir); - strcat(op_samples_current_dir, "/current/"); - - strcpy(op_lock_file, op_session_dir); - strcat(op_lock_file, "/lock"); - - strcpy(op_pipe_file, op_session_dir); - strcat(op_pipe_file, "/opd_pipe"); - - strcpy(op_log_file, op_samples_dir); - strcat(op_log_file, "oprofiled.log"); - - strcpy(op_dump_status, op_session_dir); - strcat(op_dump_status, "/complete_dump"); - - strcpy(op_device, op_session_dir); - strcat(op_device, "/opdev"); - - strcpy(op_note_device, op_session_dir); - strcat(op_note_device, "/opnotedev"); - - strcpy(op_hash_device, op_session_dir); - strcat(op_hash_device, "/ophashmapdev"); -} diff --git a/libop/op_config.h b/libop/op_config.h deleted file mode 100644 index b384497..0000000 --- a/libop/op_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file op_config.h - * - * Parameters a user may want to change. See - * also op_config_24.h - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - * @Modifications Daniel Hansel - */ - -#ifndef OP_CONFIG_H -#define OP_CONFIG_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/** - * must be called to initialize the paths below. - * @param session_dir the non-NULL value of the base session directory - */ -void init_op_config_dirs(char const * session_dir); - -/* - * various paths, corresponding to opcontrol, that should be - * initialized by init_op_config_dirs() above. - */ -extern char op_session_dir[]; -extern char op_samples_dir[]; -extern char op_samples_current_dir[]; -extern char op_lock_file[]; -extern char op_log_file[]; -extern char op_pipe_file[]; -extern char op_dump_status[]; - -#define OP_DRIVER_BASE "/dev/oprofile" -#define OP_DATA_DIR "/data/oprofile" - -/* Global directory that stores debug files */ -#ifndef DEBUGDIR -#define DEBUGDIR "/usr/lib/debug" -#endif - -#define OPD_MAGIC "DAE\n" -#define OPD_VERSION 0x11 - -#define OP_MIN_CPU_BUF_SIZE 2048 -#define OP_MAX_CPU_BUF_SIZE 131072 - -#if defined(__cplusplus) -} -#endif - -#endif /* OP_CONFIG_H */ diff --git a/libop/op_config_24.h b/libop/op_config_24.h deleted file mode 100644 index 1786fae..0000000 --- a/libop/op_config_24.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file op_config_24.h - * - * Parameters a user may want to change - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_CONFIG_24_H -#define OP_CONFIG_24_H - -#define OP_MOUNT "/proc/sys/dev/oprofile/" - -extern char op_device[]; -extern char op_note_device[]; -extern char op_hash_device[]; - -/*@{\name module default/min/max settings */ - -/** 65536 * sizeof(op_sample) */ -#define OP_DEFAULT_BUF_SIZE 65536 -/** - * we don't try to wake-up daemon until it remains more than this free entry - * in eviction buffer - */ -#define OP_PRE_WATERMARK(buffer_size) \ - (((buffer_size) / 8) < OP_MIN_PRE_WATERMARK \ - ? OP_MIN_PRE_WATERMARK \ - : (buffer_size) / 8) -/** minimal buffer water mark before we try to wakeup daemon */ -#define OP_MIN_PRE_WATERMARK 8192 -/** maximum number of entry in samples eviction buffer */ -#define OP_MAX_BUF_SIZE 1048576 -/** minimum number of entry in samples eviction buffer */ -#define OP_MIN_BUF_SIZE (32768 + OP_PRE_WATERMARK(32768)) - -/** 16384 * sizeof(op_note) = 273680 bytes default */ -#define OP_DEFAULT_NOTE_SIZE 16384 -/** - * we don't try to wake-up daemon until it remains more than this free entry - * in note buffer - */ -#define OP_PRE_NOTE_WATERMARK(note_size) \ - (((note_size) / 32) < OP_MIN_NOTE_PRE_WATERMARK \ - ? OP_MIN_NOTE_PRE_WATERMARK \ - : (note_size) / 32) -/** minimal note buffer water mark before we try to wakeup daemon */ -#define OP_MIN_NOTE_PRE_WATERMARK 512 -/** maximum number of entry in note buffer */ -#define OP_MAX_NOTE_TABLE_SIZE 1048576 -/** minimum number of entry in note buffer */ -#define OP_MIN_NOTE_TABLE_SIZE (1024 + OP_PRE_NOTE_WATERMARK(1024)) - -/** maximum sampling rate when using RTC */ -#define OP_MAX_RTC_COUNT 4096 -/** minimum sampling rate when using RTC */ -#define OP_MIN_RTC_COUNT 2 - -/*@}*/ - -/** - * nr entries in hash map. This is the maximum number of name components - * allowed. Must be a prime number - */ -#define OP_HASH_MAP_NR 4093 - -/** size of string pool in bytes */ -#define POOL_SIZE 65536 - -#ifndef NR_CPUS -/** maximum number of cpus present in the box */ -#define NR_CPUS 32 -#endif - -#endif /* OP_CONFIG_24_H */ diff --git a/libop/op_cpu_type.c b/libop/op_cpu_type.c deleted file mode 100644 index b9d13de..0000000 --- a/libop/op_cpu_type.c +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @file op_cpu_type.c - * CPU type determination - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "op_cpu_type.h" - -struct cpu_descr { - char const * pretty; - char const * name; - op_cpu cpu; - unsigned int nr_counters; -}; - -static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = { - { "Pentium Pro", "i386/ppro", CPU_PPRO, 2 }, - { "PII", "i386/pii", CPU_PII, 2 }, - { "PIII", "i386/piii", CPU_PIII, 2 }, - { "Athlon", "i386/athlon", CPU_ATHLON, 4 }, - { "CPU with timer interrupt", "timer", CPU_TIMER_INT, 1 }, - { "CPU with RTC device", "rtc", CPU_RTC, 1 }, - { "P4 / Xeon", "i386/p4", CPU_P4, 8 }, - { "IA64", "ia64/ia64", CPU_IA64, 4 }, - { "Itanium", "ia64/itanium", CPU_IA64_1, 4 }, - { "Itanium 2", "ia64/itanium2", CPU_IA64_2, 4 }, - { "AMD64 processors", "x86-64/hammer", CPU_HAMMER, 4 }, - { "P4 / Xeon with 2 hyper-threads", "i386/p4-ht", CPU_P4_HT2, 4 }, - { "Alpha EV4", "alpha/ev4", CPU_AXP_EV4, 2 }, - { "Alpha EV5", "alpha/ev5", CPU_AXP_EV5, 3 }, - { "Alpha PCA56", "alpha/pca56", CPU_AXP_PCA56, 3 }, - { "Alpha EV6", "alpha/ev6", CPU_AXP_EV6, 2 }, - { "Alpha EV67", "alpha/ev67", CPU_AXP_EV67, 20 }, - { "Pentium M (P6 core)", "i386/p6_mobile", CPU_P6_MOBILE, 2 }, - { "ARM/XScale PMU1", "arm/xscale1", CPU_ARM_XSCALE1, 3 }, - { "ARM/XScale PMU2", "arm/xscale2", CPU_ARM_XSCALE2, 5 }, - { "ppc64 POWER4", "ppc64/power4", CPU_PPC64_POWER4, 8 }, - { "ppc64 POWER5", "ppc64/power5", CPU_PPC64_POWER5, 6 }, - { "ppc64 POWER5+", "ppc64/power5+", CPU_PPC64_POWER5p, 6 }, - { "ppc64 970", "ppc64/970", CPU_PPC64_970, 8 }, - { "MIPS 20K", "mips/20K", CPU_MIPS_20K, 1}, - { "MIPS 24K", "mips/24K", CPU_MIPS_24K, 2}, - { "MIPS 25K", "mips/25K", CPU_MIPS_25K, 2}, - { "MIPS 34K", "mips/34K", CPU_MIPS_34K, 4}, - { "MIPS 5K", "mips/5K", CPU_MIPS_5K, 2}, - { "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 }, - { "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 }, - { "QED RM7000", "mips/rm7000", CPU_MIPS_RM7000, 1 }, - { "PMC-Sierra RM9000", "mips/rm9000", CPU_MIPS_RM9000, 2 }, - { "Sibyte SB1", "mips/sb1", CPU_MIPS_SB1, 4 }, - { "NEC VR5432", "mips/vr5432", CPU_MIPS_VR5432, 2 }, - { "NEC VR5500", "mips/vr5500", CPU_MIPS_VR5500, 2 }, - { "e500", "ppc/e500", CPU_PPC_E500, 4 }, - { "e500v2", "ppc/e500v2", CPU_PPC_E500_2, 4 }, - { "Core Solo / Duo", "i386/core", CPU_CORE, 2 }, - { "PowerPC G4", "ppc/7450", CPU_PPC_7450, 6 }, - { "Core 2", "i386/core_2", CPU_CORE_2, 2 }, - { "ppc64 POWER6", "ppc64/power6", CPU_PPC64_POWER6, 4 }, - { "ppc64 970MP", "ppc64/970MP", CPU_PPC64_970MP, 8 }, - { "ppc64 Cell Broadband Engine", "ppc64/cell-be", CPU_PPC64_CELL, 8 }, - { "AMD64 family10", "x86-64/family10", CPU_FAMILY10, 4 }, - { "ppc64 PA6T", "ppc64/pa6t", CPU_PPC64_PA6T, 6 }, - { "ARM MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 }, - { "ARM V6 PMU", "arm/armv6", CPU_ARM_V6, 3 }, - { "ppc64 POWER5++", "ppc64/power5++", CPU_PPC64_POWER5pp, 6 }, - { "e300", "ppc/e300", CPU_PPC_E300, 4 }, - { "AVR32", "avr32", CPU_AVR32, 3 }, -}; - -static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr); - -op_cpu op_get_cpu_type(void) -{ - int cpu_type = CPU_NO_GOOD; - char str[100]; - FILE * fp; - - fp = fopen("/proc/sys/dev/oprofile/cpu_type", "r"); - if (!fp) { - /* Try 2.6's oprofilefs one instead. */ - fp = fopen("/dev/oprofile/cpu_type", "r"); - if (!fp) { - fprintf(stderr, "Unable to open cpu_type file for reading\n"); - fprintf(stderr, "Make sure you have done opcontrol --init\n"); - return cpu_type; - } - } - - if (!fgets(str, 99, fp)) { - fprintf(stderr, "Could not read cpu type.\n"); - return CPU_NO_GOOD; - } - - cpu_type = op_get_cpu_number(str); - - fclose(fp); - - return cpu_type; -} - - -op_cpu op_get_cpu_number(char const * cpu_string) -{ - int cpu_type = CPU_NO_GOOD; - size_t i; - - for (i = 0; i < nr_cpu_descrs; ++i) { - if (!strcmp(cpu_descrs[i].name, cpu_string)) { - cpu_type = cpu_descrs[i].cpu; - break; - } - } - - /* Attempt to convert into a number */ - if (cpu_type == CPU_NO_GOOD) - sscanf(cpu_string, "%d\n", &cpu_type); - - if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE) - cpu_type = CPU_NO_GOOD; - - return cpu_type; -} - - -char const * op_get_cpu_type_str(op_cpu cpu_type) -{ - if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE) - return "invalid cpu type"; - - return cpu_descrs[cpu_type].pretty; -} - - -char const * op_get_cpu_name(op_cpu cpu_type) -{ - if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE) - return "invalid cpu type"; - - return cpu_descrs[cpu_type].name; -} - - -int op_get_nr_counters(op_cpu cpu_type) -{ - if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE) - return 0; - - return cpu_descrs[cpu_type].nr_counters; -} diff --git a/libop/op_cpu_type.h b/libop/op_cpu_type.h deleted file mode 100644 index be95ae2..0000000 --- a/libop/op_cpu_type.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file op_cpu_type.h - * CPU type determination - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_CPU_TYPE_H -#define OP_CPU_TYPE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Supported cpu type. Always add new CPU types at the very end. - */ -typedef enum { - CPU_NO_GOOD = -1, /**< unsupported CPU type */ - CPU_PPRO, /**< Pentium Pro */ - CPU_PII, /**< Pentium II series */ - CPU_PIII, /**< Pentium III series */ - CPU_ATHLON, /**< AMD P6 series */ - CPU_TIMER_INT, /**< CPU using the timer interrupt */ - CPU_RTC, /**< other CPU to use the RTC */ - CPU_P4, /**< Pentium 4 / Xeon series */ - CPU_IA64, /**< Generic IA64 */ - CPU_IA64_1, /**< IA64 Merced */ - CPU_IA64_2, /**< IA64 McKinley */ - CPU_HAMMER, /**< AMD Hammer family */ - CPU_P4_HT2, /**< Pentium 4 / Xeon series with 2 hyper-threads */ - CPU_AXP_EV4, /**< Alpha EV4 family */ - CPU_AXP_EV5, /**< Alpha EV5 family */ - CPU_AXP_PCA56, /**< Alpha PCA56 family */ - CPU_AXP_EV6, /**< Alpha EV6 family */ - CPU_AXP_EV67, /**< Alpha EV67 family */ - CPU_P6_MOBILE, /**< Pentium M series */ - CPU_ARM_XSCALE1, /**< ARM XScale 1 */ - CPU_ARM_XSCALE2, /**< ARM XScale 2 */ - CPU_PPC64_POWER4, /**< ppc64 POWER4 family */ - CPU_PPC64_POWER5, /**< ppc64 POWER5 family */ - CPU_PPC64_POWER5p, /**< ppc64 Power5+ family */ - CPU_PPC64_970, /**< ppc64 970 family */ - CPU_MIPS_20K, /**< MIPS 20K */ - CPU_MIPS_24K, /**< MIPS 24K */ - CPU_MIPS_25K, /**< MIPS 25K */ - CPU_MIPS_34K, /**< MIPS 34K */ - CPU_MIPS_5K, /**< MIPS 5K */ - CPU_MIPS_R10000, /**< MIPS R10000 */ - CPU_MIPS_R12000, /**< MIPS R12000 */ - CPU_MIPS_RM7000, /**< QED RM7000 */ - CPU_MIPS_RM9000, /**< PMC-Sierra RM9000 */ - CPU_MIPS_SB1, /**< Broadcom SB1 */ - CPU_MIPS_VR5432, /**< NEC VR5432 */ - CPU_MIPS_VR5500, /**< MIPS VR5500, VR5532 and VR7701 */ - CPU_PPC_E500, /**< e500 */ - CPU_PPC_E500_2, /**< e500v2 */ - CPU_CORE, /**< Core Solo / Duo series */ - CPU_PPC_7450, /**< PowerPC G4 */ - CPU_CORE_2, /**< Intel Core 2 */ - CPU_PPC64_POWER6, /**< ppc64 POWER6 family */ - CPU_PPC64_970MP, /**< ppc64 970MP */ - CPU_PPC64_CELL, /**< ppc64 Cell Broadband Engine*/ - CPU_FAMILY10, /**< AMD family 10 */ - CPU_PPC64_PA6T, /**< ppc64 PA6T */ - CPU_ARM_MPCORE, /**< ARM MPCore */ - CPU_ARM_V6, /**< ARM V6 */ - CPU_PPC64_POWER5pp, /**< ppc64 Power5++ family */ - CPU_PPC_E300, /**< e300 */ - CPU_AVR32, /**< AVR32 */ - MAX_CPU_TYPE -} op_cpu; - -/** - * get the CPU type from the kernel - * - * returns CPU_NO_GOOD if the CPU could not be identified. - * This function can not work if the module is not loaded - */ -op_cpu op_get_cpu_type(void); - -/** - * get the cpu number based on string - * @param cpu_string with either the cpu type identifier or cpu type number - * - * The function returns CPU_NO_GOOD if no matching string was found. - */ -op_cpu op_get_cpu_number(char const * cpu_string); - -/** - * get the cpu string. - * @param cpu_type the cpu type identifier - * - * The function always return a valid char const * the core cpu denomination - * or "invalid cpu type" if cpu_type is not valid. - */ -char const * op_get_cpu_type_str(op_cpu cpu_type); - -/** - * op_get_cpu_name - get the cpu name - * @param cpu_type the cpu identifier name - * - * The function always return a valid char const * - * Return the OProfile CPU name, e.g. "i386/pii" - */ -char const * op_get_cpu_name(op_cpu cpu_type); - -/** - * compute the number of counters available - * @param cpu_type numeric processor type - * - * returns 0 if the CPU could not be identified - */ -int op_get_nr_counters(op_cpu cpu_type); - -typedef enum { - OP_INTERFACE_NO_GOOD = -1, - OP_INTERFACE_24, - OP_INTERFACE_26 -} op_interface; - -/** - * get the INTERFACE used to communicate between daemon and the kernel - * - * returns OP_INTERFACE_NO_GOOD if the INTERFACE could not be identified. - * This function will identify the interface as OP_INTERFACE_NO_GOOD if - * the module is not loaded. - */ -op_interface op_get_interface(void); - -#ifdef __cplusplus -} -#endif - -#endif /* OP_CPU_TYPE_H */ diff --git a/libop/op_events.c b/libop/op_events.c deleted file mode 100644 index b4a10e7..0000000 --- a/libop/op_events.c +++ /dev/null @@ -1,862 +0,0 @@ -/** - * @file op_events.c - * Details of PMC profiling events - * - * You can have silliness here. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#include "op_events.h" -#include "op_libiberty.h" -#include "op_fileio.h" -#include "op_string.h" -#include "op_cpufreq.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -static LIST_HEAD(events_list); -static LIST_HEAD(um_list); - -static char const * filename; -static unsigned int line_nr; - -static void parse_error(char const * context) -{ - fprintf(stderr, "oprofile: parse error in %s, line %u\n", - filename, line_nr); - fprintf(stderr, "%s\n", context); - exit(EXIT_FAILURE); -} - - -static int parse_int(char const * str) -{ - int value; - if (sscanf(str, "%d", &value) != 1) - parse_error("expected decimal value"); - - return value; -} - - -static int parse_hex(char const * str) -{ - int value; - /* 0x/0X to force the use of hexa notation for field intended to - be in hexadecimal */ - if (sscanf(str, "0x%x", &value) != 1 && - sscanf(str, "0X%x", &value) != 1) - parse_error("expected hexadecimal value"); - - return value; -} - - -static u64 parse_long_hex(char const * str) -{ - u64 value; - if (sscanf(str, "%Lx", &value) != 1) - parse_error("expected long hexadecimal value"); - - fflush(stderr); - return value; -} - - -/* name:MESI type:bitmask default:0x0f */ -static void parse_um(struct op_unit_mask * um, char const * line) -{ - int seen_name = 0; - int seen_type = 0; - int seen_default = 0; - char const * valueend = line + 1; - char const * tagend = line + 1; - char const * start = line; - - while (*valueend) { - valueend = skip_nonws(valueend); - - while (*tagend != ':' && *tagend) - ++tagend; - - if (valueend == tagend) - break; - - if (!*tagend) - parse_error("parse_um() expected :value"); - - ++tagend; - - if (strisprefix(start, "name")) { - if (seen_name) - parse_error("duplicate name: tag"); - seen_name = 1; - um->name = op_xstrndup(tagend, valueend - tagend); - } else if (strisprefix(start, "type")) { - if (seen_type) - parse_error("duplicate type: tag"); - seen_type = 1; - if (strisprefix(tagend, "mandatory")) { - um->unit_type_mask = utm_mandatory; - } else if (strisprefix(tagend, "bitmask")) { - um->unit_type_mask = utm_bitmask; - } else if (strisprefix(tagend, "exclusive")) { - um->unit_type_mask = utm_exclusive; - } else { - parse_error("invalid unit mask type"); - } - } else if (strisprefix(start, "default")) { - if (seen_default) - parse_error("duplicate default: tag"); - seen_default = 1; - um->default_mask = parse_hex(tagend); - } else { - parse_error("invalid unit mask tag"); - } - - valueend = skip_ws(valueend); - tagend = valueend; - start = valueend; - } -} - - -/* \t0x08 (M)odified cache state */ -static void parse_um_entry(struct op_described_um * entry, char const * line) -{ - char const * c = line; - - c = skip_ws(c); - entry->value = parse_hex(c); - c = skip_nonws(c); - - if (!*c) - parse_error("invalid unit mask entry"); - - c = skip_ws(c); - - if (!*c) - parse_error("invalid unit mask entry"); - - entry->desc = xstrdup(c); -} - - -static struct op_unit_mask * new_unit_mask(void) -{ - struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask)); - memset(um, '\0', sizeof(struct op_unit_mask)); - list_add_tail(&um->um_next, &um_list); - - return um; -} - - -/* - * name:zero type:mandatory default:0x0 - * \t0x0 No unit mask - */ -static void read_unit_masks(char const * file) -{ - struct op_unit_mask * um = NULL; - char * line; - FILE * fp = fopen(file, "r"); - - if (!fp) { - fprintf(stderr, - "oprofile: could not open unit mask description file %s\n", file); - exit(EXIT_FAILURE); - } - - filename = file; - line_nr = 1; - - line = op_get_line(fp); - - while (line) { - if (empty_line(line) || comment_line(line)) - goto next; - - if (line[0] != '\t') { - um = new_unit_mask(); - parse_um(um, line); - } else { - if (!um) - parse_error("no unit mask name line"); - if (um->num >= MAX_UNIT_MASK) - parse_error("oprofile: maximum unit mask entries exceeded"); - - parse_um_entry(&um->um[um->num], line); - ++(um->num); - } - -next: - free(line); - line = op_get_line(fp); - ++line_nr; - } - - fclose(fp); -} - - -static u32 parse_counter_mask(char const * str) -{ - u32 mask = 0; - char const * numstart = str; - - while (*numstart) { - mask |= 1 << parse_int(numstart); - - while (*numstart && *numstart != ',') - ++numstart; - /* skip , unless we reach eos */ - if (*numstart) - ++numstart; - - numstart = skip_ws(numstart); - } - - return mask; -} - - -static struct op_unit_mask * find_um(char const * value) -{ - struct list_head * pos; - - list_for_each(pos, &um_list) { - struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); - if (strcmp(value, um->name) == 0) - return um; - } - - fprintf(stderr, "oprofile: could not find unit mask %s\n", value); - exit(EXIT_FAILURE); -} - - -/* parse either a "tag:value" or a ": trailing description string" */ -static int next_token(char const ** cp, char ** name, char ** value) -{ - size_t tag_len; - size_t val_len; - char const * c = *cp; - char const * end; - char const * colon; - - c = skip_ws(c); - end = colon = c; - end = skip_nonws(end); - - colon = strchr(colon, ':'); - - if (!colon) { - if (*c) - parse_error("next_token(): garbage at end of line"); - return 0; - } - - if (colon >= end) - parse_error("next_token() expected ':'"); - - tag_len = colon - c; - val_len = end - (colon + 1); - - if (!tag_len) { - /* : trailing description */ - end = skip_ws(end); - *name = xstrdup("desc"); - *value = xstrdup(end); - end += strlen(end); - } else { - /* tag:value */ - *name = op_xstrndup(c, tag_len); - *value = op_xstrndup(colon + 1, val_len); - end = skip_ws(end); - } - - *cp = end; - return 1; -} - - -static struct op_event * new_event(void) -{ - struct op_event * event = xmalloc(sizeof(struct op_event)); - memset(event, '\0', sizeof(struct op_event)); - list_add_tail(&event->event_next, &events_list); - - return event; -} - - -/* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */ -static void read_events(char const * file) -{ - struct op_event * event = NULL; - char * line; - char * name; - char * value; - char const * c; - int seen_event, seen_counters, seen_um, seen_minimum, seen_name; - FILE * fp = fopen(file, "r"); - - if (!fp) { - fprintf(stderr, "oprofile: could not open event description file %s\n", file); - exit(EXIT_FAILURE); - } - - filename = file; - line_nr = 1; - - line = op_get_line(fp); - - while (line) { - if (empty_line(line) || comment_line(line)) - goto next; - - seen_name = 0; - seen_event = 0; - seen_counters = 0; - seen_um = 0; - seen_minimum = 0; - event = new_event(); - - c = line; - while (next_token(&c, &name, &value)) { - if (strcmp(name, "name") == 0) { - if (seen_name) - parse_error("duplicate name: tag"); - seen_name = 1; - if (strchr(value, '/') != NULL) - parse_error("invalid event name"); - if (strchr(value, '.') != NULL) - parse_error("invalid event name"); - event->name = value; - } else if (strcmp(name, "event") == 0) { - if (seen_event) - parse_error("duplicate event: tag"); - seen_event = 1; - event->val = parse_hex(value); - free(value); - } else if (strcmp(name, "counters") == 0) { - if (seen_counters) - parse_error("duplicate counters: tag"); - seen_counters = 1; - event->counter_mask = parse_counter_mask(value); - free(value); - } else if (strcmp(name, "um") == 0) { - if (seen_um) - parse_error("duplicate um: tag"); - seen_um = 1; - event->unit = find_um(value); - event->unit->used = 1; - free(value); - } else if (strcmp(name, "minimum") == 0) { - if (seen_minimum) - parse_error("duplicate minimum: tag"); - seen_minimum = 1; - event->min_count = parse_int(value); - free(value); - } else if (strcmp(name, "desc") == 0) { - event->desc = value; - } else { - parse_error("unknown tag"); - } - - free(name); - } -next: - free(line); - line = op_get_line(fp); - ++line_nr; - } - - fclose(fp); -} - - -/* usefull for make check */ -static void check_unit_mask(struct op_unit_mask const * um, - char const * cpu_name) -{ - u32 i; - - if (!um->used) { - fprintf(stderr, "um %s is not used\n", um->name); - exit(EXIT_FAILURE); - } - - if (um->unit_type_mask == utm_mandatory && um->num != 1) { - fprintf(stderr, "mandatory um %s doesn't contain exactly one " - "entry (%s)\n", um->name, cpu_name); - exit(EXIT_FAILURE); - } else if (um->unit_type_mask == utm_bitmask) { - u32 default_mask = um->default_mask; - for (i = 0; i < um->num; ++i) - default_mask &= ~um->um[i].value; - - if (default_mask) { - fprintf(stderr, "um %s default mask is not valid " - "(%s)\n", um->name, cpu_name); - exit(EXIT_FAILURE); - } - } else { - for (i = 0; i < um->num; ++i) { - if (um->default_mask == um->um[i].value) - break; - } - - if (i == um->num) { - fprintf(stderr, "exclusive um %s default value is not " - "valid (%s)\n", um->name, cpu_name); - exit(EXIT_FAILURE); - } - } -} - - -static void load_events(op_cpu cpu_type) -{ - char const * cpu_name = op_get_cpu_name(cpu_type); - char * event_dir; - char * event_file; - char * um_file; - char * dir; - struct list_head * pos; - - if (!list_empty(&events_list)) - return; - - dir = getenv("OPROFILE_EVENTS_DIR"); - if (dir == NULL) - dir = OP_DATADIR; - - event_dir = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) + - strlen("/") + 1); - strcpy(event_dir, dir); - strcat(event_dir, "/"); - - strcat(event_dir, cpu_name); - strcat(event_dir, "/"); - - event_file = xmalloc(strlen(event_dir) + strlen("events") + 1); - strcpy(event_file, event_dir); - strcat(event_file, "events"); - - um_file = xmalloc(strlen(event_dir) + strlen("unit_masks") + 1); - strcpy(um_file, event_dir); - strcat(um_file, "unit_masks"); - - read_unit_masks(um_file); - read_events(event_file); - - /* sanity check: all unit mask must be used */ - list_for_each(pos, &um_list) { - struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); - - check_unit_mask(um, cpu_name); - } - - free(um_file); - free(event_file); - free(event_dir); -} - - -struct list_head * op_events(op_cpu cpu_type) -{ - load_events(cpu_type); - return &events_list; -} - - -static void delete_unit_mask(struct op_unit_mask * unit) -{ - u32 cur; - for (cur = 0 ; cur < unit->num ; ++cur) { - if (unit->um[cur].desc) - free(unit->um[cur].desc); - } - - if (unit->name) - free(unit->name); - - list_del(&unit->um_next); - free(unit); -} - - -static void delete_event(struct op_event * event) -{ - if (event->name) - free(event->name); - if (event->desc) - free(event->desc); - - list_del(&event->event_next); - free(event); -} - - -void op_free_events(void) -{ - struct list_head * pos, * pos2; - list_for_each_safe(pos, pos2, &events_list) { - struct op_event * event = list_entry(pos, struct op_event, event_next); - delete_event(event); - } - - list_for_each_safe(pos, pos2, &um_list) { - struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next); - delete_unit_mask(unit); - } -} - - -static struct op_event * find_event(u32 nr) -{ - struct list_head * pos; - - list_for_each(pos, &events_list) { - struct op_event * event = list_entry(pos, struct op_event, event_next); - if (event->val == nr) - return event; - } - - return NULL; -} - - -static FILE * open_event_mapping_file(char const * cpu_name) -{ - char * ev_map_file; - char * dir; - dir = getenv("OPROFILE_EVENTS_DIR"); - if (dir == NULL) - dir = OP_DATADIR; - - ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) + - strlen("/") + + strlen("event_mappings") + 1); - strcpy(ev_map_file, dir); - strcat(ev_map_file, "/"); - - strcat(ev_map_file, cpu_name); - strcat(ev_map_file, "/"); - strcat(ev_map_file, "event_mappings"); - filename = ev_map_file; - return (fopen(ev_map_file, "r")); -} - - -/** - * This function is PPC64-specific. - */ -static char const * get_mapping(u32 nr, FILE * fp) -{ - char * line; - char * name; - char * value; - char const * c; - char * map = NULL; - int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0; - u32 mmcr0 = 0; - u64 mmcr1 = 0; - u32 mmcra = 0; - int event_found = 0; - - line_nr = 1; - line = op_get_line(fp); - while (line && !event_found) { - if (empty_line(line) || comment_line(line)) - goto next; - - seen_event = 0; - seen_mmcr0 = 0; - seen_mmcr1 = 0; - seen_mmcra = 0; - mmcr0 = 0; - mmcr1 = 0; - mmcra = 0; - - c = line; - while (next_token(&c, &name, &value)) { - if (strcmp(name, "event") == 0) { - u32 evt; - if (seen_event) - parse_error("duplicate event tag"); - seen_event = 1; - evt = parse_hex(value); - if (evt == nr) - event_found = 1; - free(value); - } else if (strcmp(name, "mmcr0") == 0) { - if (seen_mmcr0) - parse_error("duplicate mmcr0 tag"); - seen_mmcr0 = 1; - mmcr0 = parse_hex(value); - free(value); - } else if (strcmp(name, "mmcr1") == 0) { - if (seen_mmcr1) - parse_error("duplicate mmcr1: tag"); - seen_mmcr1 = 1; - mmcr1 = parse_long_hex(value); - free(value); - } else if (strcmp(name, "mmcra") == 0) { - if (seen_mmcra) - parse_error("duplicate mmcra: tag"); - seen_mmcra = 1; - mmcra = parse_hex(value); - free(value); - } else { - parse_error("unknown tag"); - } - - free(name); - } -next: - free(line); - line = op_get_line(fp); - ++line_nr; - } - if (event_found) { - if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) { - fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename); - exit(EXIT_FAILURE); - } - map = xmalloc(70); - snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u", - mmcr0, mmcr1, mmcra); - } - - return map; -} - - -char const * find_mapping_for_event(u32 nr, op_cpu cpu_type) -{ - char const * cpu_name = op_get_cpu_name(cpu_type); - FILE * fp = open_event_mapping_file(cpu_name); - char const * map = NULL; - switch (cpu_type) { - case CPU_PPC64_PA6T: - case CPU_PPC64_970: - case CPU_PPC64_970MP: - case CPU_PPC64_POWER4: - case CPU_PPC64_POWER5: - case CPU_PPC64_POWER5p: - case CPU_PPC64_POWER5pp: - case CPU_PPC64_POWER6: - if (!fp) { - fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename); - exit(EXIT_FAILURE); - } else { - map = get_mapping(nr, fp); - } - break; - default: - break; - } - - if (fp) - fclose(fp); - - return map; -} - - -struct op_event * find_event_by_name(char const * name) -{ - struct list_head * pos; - - list_for_each(pos, &events_list) { - struct op_event * event = list_entry(pos, struct op_event, event_next); - if (strcmp(event->name, name) == 0) - return event; - } - - return NULL; -} - - -struct op_event * op_find_event(op_cpu cpu_type, u32 nr) -{ - struct op_event * event; - - load_events(cpu_type); - - event = find_event(nr); - - return event; -} - - -int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type) -{ - int ret = OP_OK_EVENT; - struct op_event * event; - size_t i; - u32 ctr_mask = 1 << ctr; - - load_events(cpu_type); - - event = find_event(nr); - - if (!event) { - ret |= OP_INVALID_EVENT; - return ret; - } - - if ((event->counter_mask & ctr_mask) == 0) - ret |= OP_INVALID_COUNTER; - - if (event->unit->unit_type_mask == utm_bitmask) { - for (i = 0; i < event->unit->num; ++i) - um &= ~(event->unit->um[i].value); - - if (um) - ret |= OP_INVALID_UM; - - } else { - for (i = 0; i < event->unit->num; ++i) { - if (event->unit->um[i].value == um) - break; - } - - if (i == event->unit->num) - ret |= OP_INVALID_UM; - } - - return ret; -} - - -void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) -{ - descr->name = ""; - descr->um = 0x0; - /* A fixed value of CPU cycles; this should ensure good - * granulity even on faster CPUs, though it will generate more - * interrupts. - */ - descr->count = 100000; - - switch (cpu_type) { - case CPU_PPRO: - case CPU_PII: - case CPU_PIII: - case CPU_P6_MOBILE: - case CPU_CORE: - case CPU_CORE_2: - case CPU_ATHLON: - case CPU_HAMMER: - case CPU_FAMILY10: - descr->name = "CPU_CLK_UNHALTED"; - break; - - case CPU_RTC: - descr->name = "RTC_INTERRUPTS"; - descr->count = 1024; - break; - - case CPU_P4: - case CPU_P4_HT2: - descr->name = "GLOBAL_POWER_EVENTS"; - descr->um = 0x1; - break; - - case CPU_IA64: - case CPU_IA64_1: - case CPU_IA64_2: - descr->count = 1000000; - descr->name = "CPU_CYCLES"; - break; - - case CPU_AXP_EV4: - case CPU_AXP_EV5: - case CPU_AXP_PCA56: - case CPU_AXP_EV6: - case CPU_AXP_EV67: - descr->name = "CYCLES"; - break; - - // we could possibly use the CCNT - case CPU_ARM_XSCALE1: - case CPU_ARM_XSCALE2: - case CPU_ARM_MPCORE: - case CPU_ARM_V6: - case CPU_AVR32: - descr->name = "CPU_CYCLES"; - break; - - case CPU_PPC64_PA6T: - case CPU_PPC64_970: - case CPU_PPC64_970MP: - case CPU_PPC_7450: - case CPU_PPC64_POWER4: - case CPU_PPC64_POWER5: - case CPU_PPC64_POWER6: - case CPU_PPC64_POWER5p: - case CPU_PPC64_POWER5pp: - case CPU_PPC64_CELL: - descr->name = "CYCLES"; - break; - - case CPU_MIPS_20K: - descr->name = "CYCLES"; - break; - - case CPU_MIPS_24K: - descr->name = "INSTRUCTIONS"; - break; - - case CPU_MIPS_34K: - descr->name = "INSTRUCTIONS"; - break; - - case CPU_MIPS_5K: - case CPU_MIPS_25K: - descr->name = "CYCLES"; - break; - - case CPU_MIPS_R10000: - case CPU_MIPS_R12000: - descr->name = "INSTRUCTIONS_GRADUATED"; - break; - - case CPU_MIPS_RM7000: - case CPU_MIPS_RM9000: - descr->name = "INSTRUCTIONS_ISSUED"; - break; - - case CPU_MIPS_SB1: - descr->name = "INSN_SURVIVED_STAGE7"; - break; - - case CPU_MIPS_VR5432: - case CPU_MIPS_VR5500: - descr->name = "INSTRUCTIONS_EXECUTED"; - break; - - case CPU_PPC_E500: - case CPU_PPC_E500_2: - case CPU_PPC_E300: - descr->name = "CPU_CLK"; - break; - - // don't use default, if someone add a cpu he wants a compiler - // warning if he forgets to handle it here. - case CPU_TIMER_INT: - case CPU_NO_GOOD: - case MAX_CPU_TYPE: - break; - } -} diff --git a/libop/op_events.h b/libop/op_events.h deleted file mode 100644 index f6462fc..0000000 --- a/libop/op_events.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file op_events.h - * Details of PMC profiling events - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_EVENTS_H -#define OP_EVENTS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "op_cpu_type.h" -#include "op_types.h" -#include "op_list.h" - -/** Describe an unit mask type. Events can optionally use a filter called - * the unit mask. the mask type can be a bitmask or a discrete value */ -enum unit_mask_type { - utm_mandatory, /**< useless but required by the hardware */ - utm_exclusive, /**< only one of the values is allowed */ - utm_bitmask /**< bitmask */ -}; - -/** up to thirty two allowed unit masks */ -#define MAX_UNIT_MASK 32 - - -/** Describe an unit mask. */ -struct op_unit_mask { - char * name; /**< name of unit mask type */ - u32 num; /**< number of possible unit masks */ - enum unit_mask_type unit_type_mask; - u32 default_mask; /**< only the gui use it */ - struct op_described_um { - u32 value; - char * desc; - } um[MAX_UNIT_MASK]; - struct list_head um_next; /**< next um in list */ - int used; /**< used by events file parser */ -}; - - -/** Describe an event. */ -struct op_event { - u32 counter_mask; /**< bitmask of allowed counter */ - u32 val; /**< event number */ - /** which unit mask if any allowed */ - struct op_unit_mask * unit; - char * name; /**< the event name */ - char * desc; /**< the event description */ - int min_count; /**< minimum counter value allowed */ - struct list_head event_next; /**< next event in list */ -}; - -/** Return the known events list. Idempotent */ -struct list_head * op_events(op_cpu cpu_type); - -/** Find a given event, returns NULL on error */ -struct op_event * op_find_event(op_cpu cpu_type, u32 nr); - -/** Find a given event by name */ -struct op_event * find_event_by_name(char const * name); - -/** - * Find a mapping for a given event ID for architectures requiring additional information - * from what is held in the events file. - */ -char const * find_mapping_for_event(u32 val, op_cpu cpu_type); - - -/** op_check_events() return code */ -enum op_event_check { - OP_OK_EVENT = 0, /**< event is valid and allowed */ - OP_INVALID_EVENT = 1, /**< event number is invalid */ - OP_INVALID_UM = 2, /**< unit mask is invalid */ - OP_INVALID_COUNTER = 4 /**< event is not allowed for the given counter */ -}; - -/** - * sanity check event values - * @param ctr counter number - * @param event value for counter - * @param um unit mask for counter - * @param cpu_type processor type - * - * Check that the counter event and unit mask values are allowed. - * - * The function returns bitmask of failure cause 0 otherwise - * - * \sa op_cpu, OP_EVENTS_OK - */ -int op_check_events(int ctr, u32 event, u32 um, op_cpu cpu_type); - -/** - * free memory used by any call to above function. Need to be called only once - */ -void op_free_events(void); - -struct op_default_event_descr { - char * name; - unsigned long count; - unsigned long um; -}; - -/** - * op_default_event - return the details of the default event - * @param cpu_type cpu type - * @param descr filled event description - * - * Fills in the event description if applicable - */ -void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr); - -#ifdef __cplusplus -} -#endif - -#endif /* OP_EVENTS_H */ diff --git a/libop/op_get_interface.c b/libop/op_get_interface.c deleted file mode 100644 index bdf72a5..0000000 --- a/libop/op_get_interface.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @file op_get_interface.c - * Determine which oprofile kernel interface used - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author Will Cohen - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "op_cpu_type.h" -#include "op_file.h" - -op_interface op_get_interface(void) -{ - static op_interface current_interface = OP_INTERFACE_NO_GOOD; - - if (current_interface != OP_INTERFACE_NO_GOOD) - return current_interface; - - if (op_file_readable("/proc/sys/dev/oprofile/cpu_type")) { - current_interface = OP_INTERFACE_24; - } else if (op_file_readable("/dev/oprofile/cpu_type")) { - current_interface = OP_INTERFACE_26; - } - - return current_interface; -} diff --git a/libop/op_hw_config.h b/libop/op_hw_config.h deleted file mode 100644 index 169b36b..0000000 --- a/libop/op_hw_config.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file op_hw_config.h - * Configuration parameters that are dependent on CPU/architecture - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_HW_CONFIG_H -#define OP_HW_CONFIG_H - -/** maximum number of counters, up to 4 for Athlon (18 for P4). The primary - * use of this variable is for static/local array dimension. Never use it in - * loop or in array index access/index checking unless you know what you - * made. */ -#ifdef __alpha__ -#define OP_MAX_COUNTERS 20 -#else -#define OP_MAX_COUNTERS 8 -#endif - -/** maximum number of events between interrupts. Counters are 40 bits, but - * for convenience we only use 32 bits. The top bit is used for overflow - * detection, so user can set up to (2^31)-1 */ -#define OP_MAX_PERF_COUNT 2147483647UL - -#endif /* OP_HW_CONFIG_H */ diff --git a/libop/op_interface.h b/libop/op_interface.h deleted file mode 100644 index fa2ecbd..0000000 --- a/libop/op_interface.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file op_interface.h - * - * Module / user space interface for 2.4 - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_INTERFACE_H -#define OP_INTERFACE_H - -#include "op_config.h" -#include "op_types.h" - -/*@{\name notifications types encoded in op_note::type */ -/** fork(),vfork(),clone() */ -#define OP_FORK 1 -/** mapping */ -#define OP_MAP 2 -/** execve() */ -#define OP_EXEC 4 -/** init_module() */ -#define OP_DROP_MODULES 8 -/** exit() */ -#define OP_EXIT 16 -/*@}*/ - -/** Data type to transfer samples counts from the module to the daemon */ -struct op_sample { - unsigned long eip; /**< eip value where occur interrupt */ - u32 counter; /**< counter nr */ - u32 pid; /**< 32 bits can hold any pid */ - u32 tgid; /**< always equal to pid for kernel < 2.4.0 */ -}; - -/** the current kernel-side profiler state */ -enum oprof_state { - STOPPED = 0, - STOPPING = 1, - RUNNING = 2 -}; - -/** - * The head structure of a kernel sample buffer. - */ -struct op_buffer_head { - int cpu_nr; /**< the CPU number of this buffer */ - size_t count; /**< number of samples in this buffer */ - enum oprof_state state; /**< current profiler state */ - struct op_sample buffer[0]; /**< the sample buffer */ -} __attribute__((__packed__)); - -/** - * Data type used by the module to notify daemon of fork/exit/mapping etc. - * Meanings of fields depend on the type of notification encoded in the type - * field. - * \sa OP_FORK, OP_EXEC, OP_MAP, OP_DROP_MODULES and OP_EXIT - */ -struct op_note { - unsigned long addr; - unsigned long len; - unsigned long offset; - unsigned int hash; - unsigned int pid; - unsigned int tgid; - unsigned short type; -}; - -/** - * A path component. Directory name are stored as a stack of path components. - * Note than the name index acts also as an unique identifier - */ -struct op_hash_index { - /** index inside the string pool */ - u32 name; - /** parent component, zero if this component is the root */ - u32 parent; -} __attribute__((__packed__)); - -/** size of hash map in bytes */ -#define OP_HASH_MAP_SIZE (OP_HASH_MAP_NR * sizeof(struct op_hash_index) + POOL_SIZE) - -#endif /* OP_INTERFACE_H */ diff --git a/libop/op_mangle.c b/libop/op_mangle.c deleted file mode 100644 index 1efe5b1..0000000 --- a/libop/op_mangle.c +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file op_mangle.c - * Mangling of sample file names - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#include "op_mangle.h" - -#include <string.h> -#include <stdio.h> - -#include "op_libiberty.h" - -#include "op_sample_file.h" -#include "op_config.h" - -static void append_image(char * dest, int flags, int anon, char const * name, char const * anon_name) -{ - if ((flags & MANGLE_KERNEL) && !strchr(name, '/')) { - strcat(dest, "{kern}/"); - } else if (anon) { - strcat(dest, "{anon:"); - strcat(dest, anon_name); - strcat(dest,"}/"); - } else { - strcat(dest, "{root}/"); - } - - strcat(dest, name); - strcat(dest, "/"); -} - -char * op_mangle_filename(struct mangle_values const * values) -{ - char * mangled; - size_t len; - int anon = values->flags & MANGLE_ANON; - int cg_anon = values->flags & MANGLE_CG_ANON; - /* if dep_name != image_name we need to invert them (and so revert them - * unconditionally because if they are equal it doesn't hurt to invert - * them), see P:3, FIXME: this is a bit weirds, we prolly need to - * reword pp_interface */ - char const * image_name = values->dep_name; - char const * anon_name = values->anon_name; - char const * dep_name = values->image_name; - char const * cg_image_name = values->cg_image_name; - - len = strlen(op_samples_current_dir) + strlen(dep_name) + 1 - + strlen(values->event_name) + 1 + strlen(image_name) + 1; - - if (values->flags & MANGLE_CALLGRAPH) - len += strlen(cg_image_name) + 1; - - if (anon || cg_anon) - len += strlen(anon_name); - - /* provision for tgid, tid, unit_mask, cpu and some {root}, {dep}, - * {kern}, {anon} and {cg} marker */ - /* FIXME: too ugly */ - len += 256; - - mangled = xmalloc(len); - - strcpy(mangled, op_samples_current_dir); - append_image(mangled, values->flags, 0, image_name, anon_name); - - strcat(mangled, "{dep}" "/"); - append_image(mangled, values->flags, anon, dep_name, anon_name); - - if (values->flags & MANGLE_CALLGRAPH) { - strcat(mangled, "{cg}" "/"); - append_image(mangled, values->flags, cg_anon, - cg_image_name, anon_name); - } - - strcat(mangled, values->event_name); - sprintf(mangled + strlen(mangled), ".%d.%d.", - values->count, values->unit_mask); - - if (values->flags & MANGLE_TGID) { - sprintf(mangled + strlen(mangled), "%d.", values->tgid); - } else { - sprintf(mangled + strlen(mangled), "%s.", "all"); - } - - if (values->flags & MANGLE_TID) { - sprintf(mangled + strlen(mangled), "%d.", values->tid); - } else { - sprintf(mangled + strlen(mangled), "%s.", "all"); - } - - if (values->flags & MANGLE_CPU) { - sprintf(mangled + strlen(mangled), "%d", values->cpu); - } else { - sprintf(mangled + strlen(mangled), "%s", "all"); - } - - return mangled; -} diff --git a/libop/op_mangle.h b/libop/op_mangle.h deleted file mode 100644 index 9b600dc..0000000 --- a/libop/op_mangle.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file op_mangle.h - * Mangling of sample file names - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_MANGLE_H -#define OP_MANGLE_H - -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -enum mangle_flags { - MANGLE_NONE = 0, - MANGLE_CPU = (1 << 0), - MANGLE_TGID = (1 << 1), - MANGLE_TID = (1 << 2), - MANGLE_KERNEL = (1 << 3), - MANGLE_CALLGRAPH = (1 << 4), - MANGLE_ANON = (1 << 5), - MANGLE_CG_ANON = (1 << 6), -}; - -/** - * Temporary structure for passing parameters to - * op_mangle_filename. - */ -struct mangle_values { - int flags; - - char const * image_name; - char const * anon_name; - char const * dep_name; - char const * cg_image_name; - char const * event_name; - int count; - unsigned int unit_mask; - pid_t tgid; - pid_t tid; - int cpu; -}; - -/** - * op_mangle_filename - mangle a sample filename - * @param values parameters to use as mangling input - * - * See also PP:3 for the encoding scheme - * - * Returns a char* pointer to the mangled string. Caller - * is responsible for freeing this string. - */ -char * op_mangle_filename(struct mangle_values const * values); - -#ifdef __cplusplus -} -#endif - -#endif /* OP_MANGLE_H */ diff --git a/libop/op_parse_event.c b/libop/op_parse_event.c deleted file mode 100644 index 920d617..0000000 --- a/libop/op_parse_event.c +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file op_parse_event.c - * event parsing - * - * You can have silliness here. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#include <stdio.h> -#include <stdlib.h> - -#include "op_parse_event.h" -#include "op_string.h" - -static char * next_part(char const ** str) -{ - char const * c; - char * ret; - - if ((*str)[0] == '\0') - return NULL; - - if ((*str)[0] == ':') - ++(*str); - - c = *str; - - while (*c != '\0' && *c != ':') - ++c; - - if (c == *str) - return NULL; - - ret = op_xstrndup(*str, c - *str); - *str += c - *str; - return ret; -} - - -static int parse_ulong(char const * str) -{ - unsigned long value; - char * end; - value = strtoul(str, &end, 0); - if (end && *end) { - fprintf(stderr, "Invalid event part %s\n", str); - exit(EXIT_FAILURE); - } - - return value; -} - - -size_t parse_events(struct parsed_event * parsed_events, size_t max_events, - char const * const * events) -{ - size_t i = 0; - - while (events[i]) { - char const * cp = events[i]; - char * part = next_part(&cp); - - if (i >= max_events) { - fprintf(stderr, "Too many events specified: CPU " - "only has %lu counters.\n", - (unsigned long) max_events); - exit(EXIT_FAILURE); - } - - if (!part) { - fprintf(stderr, "Invalid event %s\n", cp); - exit(EXIT_FAILURE); - } - - parsed_events[i].name = part; - - part = next_part(&cp); - - if (!part) { - fprintf(stderr, "Invalid count for event %s\n", events[i]); - exit(EXIT_FAILURE); - } - - parsed_events[i].count = parse_ulong(part); - free(part); - - parsed_events[i].unit_mask = 0; - part = next_part(&cp); - - if (part) { - parsed_events[i].unit_mask = parse_ulong(part); - free(part); - } - - parsed_events[i].kernel = 1; - part = next_part(&cp); - - if (part) { - parsed_events[i].kernel = parse_ulong(part); - free(part); - } - - parsed_events[i].user = 1; - part = next_part(&cp); - - if (part) { - parsed_events[i].user = parse_ulong(part); - free(part); - } - - ++i; - } - - return i; -} diff --git a/libop/op_parse_event.h b/libop/op_parse_event.h deleted file mode 100644 index 247a355..0000000 --- a/libop/op_parse_event.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file op_parse_event.h - * event parsing - * - * You can have silliness here. - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_PARSE_EVENT_H -#define OP_PARSE_EVENT_H - -#include <stddef.h> - -struct parsed_event { - char * name; - int count; - int unit_mask; - int kernel; - int user; -}; - -/** - * @param parsed_events array of events to fill in - * @param max_events size of parsed_events - * @param events null terminated array of events string on the form - * event_name:count[:unit_mask:kernel:user] - * - * parse events given by the nil terminated array events and fill in - * parsed_events with results. Events validity are not checked except. - * A fatal error occur if number of events is greater than max_events. - * - * Return the number of events parsed. - */ -size_t parse_events(struct parsed_event * parsed_events, size_t max_events, - char const * const * events); - -#endif /* !OP_PARSE_EVENT_H */ diff --git a/libop/op_sample_file.h b/libop/op_sample_file.h deleted file mode 100644 index 4f9f1d0..0000000 --- a/libop/op_sample_file.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file op_sample_file.h - * Sample file format - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - */ - -#ifndef OP_SAMPLE_FILE_H -#define OP_SAMPLE_FILE_H - -#include "op_types.h" - -#include <stdint.h> -#include <time.h> - -/* header of the sample files */ -struct opd_header { - u8 magic[4]; - u32 version; - u32 cpu_type; - u32 ctr_event; - u32 ctr_um; - u32 ctr_count; - // for cg file the from_cg_is_kernel - u32 is_kernel; - double cpu_speed; - time_t mtime; - u32 cg_to_is_kernel; - /* spu_profile=1 says sample file contains Cell BE SPU profile data */ - u32 spu_profile; - uint64_t embedded_offset; - u64 anon_start; - u64 cg_to_anon_start; - /* binary compatibility reserve */ - u32 reserved1[1]; -}; - -#endif /* OP_SAMPLE_FILE_H */ |