diff options
author | jolsa@redhat.com <jolsa@redhat.com> | 2011-11-01 16:37:03 +0100 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2011-11-24 21:20:27 +0100 |
commit | af5dafdd61af5a29043a1d8ae79427caa2136c7d (patch) | |
tree | 22aeb251dabca557d18e7d08dcfce98eeeba4835 /src/error.c | |
parent | 8967d2b09abc5f3e2bace9f6f14e1cfef8e47030 (diff) | |
download | latrace-af5dafdd61af5a29043a1d8ae79427caa2136c7d.tar.gz latrace-af5dafdd61af5a29043a1d8ae79427caa2136c7d.tar.xz latrace-af5dafdd61af5a29043a1d8ae79427caa2136c7d.zip |
error simulation: automated changes
Diffstat (limited to 'src/error.c')
-rw-r--r-- | src/error.c | 289 |
1 files changed, 261 insertions, 28 deletions
diff --git a/src/error.c b/src/error.c index 6698ff8..ec457be 100644 --- a/src/error.c +++ b/src/error.c @@ -390,23 +390,22 @@ static int process_run(struct lt_config_app *cfg, return 0; } -static int process_automated_cb(struct lt_config_app *cfg, - struct lt_thread *t, - struct lt_fifo_mbase *mbase) -{ - 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; + int count = 0, runs = 1; lt_list_for_each_entry(run, &go->head_run, list_go) { struct lt_error_app_return *ret; + if (!runs--) { + PRINT_VERBOSE(cfg, 1, + "failed: supporting only single RUN within AUTOMATED go\n"); + return -1; + } + lt_list_for_each_entry(ret, &run->head_return, list_run) { struct lt_error_app_return_sym *sym; @@ -417,38 +416,270 @@ static int automated_get_all_syms(struct lt_config_app *cfg, } } + PRINT_VERBOSE(cfg, 1, "got %d symbols\n", count); return count; } -static int process_go_automated(struct lt_config_app *cfg, char *dir, - struct lt_error_app *app, - struct lt_error_app_go *go) +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 process_run_automated_cb(struct lt_config_app *cfg, + struct lt_thread *t, + struct lt_fifo_mbase *mbase) +{ + struct lt_error_app_return_sym *sym; + struct lt_error_config *error_config; + char *symname; + long index; + + if (mbase->type != LT_FIFO_MTYPE_EXIT) + return 0; + + index = automated_get_index(cfg, mbase); + error_config = cfg->error_config; + + if (cfg->error_automated_symbol_index < error_config->sym_cnt) { + if (index != -1) + BUG_ON((cfg->error_automated_symbol_index + 1) != index); + cfg->error_automated_symbol_index = index; + return 0; + } + + symname = automated_get_symname(cfg, mbase); + sym = automated_find_symbol_all(cfg, symname); + if (!sym) + return 0; + + if (automated_add_symbol_current(cfg, sym)) + return -1; + + return 0; +} + +static int prepare_config_symbols_automated(struct lt_config_app *cfg) +{ + struct lt_list_head *sym_current = &cfg->error_symbols_current; + + 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_automated_finished = 1; + return 0; + } + + return 0; +} + +static int prepare_config_error_automated(struct lt_config_app *cfg, + struct lt_error_app_run *run) { - int ret = 0; + 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++; + + BUG_ON(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)); + if (!cfg_err) + return -ENOMEM; + + cfg_err->sym_cnt = sym_cnt; + cfg_err->automated = 1; + + sym_cnt = 0; + + lt_list_for_each_entry(sym, sym_current, list) { + struct lt_error_config_sym *cfg_sym; + + cfg_sym = &cfg_err->sym[sym_cnt++]; + strncpy(cfg_sym->symbol, sym->name, LT_MAXNAME); + cfg_sym->ret = sym->vals[sym->val_idx]; + cfg_sym->keep = sym->keep; + cfg_sym->handle_sigsegv = sym->handle_sigsegv; - if (lt_process_register(cfg, process_automated_cb)) + PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n", + sym->name, cfg_sym->ret); + } + + cfg->error_config = cfg_err; + return 0; +} + +static int prepare_config_automated(struct lt_config_app *cfg, + char *dir, + struct lt_error_app *app, + struct lt_error_app_run *run, + int n) +{ + if (prepare_config_trace(cfg, dir)) + return -1; + + if (prepare_config_stat(cfg, dir)) return -1; - if (!automated_get_all_syms(cfg, go)) { - PRINT_VERBOSE(cfg, 1, "no symbols defined\n"); + if (prepare_config_tty(cfg, dir)) return -1; + + if (prepare_config_args(cfg, app, run)) + return -1; + + /* omit the first run */ + if (n && prepare_config_symbols_automated(cfg)) + return -1; + + if (prepare_config_error_automated(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) +{ + post_config(cfg, app); + automated_dump_config(cfg, app, dir); + free(cfg->error_config); +} + +static int process_run_automated(struct lt_config_app *cfg, + char *dir_base, + struct lt_error_app *app, + struct lt_error_app_run *run) +{ + static char dir[LT_MAXFILE]; + int n = 0; + + if (lt_process_register(cfg, process_run_automated_cb)) + return -1; + + while(1) { + if (dir_run(cfg, dir, dir_base, run, n)) + break; + + if (prepare_config_automated(cfg, dir, app, run, n)) + break; + + if (cfg->error_automated_finished) + break; + + lt_run(cfg); + + post_config_automated(cfg, app, dir); + + n++; } - /* 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 - * - */ + BUG_ON(lt_process_unregister(cfg, process_run_automated_cb)); + + return cfg->error_automated_finished ? 0 : -1; +} + +static int process_go_automated(struct lt_config_app *cfg, char *dir, + struct lt_error_app *app, + struct lt_error_app_go *go) +{ + struct lt_error_app_run *run; + + if (!automated_get_all_syms(cfg, go) <= 0) + return -1; + + run = lt_list_first_entry(&go->head_run, struct lt_error_app_run, list_go); - BUG_ON(lt_process_unregister(cfg, process_automated_cb)); + if (process_run_automated(cfg, dir, app, run)) + PRINT_VERBOSE(cfg, 1, "failed: AUTOMATED run %s\n", run->name); - return ret; + return 0; } static int process_go_replay(struct lt_config_app *cfg, char *dir, @@ -765,6 +996,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); |