From: Maynard J. <may...@us...> - 2009-04-30 00:54:29
|
Update of /cvsroot/oprofile/oprofile/libop In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10626/libop Modified Files: op_events.c Log Message: Add support for include and unit mask merging statements in event files Index: op_events.c =================================================================== RCS file: /cvsroot/oprofile/oprofile/libop/op_events.c,v retrieving revision 1.93 retrieving revision 1.94 diff -u -p -d -r1.93 -r1.94 --- op_events.c 30 Apr 2009 00:50:51 -0000 1.93 +++ op_events.c 30 Apr 2009 00:54:25 -0000 1.94 @@ -29,6 +29,22 @@ static char const * filename; static unsigned int line_nr; static void delete_event(struct op_event * event); +static void read_events(char const * file); +static void read_unit_masks(char const * file); +static void free_unit_mask(struct op_unit_mask * um); + +static char *build_fn(const char *cpu_name, const char *fn) +{ + char *s; + static const char *dir; + if (dir == NULL) + dir = getenv("OPROFILE_EVENTS_DIR"); + if (dir == NULL) + dir = OP_DATADIR; + s = xmalloc(strlen(dir) + strlen(cpu_name) + strlen(fn) + 5); + sprintf(s, "%s/%s/%s", dir, cpu_name, fn); + return s; +} static void parse_error(char const * context) { @@ -72,6 +88,23 @@ static u64 parse_long_hex(char const * s return value; } +static void include_um(const char *start, const char *end) +{ + char *s; + char cpu[end - start + 1]; + int old_line_nr; + const char *old_filename; + + strncpy(cpu, start, end - start); + cpu[end - start] = 0; + s = build_fn(cpu, "unit_masks"); + old_line_nr = line_nr; + old_filename = filename; + read_unit_masks(s); + line_nr = old_line_nr; + filename = old_filename; + free(s); +} /* name:MESI type:bitmask default:0x0f */ static void parse_um(struct op_unit_mask * um, char const * line) @@ -97,6 +130,14 @@ static void parse_um(struct op_unit_mask ++tagend; + if (strisprefix(start, "include")) { + if (seen_name + seen_type + seen_default > 0) + parse_error("include must be on its own"); + free_unit_mask(um); + include_um(tagend, valueend); + return; + } + if (strisprefix(start, "name")) { if (seen_name) parse_error("duplicate name: tag"); @@ -128,6 +169,11 @@ static void parse_um(struct op_unit_mask tagend = valueend; start = valueend; } + + if (!um->name) + parse_error("Missing name for unit mask"); + if (!seen_type) + parse_error("Missing type for unit mask"); } @@ -161,6 +207,11 @@ static struct op_unit_mask * new_unit_ma return um; } +static void free_unit_mask(struct op_unit_mask * um) +{ + list_del(&um->um_next); + free(um); +} /* * name:zero type:mandatory default:0x0 @@ -230,21 +281,68 @@ static u32 parse_counter_mask(char const return mask; } - -static struct op_unit_mask * find_um(char const * value) +static struct op_unit_mask * try_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) + if (strcmp(value, um->name) == 0) { + um->used = 1; return um; + } } + return NULL; +} +static struct op_unit_mask * find_um(char const * value) +{ + struct op_unit_mask * um = try_find_um(value); + if (um) + return um; fprintf(stderr, "oprofile: could not find unit mask %s\n", value); exit(EXIT_FAILURE); } +/* um:a,b,c,d merge multiple unit masks */ +static struct op_unit_mask * merge_um(char * value) +{ + int num; + char *s; + struct op_unit_mask *new, *um; + enum unit_mask_type type = -1U; + + um = try_find_um(value); + if (um) + return um; + + new = new_unit_mask(); + new->name = xstrdup(value); + new->used = 1; + num = 0; + while ((s = strsep(&value, ",")) != NULL) { + unsigned c; + um = find_um(s); + if (type == -1U) + type = um->unit_type_mask; + if (um->unit_type_mask != type) + parse_error("combined unit mask must be all the same types"); + if (type != utm_bitmask && type != utm_exclusive) + parse_error("combined unit mask must be all bitmasks or exclusive"); + new->default_mask |= um->default_mask; + new->num += um->num; + if (new->num > MAX_UNIT_MASK) + parse_error("too many members in combined unit mask"); + for (c = 0; c < um->num; c++, num++) { + new->um[num] = um->um[c]; + new->um[num].desc = xstrdup(new->um[num].desc); + } + } + if (type == -1U) + parse_error("Empty unit mask"); + new->unit_type_mask = type; + return new; +} /* parse either a "tag:value" or a ": trailing description string" */ static int next_token(char const ** cp, char ** name, char ** value) @@ -290,6 +388,20 @@ static int next_token(char const ** cp, return 1; } +static void include_events (char *value) +{ + char * event_file; + const char *old_filename; + int old_line_nr; + + event_file = build_fn(value, "events"); + old_line_nr = line_nr; + old_filename = filename; + read_events(event_file); + line_nr = old_line_nr; + filename = old_filename; + free(event_file); +} static struct op_event * new_event(void) { @@ -300,6 +412,11 @@ static struct op_event * new_event(void) return event; } +static void free_event(struct op_event * event) +{ + list_del(&event->event_next); + free(event); +} /* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */ /* event:0x00 ext:xxxxxx um:zero minimum:4096 name:ISSUES : Total issues */ @@ -312,6 +429,7 @@ static void read_events(char const * fil char const * c; int seen_event, seen_counters, seen_um, seen_minimum, seen_name, seen_ext; FILE * fp = fopen(file, "r"); + int tags; if (!fp) { fprintf(stderr, "oprofile: could not open event description file %s\n", file); @@ -327,6 +445,7 @@ static void read_events(char const * fil if (empty_line(line) || comment_line(line)) goto next; + tags = 0; seen_name = 0; seen_event = 0; seen_counters = 0; @@ -372,8 +491,10 @@ static void read_events(char const * fil if (seen_um) parse_error("duplicate um: tag"); seen_um = 1; - event->unit = find_um(value); - event->unit->used = 1; + if (strchr(value, ',')) + event->unit = merge_um(value); + else + event->unit = find_um(value); free(value); } else if (strcmp(name, "minimum") == 0) { if (seen_minimum) @@ -383,12 +504,22 @@ static void read_events(char const * fil free(value); } else if (strcmp(name, "desc") == 0) { event->desc = value; - } else if (strcmp(name, "filter") == 0) { + } else if (strcmp(name, "filter") == 0) { event->filter = parse_int(value); free(value); + } else if (strcmp(name, "include") == 0) { + if (tags > 0) + parse_error("tags before include:"); + free_event(event); + include_events(value); + free(value); + c = skip_ws(c); + if (*c != '\0' && *c != '#') + parse_error("non whitespace after include:"); } else { parse_error("unknown tag"); } + tags++; free(name); } @@ -449,61 +580,46 @@ static void arch_filter_events(op_cpu cp unsigned filter = arch_get_filter(cpu_type); if (!filter) return; - list_for_each_safe (pos, pos2, &events_list) { + list_for_each_safe (pos, pos2, &events_list) { struct op_event * event = list_entry(pos, struct op_event, event_next); if (event->filter >= 0 && ((1U << event->filter) & filter)) delete_event(event); } } -static void load_events(op_cpu cpu_type) +static void load_events_name(const char *cpu_name) { - char const * cpu_name = op_get_cpu_name(cpu_type); - char * event_dir; char * event_file; char * um_file; - char * dir; - int err = 0; - 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, "/"); + event_file = build_fn(cpu_name, "events"); + um_file = build_fn(cpu_name, "unit_masks"); - strcat(event_dir, cpu_name); - strcat(event_dir, "/"); + read_unit_masks(um_file); + read_events(event_file); + + free(um_file); + free(event_file); +} - event_file = xmalloc(strlen(event_dir) + strlen("events") + 1); - strcpy(event_file, event_dir); - strcat(event_file, "events"); +static void load_events(op_cpu cpu_type) +{ + const char * cpu_name = op_get_cpu_name(cpu_type); + struct list_head * pos; + int err = 0; - um_file = xmalloc(strlen(event_dir) + strlen("unit_masks") + 1); - strcpy(um_file, event_dir); - strcat(um_file, "unit_masks"); + if (!list_empty(&events_list)) + return; - read_unit_masks(um_file); - read_events(event_file); + load_events_name(cpu_name); arch_filter_events(cpu_type); /* 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); - err |= check_unit_mask(um, cpu_name); } - - free(um_file); - free(event_file); - free(event_dir); if (err) exit(err); } @@ -579,18 +695,18 @@ static struct op_event * find_event_um(u list_for_each(pos, &events_list) { struct op_event * event = list_entry(pos, struct op_event, event_next); - if (event->val == nr) { - for (i = 0; i < event->unit->num; i++) { + if (event->val == nr) { + for (i = 0; i < event->unit->num; i++) { if (event->unit->um[i].value == um) - return event; - } + return event; + } } } return NULL; } -static FILE * open_event_mapping_file(char const * cpu_name) +static FILE * open_event_mapping_file(char const * cpu_name) { char * ev_map_file; char * dir; @@ -614,7 +730,7 @@ static FILE * open_event_mapping_file(ch /** * This function is PPC64-specific. */ -static char const * get_mapping(u32 nr, FILE * fp) +static char const * get_mapping(u32 nr, FILE * fp) { char * line; char * name; |