From daafe68255b0fbae2d7c1d4c696538327037b067 Mon Sep 17 00:00:00 2001 From: "jolsa@redhat.com" Date: Tue, 1 Nov 2011 16:37:03 +0100 Subject: error simulation: automated changes --- src/error.c | 574 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 440 insertions(+), 134 deletions(-) (limited to 'src/error.c') diff --git a/src/error.c b/src/error.c index 6698ff8..48afa23 100644 --- a/src/error.c +++ b/src/error.c @@ -185,11 +185,28 @@ static int dir_go(struct lt_config_app *cfg, static int dir_run(struct lt_config_app *cfg, char *dir, char *dir_base, - struct lt_error_app_run *run, int n) + struct lt_error_app_run *run) { int size; - size = snprintf(dir, LT_MAXFILE, "%s/RUN-%s-%05d/", dir_base, run->name, n); + size = snprintf(dir, LT_MAXFILE, "%s/RUN-%s/", dir_base, run->name); + if (size == LT_MAXFILE) + return -1; + + if (dir_get(cfg, dir, 0)) + return -1; + + return 0; +} + +static int dir_round(struct lt_config_app *cfg, + char *dir, char *dir_run, + struct lt_error_app_run *run, + unsigned long round) +{ + int size; + + size = snprintf(dir, LT_MAXFILE, "%s/%lu/", dir_run, round); if (size == LT_MAXFILE) return -1; @@ -277,60 +294,314 @@ static int prepare_config_args(struct lt_config_app *cfg, return 0; } -static int prepare_config_error(struct lt_config_app *cfg, - struct lt_error_app_run *run, - int n) +static int get_symbols_all(struct lt_config_app *cfg, + struct lt_error_app_run *run) { + struct lt_list_head *sym_all = &cfg->error_symbols_all; struct lt_error_app_return *ret; - struct lt_error_config *cfg_err; - int sym_cnt = 0; + int count = 0; - /* get the nymber of configured symbols */ lt_list_for_each_entry(ret, &run->head_return, list_run) { - struct lt_error_app_return_sym *sym; - lt_list_for_each_entry(sym, &ret->head_sym, list) - sym_cnt++; + struct lt_error_app_return_sym *sym, *n; + + lt_list_for_each_entry_safe(sym, n, &ret->head_sym, list) { + lt_list_move_tail(&sym->list, sym_all); + count++; + } + } + + PRINT_VERBOSE(cfg, 1, "got %d symbols\n", count); + return count; +} + +long automated_get_index(struct lt_config_app *cfg, + struct lt_fifo_mbase *mbase) +{ + struct lt_fifo_msym *msym = (struct lt_fifo_msym*) mbase; + return msym->info; +} + +static char *automated_get_symname(struct lt_config_app *cfg, + struct lt_fifo_mbase *mbase) +{ + struct lt_fifo_msym *msym = (struct lt_fifo_msym*) mbase; + return msym->data + msym->sym; +} + +static struct lt_error_app_return_sym* +automated_find_symbol_all(struct lt_config_app *cfg, char *symname) +{ + struct lt_error_app_return_sym *sym; + struct lt_list_head *sym_all = &cfg->error_symbols_all; + + /* TODO hash, hash, hash... and hash again .. pleaeease ;) hash! */ + lt_list_for_each_entry(sym, sym_all, list) + if (!strcmp(sym->name, symname)) + return sym; + + return NULL; +} + +static int automated_add_symbol_current(struct lt_config_app *cfg, + struct lt_error_app_return_sym *sym_orig) +{ + struct lt_error_app_return_sym *sym; + + sym = malloc(sizeof(*sym)); + if (!sym) + return -1; + + *sym = *sym_orig; + + sym->keep = 1; + sym->val_idx = 0; + + lt_list_add_tail(&sym->list, &cfg->error_symbols_current); + return 0; +} + +static int +prepare_config_symbols_automated(struct lt_config_app *cfg, + struct lt_error_app_run *run, + unsigned long round) +{ + struct lt_list_head *sym_current = &cfg->error_symbols_current; + + cfg->error_automated_symbol_index = -1; + + if (!round) { + int cnt; + cnt = get_symbols_all(cfg, run); + if (cnt <= 0) + return -EINVAL; + + cfg->error_symbols_all_cnt = cnt; + return 0; + } + + while (!lt_list_empty(sym_current)) { + struct lt_error_app_return_sym *last; + + last = lt_list_last_entry(sym_current, + struct lt_error_app_return_sym, + list); + + PRINT_VERBOSE(cfg, 1, "last %s\n", last->name); + + if (last->keep) { + int idx = last->val_idx; + last->keep = 0; + + PRINT_VERBOSE(cfg, 1, "from keep to vals[%d] = %llu\n", + idx, last->vals[idx]); + break; + } else { + int idx = last->val_idx + 1; + + if (idx < last->val_cnt) { + last->val_idx = idx; + + PRINT_VERBOSE(cfg, 1, "from vals[%d] = %llu to vals[%d] = %llu\n", + idx - 1, last->vals[idx - 1], + idx, last->vals[idx]); + break; + } + + PRINT_VERBOSE(cfg, 1, "removing\n"); + lt_list_del(&last->list); + } + } + + /* nothing more to try, we are done */ + if (lt_list_empty(sym_current)) { + PRINT_VERBOSE(cfg, 1, "FINISHED\n"); + cfg->error_finished = 1; + return 0; + } + + return 0; +} + +static int +prepare_config_symbols_replay(struct lt_config_app *cfg) +{ + return 0; +} + +static int +prepare_config_symbols_seq(struct lt_config_app *cfg, + unsigned long round) +{ + return 0; +} + +static int prepare_config_symbols(struct lt_config_app *cfg, + struct lt_error_app_run *run, + unsigned long round) +{ + switch(run->type) { + case LT_ERROR_RUN_TYPE_SEQ: + return prepare_config_symbols_seq(cfg, round); + + case LT_ERROR_RUN_TYPE_AUTO: + return prepare_config_symbols_automated(cfg, run, round); + + case LT_ERROR_RUN_TYPE_REPLAY: + return prepare_config_symbols_replay(cfg); + } + + BUG(); + return -EINVAL; +} + +static int find_error_symbol(struct lt_config_app *cfg, char *name, + int len) +{ + char *names = cfg->error_symbols; + int size_names = cfg->error_symbols_size_names; + char *p; + + PRINT_VERBOSE(cfg, 1, "name %s\n", name); + + while(size_names) { + if (!strncmp(names, name, len)) { + int idx = names - cfg->error_symbols; + PRINT_VERBOSE(cfg, 1, "found idx %d\n", idx); + return names - cfg->error_symbols; + } + + p = memchr(names, 0, size_names); + size_names -= ++p - names; + names = p; + } + + PRINT_VERBOSE(cfg, 1, "not found\n"); + return -1; +} + +static void display_error_symbols(struct lt_config_app *cfg) +{ + char *names = cfg->error_symbols; + int size_names = cfg->error_symbols_size_names; + char *p; + + PRINT_VERBOSE(cfg, 1, "START\n"); + + while(size_names) { + PRINT_VERBOSE(cfg, 1, "name %s\n", names); + p = memchr(names, 0, size_names); + size_names -= ++p - names; + names = p; + } + + PRINT_VERBOSE(cfg, 1, "END\n"); +} + +static int add_error_symbol(struct lt_config_app *cfg, char *name) +{ + char *names = cfg->error_symbols; + int len = strlen(name); + int size_names = cfg->error_symbols_size_names; + int size_total = cfg->error_symbols_size_total; + int index; + + PRINT_VERBOSE(cfg, 1, "name %s\n", name); + display_error_symbols(cfg); + + if (!names) { + names = malloc(1000); + if (!names) + return -ENOMEM; + + PRINT_VERBOSE(cfg, 1, "initial allocation\n"); + cfg->error_symbols = names; + size_names = cfg->error_symbols_size_names = 0; + size_total = cfg->error_symbols_size_total = 1000; } + index = find_error_symbol(cfg, name, len); + if (index >= 0) + return index; + + /* +1 for ZERO byte */ + if (len + size_names + 1 >= size_total) { + size_total += 1000; + names = realloc(names, size_total); + if (!names) + return -ENOMEM; + + PRINT_VERBOSE(cfg, 1, "reallocation size %d\n", size_total); + cfg->error_symbols = names; + cfg->error_symbols_size_total = size_total; + } + + index = size_names; + + strncpy(names + size_names, name, len); + size_names += len; + names[size_names++] = 0; + + cfg->error_symbols_size_names = size_names; + + PRINT_VERBOSE(cfg, 1, "added %s, index %d\n", name, index); + display_error_symbols(cfg); + return index; +} + +static int prepare_config_error(struct lt_config_app *cfg, + struct lt_error_app_run *run) +{ + struct lt_list_head *sym_current = &cfg->error_symbols_current; + struct lt_error_app_return_sym *sym; + struct lt_error_config *cfg_err; + int sym_cnt = 0; + + lt_list_for_each_entry(sym, sym_current, list) + sym_cnt++; + PRINT_VERBOSE(cfg, 1, "number of symbols %d\n", sym_cnt); cfg_err = malloc(sizeof(*cfg_err) + - sym_cnt * sizeof(struct lt_error_config_sym)); + sym_cnt * sizeof(struct lt_error_sym)); if (!cfg_err) return -ENOMEM; + memset(cfg_err, 0, sizeof(*cfg_err)); cfg_err->sym_cnt = sym_cnt; - cfg_err->n = n; + cfg_err->type = run->type; sym_cnt = 0; - lt_list_for_each_entry(ret, &run->head_return, list_run) { - struct lt_error_app_return_sym *sym; + lt_list_for_each_entry(sym, sym_current, list) { + struct lt_error_sym *cfg_sym; + int index; - lt_list_for_each_entry(sym, &ret->head_sym, list) { - struct lt_error_config_sym *cfg_sym; + cfg_sym = &cfg_err->sym[sym_cnt++]; - cfg_sym = &cfg_err->sym[sym_cnt++]; - strncpy(cfg_sym->symbol, sym->name, LT_MAXNAME); - cfg_sym->ret = sym->val; - cfg_sym->filter.type = ret->filter.type; - cfg_sym->handle_sigsegv = sym->handle_sigsegv; + index = add_error_symbol(cfg, sym->name); + if (index < 0) + return -ENOMEM; - PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n", - sym->name, sym->val); - } + cfg_sym->name.index = index; + cfg_sym->ret = sym->vals[sym->val_idx]; + cfg_sym->keep = sym->keep; + cfg_sym->handle_sigsegv = sym->handle_sigsegv; + + PRINT_VERBOSE(cfg, 1, "symbol %s, keep %d, ret %llu\n", + sym->name, cfg_sym->keep, cfg_sym->ret); } + cfg_err->names_size = cfg->error_symbols_size_names; cfg->error_config = cfg_err; return 0; } -static int prepare_config(struct lt_config_app *cfg, char *dir, +static int prepare_config(struct lt_config_app *cfg, + char *dir, struct lt_error_app *app, - struct lt_error_app_run *run, int n) + struct lt_error_app_run *run, + unsigned long round) { - PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir); - if (!app->no_storage) { if (prepare_config_trace(cfg, dir)) return -1; @@ -345,137 +616,153 @@ static int prepare_config(struct lt_config_app *cfg, char *dir, if (prepare_config_args(cfg, app, run)) return -1; - if (prepare_config_error(cfg, run, n)) + if (prepare_config_symbols(cfg, run, round)) + return -1; + + if (prepare_config_error(cfg, run)) return -1; return 0; } +static void automated_dump_config(struct lt_config_app *cfg, + struct lt_error_app *app, + char *dir) +{ + /* dump config to be replayed with REPLAY */ +} + +static void post_config_automated(struct lt_config_app *cfg, + struct lt_error_app *app, + char *dir) +{ + automated_dump_config(cfg, app, dir); +} + static void post_config(struct lt_config_app *cfg, - struct lt_error_app *app) + struct lt_error_app *app, + struct lt_error_app_run *run, + char *dir) { + switch(run->type) { + case LT_ERROR_RUN_TYPE_AUTO: + return post_config_automated(cfg, app, dir); + } + if (!app->no_storage) { if ((lt_sh(cfg, pipe)) && (*lt_sh(cfg, output))) fclose(lt_sh(cfg, fout)); fclose(cfg->fstat); } + + free(cfg->error_config); + free(cfg->error_symbols); + + cfg->error_config = NULL; + cfg->error_symbols = NULL; + cfg->error_symbols_size_names = 0; + cfg->error_symbols_size_total = 0; } -static int process_run(struct lt_config_app *cfg, - char *dir_base, - struct lt_error_app *app, - struct lt_error_app_go *go, - struct lt_error_app_run *run, - int n) +static int process_run_automated_cb(struct lt_config_app *cfg, + struct lt_thread *t, + struct lt_fifo_mbase *mbase) { - static char dir[LT_MAXFILE]; + struct lt_error_app_return_sym *sym; + struct lt_error_config *error_config; + char *symname; + long index; - if (!app->no_storage && - dir_run(cfg, dir, dir_base, run, n)) - return -1; + PRINT_VERBOSE(cfg, 1, "type %d\n", mbase->type); - PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir); + if (mbase->type != LT_FIFO_MTYPE_EXIT) + return 0; - if (prepare_config(cfg, dir, app, run, n)) - return -1; + index = automated_get_index(cfg, mbase); + error_config = cfg->error_config; - if (app->no_storage) - printf("latrace error simulation [%s] n = %d\n", app->name, n); + PRINT_VERBOSE(cfg, 1, "index %d, error_automated_symbol_index %d, sym_cnt %d\n", + index, cfg->error_automated_symbol_index, error_config->sym_cnt); - lt_run(cfg); + symname = automated_get_symname(cfg, mbase); + PRINT_VERBOSE(cfg, 1, "symname %s\n", symname); - post_config(cfg, app); + if (cfg->error_automated_symbol_index < (error_config->sym_cnt - 1)) { + if (index != -1) + cfg->error_automated_symbol_index = index; - return 0; -} - -static int process_automated_cb(struct lt_config_app *cfg, - struct lt_thread *t, - struct lt_fifo_mbase *mbase) -{ - return 0; -} + return 0; + } -static int automated_get_all_syms(struct lt_config_app *cfg, - struct lt_error_app_go *go) -{ - struct lt_list_head *sym_all = &cfg->error_symbols_all; - struct lt_error_app_run *run; - int count = 0; + sym = automated_find_symbol_all(cfg, symname); + if (!sym) + return 0; - lt_list_for_each_entry(run, &go->head_run, list_go) { - struct lt_error_app_return *ret; + PRINT_VERBOSE(cfg, 1, "added %s\n", symname); - lt_list_for_each_entry(ret, &run->head_return, list_run) { - struct lt_error_app_return_sym *sym; + if (automated_add_symbol_current(cfg, sym)) + return -1; - lt_list_for_each_entry(sym, &ret->head_sym, list) { - lt_list_move_tail(&sym->list, sym_all); - count++; - } - } - } + return 0; +} - return count; +static int process_run_cb(struct lt_config_app *cfg, + struct lt_thread *t, + struct lt_fifo_mbase *mbase) +{ + /* TODO need a way to distiguish error type inside tracer */ + return process_run_automated_cb(cfg, t, mbase); } -static int process_go_automated(struct lt_config_app *cfg, char *dir, - struct lt_error_app *app, - struct lt_error_app_go *go) +static int process_run(struct lt_config_app *cfg, + char *dir_base, + struct lt_error_app *app, + struct lt_error_app_run *run) { - int ret = 0; + static char dir[LT_MAXFILE]; + static char round[LT_MAXFILE]; + unsigned long r = 0; - if (lt_process_register(cfg, process_automated_cb)) + if (!app->no_storage && + dir_run(cfg, dir, dir_base, run)) return -1; - if (!automated_get_all_syms(cfg, go)) { - PRINT_VERBOSE(cfg, 1, "no symbols defined\n"); + PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir); + + if (lt_process_register(cfg, process_run_cb)) return -1; - } - /* TODO - * 1) first run with no symbols - * 2) after each run add new symbol to the 'cur' list from global 'all' list - * 3) 'cur' list has fresh reallocated symbols giving the position and return - * for each symbol occurence - * 4) each 'cur' list symbol moves to new return value if all symbols 'below' it - * has changed all their return values - * 5) finish when first symbol cycles its all return values - * 6) repeating till there are new symbols (from 'all' list) visible - * - */ + while(1) { + int status; - BUG_ON(lt_process_unregister(cfg, process_automated_cb)); + if (!app->no_storage && + dir_round(cfg, round, dir, run, r)) + return -1; - return ret; -} + printf("."); -static int process_go_replay(struct lt_config_app *cfg, char *dir, - struct lt_error_app *app, - struct lt_error_app_go *go) -{ - return 0; -} + if (prepare_config(cfg, round, app, run, r)) + break; -static int process_go_configured(struct lt_config_app *cfg, char *dir, - struct lt_error_app *app, - struct lt_error_app_go *go) -{ - int i; + if (cfg->error_finished) + break; - PRINT_VERBOSE(cfg, 1, "dir '%s', name %s, start %d, n %d\n", - dir, go->name, go->start, go->n); + status = lt_run(cfg); + if (WIFSIGNALED(status)) + printf("\nround %lu killed by signal %d\n", + r, WTERMSIG(status)); + fflush(NULL); - for(i = go->start; i < (go->start + go->n); i++) { - struct lt_error_app_run *run; + post_config(cfg, app, run, round); - lt_list_for_each_entry(run, &go->head_run, list_go) - if (process_run(cfg, dir, app, go, run, i)) - return -1; - } + r++; + }; - return 0; + printf("\n"); + BUG_ON(lt_process_unregister(cfg, process_run_cb)); + + return cfg->error_finished ? 0 : -1; } static int process_go(struct lt_config_app *cfg, char *dir_base, @@ -483,21 +770,17 @@ static int process_go(struct lt_config_app *cfg, char *dir_base, struct lt_error_app_go *go) { static char dir[LT_MAXFILE]; + struct lt_error_app_run *run; if (!app->no_storage && dir_go(cfg, dir, dir_base, go)) return -1; - /* automated processing.. God save us */ - if (go->automated) - return process_go_automated(cfg, dir, app, go); - - /* exact symbols return replay */ - if (go->replay) - return process_go_replay(cfg, dir, app, go); + lt_list_for_each_entry(run, &go->head_run, list_go) + if (process_run(cfg, dir, app, run)) + return -1; - /* Whatever user configuration wants.. */ - return process_go_configured(cfg, dir, app, go); + return 0; } int lt_error_run(struct lt_config_app *cfg) @@ -608,6 +891,19 @@ int lt_error_run_return(struct lt_config_app *cfg, return 0; } +int lt_error_run_type(struct lt_config_app *cfg, + struct lt_error_app_run **run, + int type) +{ + struct lt_error_app_run *app_run = app_run_get(cfg, run); + + if (!app_run) + return -ENOMEM; + + app_run->type = type; + return 0; +}; + int lt_error_run_args(struct lt_config_app *cfg, struct lt_error_app_run **run, struct lt_list_head *head) @@ -657,9 +953,7 @@ static struct lt_error_app_run *find_run(struct lt_config_app *cfg, int lt_error_go(struct lt_config_app *cfg, struct lt_error_app_go **go, struct lt_error_app *error_app, - char *name, int start, int n, - int automated, int replay, - struct lt_list_head *runs) + char *name, struct lt_list_head *runs) { struct lt_error_app_go *app_go = *go; struct lt_config_ln *ln, *h; @@ -672,11 +966,7 @@ int lt_error_go(struct lt_config_app *cfg, lt_init_list_head(&app_go->head_run); lt_init_list_head(&app_go->list); - app_go->n = n; - app_go->start = start; app_go->name = name; - app_go->automated = automated; - app_go->replay = replay; lt_list_for_each_entry_safe(ln, h, runs, list) { struct lt_error_app_run *run; @@ -765,6 +1055,8 @@ int lt_error_return_ass(struct lt_config_app *cfg, free(ln); } + sym->val_cnt = vals_cnt; + PRINT_VERBOSE(cfg, 1, "%s = %ld, handle_sigsegv = %d, keep %d\n", sym->name, sym->val, handle_sigsegv, keep); @@ -812,16 +1104,30 @@ int lt_error_app_init(struct lt_error_app *app) int lt_error_config_write(struct lt_config_app *cfg, int fd) { struct lt_error_config *cfg_err = cfg->error_config; - int size = sizeof(struct lt_error_config); + int len, size = sizeof(struct lt_error_config); BUG_ON(!cfg_err); - size += cfg_err->sym_cnt * sizeof(struct lt_error_config_sym); + size += cfg_err->sym_cnt * sizeof(struct lt_error_sym); + + PRINT_VERBOSE(cfg, 1, "sym_cnt %d\n", cfg_err->sym_cnt); if (size != write(fd, cfg_err, size)) { perror("write failed"); return -1; } + PRINT_VERBOSE(cfg, 1, "writing names size %d\n", cfg->error_symbols_size_names); + display_error_symbols(cfg); + + len = cfg->error_symbols_size_names; + size = write(fd, cfg->error_symbols, len); + + if (size != len) { + perror("write failed"); + return -1; + } + + PRINT_VERBOSE(cfg, 1, "OK\n"); return 0; } -- cgit