summaryrefslogtreecommitdiffstats
path: root/src/error.c
diff options
context:
space:
mode:
authorjolsa@redhat.com <jolsa@redhat.com>2011-11-01 16:37:03 +0100
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2011-11-24 21:20:27 +0100
commitaf5dafdd61af5a29043a1d8ae79427caa2136c7d (patch)
tree22aeb251dabca557d18e7d08dcfce98eeeba4835 /src/error.c
parent8967d2b09abc5f3e2bace9f6f14e1cfef8e47030 (diff)
downloadlatrace-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.c289
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);