diff options
author | Ben Cheng <bccheng@android.com> | 2010-09-02 21:48:01 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@android.com> | 2010-09-02 21:48:01 -0700 |
commit | 5bbbe460405564a1aed8a67a13c43e9356ffc656 (patch) | |
tree | b46ca39ef816f5522cbd16023291657206751cc5 | |
parent | c4ad4bafe1bc1c9e92be1995c288ff89eb7b191e (diff) | |
download | oprofile-5bbbe460405564a1aed8a67a13c43e9356ffc656.tar.gz |
Port work-in-progress oprofile with Cortex-A9 support.
Change-Id: I26ecf3697c651dae31050081d6918ee5fc87915d
-rw-r--r-- | daemon/opd_events.c | 11 | ||||
-rw-r--r-- | daemon/opd_perfmon.c | 92 | ||||
-rw-r--r-- | daemon/opd_pipe.c | 11 | ||||
-rw-r--r-- | libop/op_cpu_type.c | 11 | ||||
-rw-r--r-- | libop/op_cpu_type.h | 7 | ||||
-rw-r--r-- | libop/op_events.c | 8 | ||||
-rw-r--r-- | libop/op_hw_specific.h | 15 | ||||
-rw-r--r-- | libop/op_xml_events.c | 69 | ||||
-rw-r--r-- | libop/op_xml_out.c | 198 | ||||
-rw-r--r-- | libop/op_xml_out.h | 11 | ||||
-rw-r--r-- | libutil/fscanf.c | 22 | ||||
-rw-r--r-- | libutil/op_cpufreq.c | 5 |
12 files changed, 255 insertions, 205 deletions
diff --git a/daemon/opd_events.c b/daemon/opd_events.c index fa017e4..b544fb3 100644 --- a/daemon/opd_events.c +++ b/daemon/opd_events.c @@ -142,19 +142,8 @@ struct opd_event * find_counter_event(unsigned long counter) } fprintf(stderr, "Unknown event for counter %lu\n", counter); - /* - * ANDROID FIXME - from time to time there seems to be 1 phantom event - * reported from counter 3 when only counter 0 is enabled. Instead of - * crashing the daemon and losing tons of useful samples, we just - * charge the erroneous single count to the first event. - */ -#ifdef ANDROID - return &opd_events[0]; -#else abort(); return NULL; - -#endif } diff --git a/daemon/opd_perfmon.c b/daemon/opd_perfmon.c index a1b158a..97f307c 100644 --- a/daemon/opd_perfmon.c +++ b/daemon/opd_perfmon.c @@ -30,6 +30,8 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> #ifdef HAVE_SCHED_SETAFFINITY #include <sched.h> #endif @@ -98,7 +100,6 @@ static struct child * children; static void perfmon_start_child(int ctx_fd) { if (perfmonctl(ctx_fd, PFM_START, 0, 0) == -1) { - perror("Couldn't start perfmon: "); exit(EXIT_FAILURE); } } @@ -107,7 +108,6 @@ static void perfmon_start_child(int ctx_fd) static void perfmon_stop_child(int ctx_fd) { if (perfmonctl(ctx_fd, PFM_STOP, 0, 0) == -1) { - perror("Couldn't stop perfmon: "); exit(EXIT_FAILURE); } } @@ -141,7 +141,6 @@ static void child_sigusr2(int val __attribute__((unused))) static void child_sigterm(int val __attribute__((unused))) { - printf("Child received SIGTERM, killing parent.\n"); kill(getppid(), SIGTERM); } @@ -149,15 +148,15 @@ static void child_sigterm(int val __attribute__((unused))) static void set_affinity(size_t cpu) { cpu_set_t set; + int err; CPU_ZERO(&set); CPU_SET(cpu, &set); - int err = sched_setaffinity(getpid(), sizeof(set), &set); + err = sched_setaffinity(getpid(), sizeof(set), &set); if (err == -1) { - fprintf(stderr, "Failed to set affinity: %s\n", - strerror(errno)); + perror("Failed to set affinity"); exit(EXIT_FAILURE); } } @@ -178,7 +177,7 @@ static void setup_signals(void) sigemptyset(&act.sa_mask); if (sigaction(SIGUSR1, &act, NULL)) { - perror("oprofiled: install of SIGUSR1 handler failed: "); + perror("oprofiled: install of SIGUSR1 handler failed"); exit(EXIT_FAILURE); } @@ -187,7 +186,7 @@ static void setup_signals(void) sigemptyset(&act.sa_mask); if (sigaction(SIGUSR2, &act, NULL)) { - perror("oprofiled: install of SIGUSR2 handler failed: "); + perror("oprofiled: install of SIGUSR2 handler failed"); exit(EXIT_FAILURE); } @@ -196,7 +195,7 @@ static void setup_signals(void) sigemptyset(&act.sa_mask); if (sigaction(SIGTERM, &act, NULL)) { - perror("oprofiled: install of SIGTERM handler failed: "); + perror("oprofiled: install of SIGTERM handler failed"); exit(EXIT_FAILURE); } } @@ -214,8 +213,7 @@ static void create_context(struct child * self) err = perfmonctl(0, PFM_CREATE_CONTEXT, &ctx, 1); if (err == -1) { - fprintf(stderr, "CREATE_CONTEXT failed: %s\n", - strerror(errno)); + perror("CREATE_CONTEXT failed"); exit(EXIT_FAILURE); } @@ -268,13 +266,13 @@ static void write_pmu(struct child * self) err = perfmonctl(self->ctx_fd, PFM_WRITE_PMCS, pc, i); if (err == -1) { - perror("Couldn't write PMCs: "); + perror("Couldn't write PMCs"); exit(EXIT_FAILURE); } err = perfmonctl(self->ctx_fd, PFM_WRITE_PMDS, pd, i); if (err == -1) { - perror("Couldn't write PMDs: "); + perror("Couldn't write PMDs"); exit(EXIT_FAILURE); } } @@ -290,7 +288,7 @@ static void load_context(struct child * self) err = perfmonctl(self->ctx_fd, PFM_LOAD_CONTEXT, &load_args, 1); if (err == -1) { - perror("Couldn't load context: "); + perror("Couldn't load context"); exit(EXIT_FAILURE); } } @@ -304,13 +302,17 @@ static void notify_parent(struct child * self, size_t cpu) if (ret == sizeof(size_t)) break; if (ret < 0 && errno != EINTR) { - fprintf(stderr, "Failed to write child pipe with %s\n", - strerror(errno)); + perror("Failed to write child pipe:"); exit(EXIT_FAILURE); } } } +static struct child * inner_child; +void close_pipe(void) +{ + close(inner_child->up_pipe[1]); +} static void run_child(size_t cpu) { @@ -321,6 +323,19 @@ static void run_child(size_t cpu) self->sigusr2 = 0; self->sigterm = 0; + inner_child = self; + if (atexit(close_pipe)){ + close_pipe(); + exit(EXIT_FAILURE); + } + + umask(0); + /* Change directory to allow directory to be removed */ + if (chdir("/") < 0) { + perror("Unable to chdir to \"/\""); + exit(EXIT_FAILURE); + } + setup_signals(); set_affinity(cpu); @@ -333,6 +348,11 @@ static void run_child(size_t cpu) notify_parent(self, cpu); + /* Redirect standard files to /dev/null */ + freopen( "/dev/null", "r", stdin); + freopen( "/dev/null", "w", stdout); + freopen( "/dev/null", "w", stderr); + for (;;) { sigset_t sigmask; sigfillset(&sigmask); @@ -341,15 +361,11 @@ static void run_child(size_t cpu) sigdelset(&sigmask, SIGTERM); if (self->sigusr1) { - printf("PFM_START on CPU%d\n", (int)cpu); - fflush(stdout); perfmon_start_child(self->ctx_fd); self->sigusr1 = 0; } if (self->sigusr2) { - printf("PFM_STOP on CPU%d\n", (int)cpu); - fflush(stdout); perfmon_stop_child(self->ctx_fd); self->sigusr2 = 0; } @@ -367,9 +383,8 @@ static void wait_for_child(struct child * child) ret = read(child->up_pipe[0], &tmp, sizeof(size_t)); if (ret == sizeof(size_t)) break; - if (ret < 0 && errno != EINTR) { - fprintf(stderr, "Failed to read child pipe with %s\n", - strerror(errno)); + if ((ret < 0 && errno != EINTR) || ret == 0 ) { + perror("Failed to read child pipe"); exit(EXIT_FAILURE); } } @@ -377,7 +392,6 @@ static void wait_for_child(struct child * child) fflush(stdout); close(child->up_pipe[0]); - close(child->up_pipe[1]); } static struct child* xen_ctx; @@ -417,25 +431,26 @@ void perfmon_init(void) nr_cpus = nr; children = xmalloc(sizeof(struct child) * nr_cpus); + bzero(children, sizeof(struct child) * nr_cpus); for (i = 0; i < nr_cpus; ++i) { int ret; if (pipe(children[i].up_pipe)) { - perror("Couldn't create child pipe.\n"); + perror("Couldn't create child pipe"); exit(EXIT_FAILURE); } ret = fork(); if (ret == -1) { - fprintf(stderr, "Couldn't fork perfmon child.\n"); + perror("Couldn't fork perfmon child"); exit(EXIT_FAILURE); } else if (ret == 0) { - printf("Running perfmon child on CPU%d.\n", (int)i); - fflush(stdout); + close(children[i].up_pipe[0]); run_child(i); } else { children[i].pid = ret; + close(children[i].up_pipe[1]); printf("Waiting on CPU%d\n", (int)i); wait_for_child(&children[i]); } @@ -454,8 +469,12 @@ void perfmon_exit(void) return; for (i = 0; i < nr_cpus; ++i) { - kill(children[i].pid, SIGKILL); - waitpid(children[i].pid, NULL, 0); + if (children[i].pid) { + int c_pid = children[i].pid; + children[i].pid = 0; + if (kill(c_pid, SIGKILL)==0) + waitpid(c_pid, NULL, 0); + } } } @@ -472,8 +491,12 @@ void perfmon_start(void) return; } - for (i = 0; i < nr_cpus; ++i) - kill(children[i].pid, SIGUSR1); + for (i = 0; i < nr_cpus; ++i) { + if (kill(children[i].pid, SIGUSR1)) { + perror("Unable to start perfmon"); + exit(EXIT_FAILURE); + } + } } @@ -490,7 +513,10 @@ void perfmon_stop(void) } for (i = 0; i < nr_cpus; ++i) - kill(children[i].pid, SIGUSR2); + if (kill(children[i].pid, SIGUSR2)) { + perror("Unable to stop perfmon"); + exit(EXIT_FAILURE); + } } #endif /* __ia64__ */ diff --git a/daemon/opd_pipe.c b/daemon/opd_pipe.c index a5c334a..3c81979 100644 --- a/daemon/opd_pipe.c +++ b/daemon/opd_pipe.c @@ -22,6 +22,7 @@ #include <sys/stat.h> static int fifo; +static FILE * fifo_fd = NULL; void opd_create_pipe(void) { @@ -48,6 +49,8 @@ void opd_open_pipe(void) void opd_close_pipe(void) { + if (fifo_fd) + fclose(fifo_fd); close(fifo); } @@ -58,14 +61,14 @@ int is_jitconv_requested(void) static long nr_drops = 0; /* modulus to output only a few warnings to avoid flooding oprofiled.log */ static int mod_cnt_drops = 1; - FILE * fd; char line[256]; int i, ret = 0; /* get a file descriptor to the pipe */ - fd = fdopen(fifo, "r"); + if (!fifo_fd) + fifo_fd = fdopen(fifo, "r"); - if (fd == NULL) { + if (fifo_fd == NULL) { perror("oprofiled: couldn't create file descriptor: "); exit(EXIT_FAILURE); } @@ -73,7 +76,7 @@ int is_jitconv_requested(void) /* read up to 99 lines to check for 'do_jitconv' */ for (i = 0; i < 99; i++) { /* just break if no new line is found */ - if (fgets(line, 256, fd) == NULL) + if (fgets(line, 256, fifo_fd) == NULL) break; line[strlen(line) - 1] = '\0'; diff --git a/libop/op_cpu_type.c b/libop/op_cpu_type.c index e168b43..4633fd1 100644 --- a/libop/op_cpu_type.c +++ b/libop/op_cpu_type.c @@ -51,7 +51,7 @@ static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = { { "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 34K", "mips/34K", CPU_MIPS_34K, 2}, { "MIPS 5K", "mips/5K", CPU_MIPS_5K, 2}, { "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 }, { "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 }, @@ -70,18 +70,23 @@ static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = { { "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 11MPCore", "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 }, - { "ARM V7 PMNC", "arm/armv7", CPU_ARM_V7, 5 }, + { "ARM Cortex-A8", "arm/armv7", CPU_ARM_V7, 5 }, { "Intel Architectural Perfmon", "i386/arch_perfmon", CPU_ARCH_PERFMON, 0}, { "AMD64 family11h", "x86-64/family11h", CPU_FAMILY11H, 4 }, { "ppc64 POWER7", "ppc64/power7", CPU_PPC64_POWER7, 6 }, { "ppc64 compat version 1", "ppc64/ibm-compat-v1", CPU_PPC64_IBM_COMPAT_V1, 4 }, { "Intel Core/i7", "i386/core_i7", CPU_CORE_I7, 4 }, { "Intel Atom", "i386/atom", CPU_ATOM, 2 }, + { "Loongson2", "mips/loongson2", CPU_MIPS_LOONGSON2, 2 }, + { "Intel Nehalem microarchitecture", "i386/nehalem", CPU_NEHALEM, 4 }, + { "ARM Cortex-A9", "arm/armv7-ca9", CPU_ARM_V7_CA9, 7 }, + { "MIPS 74K", "mips/74K", CPU_MIPS_74K, 4}, + { "MIPS 1004K", "mips/1004K", CPU_MIPS_1004K, 2}, }; static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr); diff --git a/libop/op_cpu_type.h b/libop/op_cpu_type.h index 133a4f8..990e213 100644 --- a/libop/op_cpu_type.h +++ b/libop/op_cpu_type.h @@ -72,13 +72,18 @@ typedef enum { CPU_PPC64_POWER5pp, /**< ppc64 Power5++ family */ CPU_PPC_E300, /**< e300 */ CPU_AVR32, /**< AVR32 */ - CPU_ARM_V7, /**< ARM V7 */ + CPU_ARM_V7, /**< ARM Cortex-A8 */ CPU_ARCH_PERFMON, /**< Intel architectural perfmon */ CPU_FAMILY11H, /**< AMD family 11h */ CPU_PPC64_POWER7, /**< ppc64 POWER7 family */ CPU_PPC64_IBM_COMPAT_V1, /**< IBM PPC64 processor compat mode version 1 */ CPU_CORE_I7, /* Intel Core i7, Nehalem */ CPU_ATOM, /* First generation Intel Atom */ + CPU_MIPS_LOONGSON2, /* < loongson2 family */ + CPU_NEHALEM, /* Intel Nehalem microarchitecture */ + CPU_ARM_V7_CA9, /**< ARM Cortex-A9 */ + CPU_MIPS_74K, /**< MIPS 74K */ + CPU_MIPS_1004K, /**< MIPS 1004K */ MAX_CPU_TYPE } op_cpu; diff --git a/libop/op_events.c b/libop/op_events.c index ad95d86..c3fcf57 100644 --- a/libop/op_events.c +++ b/libop/op_events.c @@ -970,6 +970,8 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) case CPU_FAMILY11H: case CPU_ATOM: case CPU_CORE_I7: + case CPU_NEHALEM: + case CPU_MIPS_LOONGSON2: descr->name = "CPU_CLK_UNHALTED"; break; @@ -1005,6 +1007,7 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) case CPU_ARM_MPCORE: case CPU_ARM_V6: case CPU_ARM_V7: + case CPU_ARM_V7_CA9: case CPU_AVR32: descr->name = "CPU_CYCLES"; break; @@ -1029,10 +1032,9 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) break; case CPU_MIPS_24K: - descr->name = "INSTRUCTIONS"; - break; - case CPU_MIPS_34K: + case CPU_MIPS_74K: + case CPU_MIPS_1004K: descr->name = "INSTRUCTIONS"; break; diff --git a/libop/op_hw_specific.h b/libop/op_hw_specific.h index b1e3b4c..35080ad 100644 --- a/libop/op_hw_specific.h +++ b/libop/op_hw_specific.h @@ -20,8 +20,7 @@ static inline int cpuid_vendor(char *vnd) char v[12]; } v; unsigned eax; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (eax), "=S" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0)); + asm("cpuid" : "=a" (eax), "=b" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0)); return !strncmp(v.v, vnd, 12); } @@ -47,8 +46,7 @@ static inline void workaround_nehalem_aaj79(unsigned *ebx) if (!cpuid_vendor("GenuineIntel")) return; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (v.eax) : "0" (1) : "ecx","edx"); + asm("cpuid" : "=a" (v.eax) : "0" (1) : "ecx","ebx","edx"); model = (v.ext_model << 4) + v.model; if (v.family != 6 || model != 26 || v.stepping > 4) return; @@ -59,8 +57,7 @@ static inline unsigned arch_get_filter(op_cpu cpu_type) { if (cpu_type == CPU_ARCH_PERFMON) { unsigned ebx, eax; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (eax), "=S" (ebx) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (eax), "=b" (ebx) : "0" (0xa) : "ecx","edx"); workaround_nehalem_aaj79(&ebx); return ebx & num_to_mask(eax >> 24); } @@ -71,8 +68,7 @@ static inline int arch_num_counters(op_cpu cpu_type) { if (cpu_type == CPU_ARCH_PERFMON) { unsigned v; - asm volatile( "pushl %%ebx; cpuid; movl %%eax, %1; popl %%ebx" - : "=a" (v) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx"); return (v >> 8) & 0xff; } return -1; @@ -81,8 +77,7 @@ static inline int arch_num_counters(op_cpu cpu_type) static inline unsigned arch_get_counter_mask(void) { unsigned v; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (v) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx"); return num_to_mask((v >> 8) & 0xff); } diff --git a/libop/op_xml_events.c b/libop/op_xml_events.c index 5b9ac7d..67fc0a5 100644 --- a/libop/op_xml_events.c +++ b/libop/op_xml_events.c @@ -16,38 +16,38 @@ #include "op_xml_out.h" static op_cpu cpu_type; -#define MAX_BUFFER 4096 +#define MAX_BUFFER 16384 +static char buffer[MAX_BUFFER]; + void open_xml_events(char const * title, char const * doc, op_cpu the_cpu_type) { char const * schema_version = "1.0"; - char buffer[MAX_BUFFER]; buffer[0] = '\0'; cpu_type = the_cpu_type; - open_xml_element(HELP_EVENTS, 0, buffer); - open_xml_element(HELP_HEADER, 1, buffer); - init_xml_str_attr(HELP_TITLE, title, buffer); - init_xml_str_attr(SCHEMA_VERSION, schema_version, buffer); - init_xml_str_attr(HELP_DOC, doc, buffer); - close_xml_element(NONE, 0, buffer); + open_xml_element(HELP_EVENTS, 0, buffer, MAX_BUFFER); + open_xml_element(HELP_HEADER, 1, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_TITLE, title, buffer, MAX_BUFFER); + init_xml_str_attr(SCHEMA_VERSION, schema_version, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_DOC, doc, buffer, MAX_BUFFER); + close_xml_element(NONE, 0, buffer, MAX_BUFFER); printf("%s", buffer); } void close_xml_events(void) { - char buffer[MAX_BUFFER]; - buffer[0] = '\0'; - close_xml_element(HELP_EVENTS, 0, buffer); + close_xml_element(HELP_EVENTS, 0, buffer, MAX_BUFFER); printf("%s", buffer); } -static void xml_do_arch_specific_event_help(struct op_event const * event, - char * buffer) +static void xml_do_arch_specific_event_help(struct op_event const *event, + char *buffer, size_t size) { switch (cpu_type) { case CPU_PPC64_CELL: - init_xml_int_attr(HELP_EVENT_GROUP, event->val / 100, buffer); + init_xml_int_attr(HELP_EVENT_GROUP, event->val / 100, buffer, + size); break; default: break; @@ -60,34 +60,41 @@ void xml_help_for_event(struct op_event const * event) uint i; int nr_counters; int has_nested = strcmp(event->unit->name, "zero"); - char buffer[MAX_BUFFER]; buffer[0] = '\0'; - open_xml_element(HELP_EVENT, 1, buffer); - init_xml_str_attr(HELP_EVENT_NAME, event->name, buffer); - xml_do_arch_specific_event_help(event, buffer); - init_xml_str_attr(HELP_EVENT_DESC, event->desc, buffer); + open_xml_element(HELP_EVENT, 1, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_EVENT_NAME, event->name, buffer, MAX_BUFFER); + xml_do_arch_specific_event_help(event, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_EVENT_DESC, event->desc, buffer, MAX_BUFFER); nr_counters = op_get_nr_counters(cpu_type); - init_xml_int_attr(HELP_COUNTER_MASK, event->counter_mask, buffer); - init_xml_int_attr(HELP_MIN_COUNT, event->min_count, buffer); + init_xml_int_attr(HELP_COUNTER_MASK, event->counter_mask, buffer, + MAX_BUFFER); + if (event->ext) + init_xml_str_attr(HELP_EXT, event->ext, buffer, MAX_BUFFER); + init_xml_int_attr(HELP_MIN_COUNT, event->min_count, + buffer, MAX_BUFFER); if (has_nested) { - close_xml_element(NONE, 1, buffer); - open_xml_element(HELP_UNIT_MASKS, 1, buffer); - init_xml_int_attr(HELP_DEFAULT_MASK, event->unit->default_mask, buffer); - close_xml_element(NONE, 1, buffer); + close_xml_element(NONE, 1, buffer, MAX_BUFFER); + open_xml_element(HELP_UNIT_MASKS, 1, buffer, MAX_BUFFER); + init_xml_int_attr(HELP_DEFAULT_MASK, event->unit->default_mask, + buffer, MAX_BUFFER); + close_xml_element(NONE, 1, buffer, MAX_BUFFER); for (i = 0; i < event->unit->num; i++) { - open_xml_element(HELP_UNIT_MASK, 1, buffer); + open_xml_element(HELP_UNIT_MASK, 1, buffer, MAX_BUFFER); init_xml_int_attr(HELP_UNIT_MASK_VALUE, - event->unit->um[i].value, buffer); + event->unit->um[i].value, + buffer, MAX_BUFFER); init_xml_str_attr(HELP_UNIT_MASK_DESC, - event->unit->um[i].desc, buffer); - close_xml_element(NONE, 0, buffer); + event->unit->um[i].desc, + buffer, MAX_BUFFER); + close_xml_element(NONE, 0, buffer, MAX_BUFFER); } - close_xml_element(HELP_UNIT_MASKS, 0, buffer); + close_xml_element(HELP_UNIT_MASKS, 0, buffer, MAX_BUFFER); } - close_xml_element(has_nested ? HELP_EVENT : NONE, has_nested, buffer); + close_xml_element(has_nested ? HELP_EVENT : NONE, has_nested, + buffer, MAX_BUFFER); printf("%s", buffer); } diff --git a/libop/op_xml_out.c b/libop/op_xml_out.c index d779c45..b12919e 100644 --- a/libop/op_xml_out.c +++ b/libop/op_xml_out.c @@ -77,6 +77,7 @@ char const * xml_tag_map[] = { "desc", "counter_mask", "min_count", + "ext", "unit_masks", "default", "unit_mask", @@ -91,143 +92,176 @@ char const * xml_tag_name(tag_t tag) } -void open_xml_element(tag_t tag, int with_attrs, char * buffer) +void open_xml_element(tag_t tag, int with_attrs, char *buffer, size_t max) { - char const * tag_name = xml_tag_name(tag); - unsigned int const max_len = strlen(tag_name) + 3; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr,"Warning: open_xml_element: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (snprintf(tmp_buf, sizeof(tmp_buf), "<%s%s", tag_name, - (with_attrs ? " " : ">\n")) < 0) { + ret = snprintf(buf, size, "<%s%s", xml_tag_name(tag), + (with_attrs ? " " : ">\n")); + + if (ret < 0 || ret >= size) { fprintf(stderr,"open_xml_element: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void close_xml_element(tag_t tag, int has_nested, char * buffer) +void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t max) { - char const * tag_name = xml_tag_name(tag); - unsigned int const max_len = strlen(tag_name) + 3; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr,"Warning: close_xml_element: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (tag == NONE) { - if (snprintf(tmp_buf, sizeof(tmp_buf), "%s\n", (has_nested ? ">" : "/>")) < 0) { - fprintf(stderr, "close_xml_element: snprintf failed\n"); - exit(EXIT_FAILURE); - } - } else { - if (snprintf(tmp_buf, sizeof(tmp_buf), "</%s>\n", tag_name) < 0) { - fprintf(stderr, "close_xml_element: snprintf failed\n"); - exit(EXIT_FAILURE); - } + if (tag == NONE) + ret = snprintf(buf, size, "%s\n", (has_nested ? ">" : "/>")); + else + ret = snprintf(buf, size, "</%s>\n", xml_tag_name(tag)); + + if (ret < 0 || ret >= size) { + fprintf(stderr, "close_xml_element: snprintf failed\n"); + exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void init_xml_int_attr(tag_t attr, int value, char * buffer) +void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t max) { - char const * attr_name = xml_tag_name(attr); - char tmp_buf[MAX_BUF_LEN]; - unsigned int const max_len = strlen(attr_name) + 50; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) { - fprintf(stderr, - "Warning: init_xml_int_attr: buffer overflow %d\n", max_len); - } + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; + ret = snprintf(buf, size, " %s=\"%d\"", xml_tag_name(attr), value); - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%d\"", attr_name, value) < 0) { + if (ret < 0 || ret >= size) { fprintf(stderr,"init_xml_int_attr: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void init_xml_dbl_attr(tag_t attr, double value, char * buffer) +void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t max) { - char const * attr_name = xml_tag_name(attr); - unsigned int const max_len = strlen(attr_name) + 50; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; + + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr, "Warning: init_xml_dbl_attr: buffer overflow %d\n", max_len); + ret = snprintf(buf, size, " %s=\"%.2f\"", xml_tag_name(attr), value); - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%.2f\"", attr_name, value) < 0) { + if (ret < 0 || ret >= size) { fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -static char * xml_quote(char const * str, char * quote_buf) +static void xml_quote(char const *str, char *buffer, size_t max) { - int i; - int pos = 0; - int len = strlen(str); + char *buf; + char *quote; + char *pos = (char*)str; + size_t size; + int ret; - - quote_buf[pos++] = '"'; + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - for (i = 0; i < len; i++) { - if (pos >= MAX_BUF_LEN - 10) { - fprintf(stderr,"quote_str: buffer overflow %d\n", pos); - exit(EXIT_FAILURE); - } + if (size < strlen(pos) + 2) + goto Error; - switch(str[i]) { + *buf = '"'; + buf++; + size--; + + while (*pos) { + switch(*pos) { case '&': - strncpy(quote_buf + pos, "&", 5); - pos += 5; + quote = "&"; break; case '<': - strncpy(quote_buf + pos, "<", 4); - pos += 4; + quote = "<"; break; case '>': - strncpy(quote_buf + pos, ">", 4); - pos += 4; + quote = ">"; break; case '"': - strncpy(quote_buf + pos, """, 6); - pos += 6; + quote = """; break; default: - quote_buf[pos++] = str[i]; - break; + *buf = *pos; + pos++; + buf++; + size--; + continue; } + + pos++; + ret = snprintf(buf, size, "%s", quote); + if (ret < 0 || ret >= (int)size) + goto Error; + buf += ret; + size -= ret; + if (size < strlen(pos)) + goto Error; } - quote_buf[pos++] = '"'; - quote_buf[pos++] = '\0'; - return quote_buf; + if (!size) + goto Error; + + *buf = '"'; + buf++; + *buf = '\0'; + + return; + +Error: + fprintf(stderr,"quote_str: buffer overflow\n"); + exit(EXIT_FAILURE); } -void init_xml_str_attr(tag_t attr, char const * str, char * buffer) +void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t max) { - char tmp_buf[MAX_BUF_LEN]; - char quote_buf[MAX_BUF_LEN]; - char const * attr_name = xml_tag_name(attr); - char const * quote_str = xml_quote(str, quote_buf); - const unsigned int max_len = strlen(attr_name) + strlen(quote_str) + 10; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr, "Warning: init_xml_str_attr: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=""%s""", attr_name, quote_str) < 0) { - fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); - exit(EXIT_FAILURE); - } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); + ret = snprintf(buf, size, " %s=", xml_tag_name(attr)); + if (ret < 0 || ret >= size) + goto Error; + + buf += ret; + size -= ret; + + if (!size) + goto Error; + + xml_quote(str, buf, size); + return; +Error: + fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); + exit(EXIT_FAILURE); } diff --git a/libop/op_xml_out.h b/libop/op_xml_out.h index 52e8d8f..b0188b2 100644 --- a/libop/op_xml_out.h +++ b/libop/op_xml_out.h @@ -51,6 +51,7 @@ typedef enum { HELP_EVENT_DESC, HELP_COUNTER_MASK, HELP_MIN_COUNT, + HELP_EXT, HELP_UNIT_MASKS, HELP_DEFAULT_MASK, HELP_UNIT_MASK, @@ -59,11 +60,11 @@ typedef enum { } tag_t; char const * xml_tag_name(tag_t tag); -void open_xml_element(tag_t tag, int with_attrs, char * result); -void close_xml_element(tag_t tag, int has_nested, char * result); -void init_xml_int_attr(tag_t attr, int value, char * result); -void init_xml_dbl_attr(tag_t attr, double value, char * result); -void init_xml_str_attr(tag_t attr, char const * str, char * result); +void open_xml_element(tag_t tag, int with_attrs, char *buffer, size_t size); +void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t size); +void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t size); +void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t size); +void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t size); #ifdef __cplusplus } diff --git a/libutil/fscanf.c b/libutil/fscanf.c deleted file mode 100644 index d567324..0000000 --- a/libutil/fscanf.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <stdio.h> - -// ugly hack because we don't have fscanf - -int fscanf(FILE* stream, const char* format, int* value) -{ - int c; - int r = 0; - do { - c = fgetc(stream); - if (c>='0' && c<='9') { - r = r*10 + (c-'0'); - continue; - } - break; - } while (1); - - *value = r; - - // gahhhh - return 1; -} diff --git a/libutil/op_cpufreq.c b/libutil/op_cpufreq.c index 78a6333..c95cb58 100644 --- a/libutil/op_cpufreq.c +++ b/libutil/op_cpufreq.c @@ -51,6 +51,11 @@ double op_cpu_frequency(void) fval = uval / 1E6; break; } + /* mips including loongson2 */ + if (sscanf(line, "BogoMIPS : %lu", &uval) == 1) { + fval = uval * 3 / 2; + break; + } /* s390 doesn't provide cpu freq, checked up to 2.6-test4 */ free(line); |