Add interfaces to allow users of dwarf_loader to prepare and pass per-thread data to steal-functions running on worker threads. Signed-off-by: Kui-Feng Lee <kuifeng@xxxxxx> --- btf_loader.c | 2 +- ctf_loader.c | 2 +- dwarf_loader.c | 58 +++++++++++++++++++++++++++++++++++++++----------- dwarves.h | 9 ++++++-- pahole.c | 3 ++- pdwtags.c | 3 ++- pfunct.c | 4 +++- 7 files changed, 61 insertions(+), 20 deletions(-) diff --git a/btf_loader.c b/btf_loader.c index 7a5b16ff393e..b61cadd55127 100644 --- a/btf_loader.c +++ b/btf_loader.c @@ -624,7 +624,7 @@ static int cus__load_btf(struct cus *cus, struct conf_load *conf, const char *fi * The app stole this cu, possibly deleting it, * so forget about it */ - if (conf && conf->steal && conf->steal(cu, conf)) + if (conf && conf->steal && conf->steal(cu, conf, NULL)) return 0; cus__add(cus, cu); diff --git a/ctf_loader.c b/ctf_loader.c index 7c34739afdce..de6d4dbfce97 100644 --- a/ctf_loader.c +++ b/ctf_loader.c @@ -722,7 +722,7 @@ int ctf__load_file(struct cus *cus, struct conf_load *conf, * The app stole this cu, possibly deleting it, * so forget about it */ - if (conf && conf->steal && conf->steal(cu, conf)) + if (conf && conf->steal && conf->steal(cu, conf, NULL)) return 0; cus__add(cus, cu); diff --git a/dwarf_loader.c b/dwarf_loader.c index e30b03c1c541..ed415d2db11f 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -2682,18 +2682,18 @@ static int class_member__cache_byte_size(struct tag *tag, struct cu *cu, return 0; } -static int cu__finalize(struct cu *cu, struct conf_load *conf) +static int cu__finalize(struct cu *cu, struct conf_load *conf, void *thr_data) { cu__for_all_tags(cu, class_member__cache_byte_size, conf); if (conf && conf->steal) { - return conf->steal(cu, conf); + return conf->steal(cu, conf, thr_data); } return LSK__KEEPIT; } -static int cus__finalize(struct cus *cus, struct cu *cu, struct conf_load *conf) +static int cus__finalize(struct cus *cus, struct cu *cu, struct conf_load *conf, void *thr_data) { - int lsk = cu__finalize(cu, conf); + int lsk = cu__finalize(cu, conf, thr_data); switch (lsk) { case LSK__DELETE: cu__delete(cu); @@ -2862,7 +2862,13 @@ struct dwarf_cus { struct dwarf_cu *type_dcu; }; -static int dwarf_cus__create_and_process_cu(struct dwarf_cus *dcus, Dwarf_Die *cu_die, uint8_t pointer_size) +struct dwarf_thread { + struct dwarf_cus *dcus; + void *data; +}; + +static int dwarf_cus__create_and_process_cu(struct dwarf_cus *dcus, Dwarf_Die *cu_die, + uint8_t pointer_size, void *thr_data) { /* * DW_AT_name in DW_TAG_compile_unit can be NULL, first seen in: @@ -2884,7 +2890,7 @@ static int dwarf_cus__create_and_process_cu(struct dwarf_cus *dcus, Dwarf_Die *c cu->dfops = &dwarf__ops; if (die__process_and_recode(cu_die, cu, dcus->conf) != 0 || - cus__finalize(dcus->cus, cu, dcus->conf) == LSK__STOP_LOADING) + cus__finalize(dcus->cus, cu, dcus->conf, thr_data) == LSK__STOP_LOADING) return DWARF_CB_ABORT; return DWARF_CB_OK; @@ -2918,7 +2924,8 @@ out_unlock: static void *dwarf_cus__process_cu_thread(void *arg) { - struct dwarf_cus *dcus = arg; + struct dwarf_thread *dthr = arg; + struct dwarf_cus *dcus = dthr->dcus; uint8_t pointer_size, offset_size; Dwarf_Die die_mem, *cu_die; @@ -2926,11 +2933,13 @@ static void *dwarf_cus__process_cu_thread(void *arg) if (cu_die == NULL) break; - if (dwarf_cus__create_and_process_cu(dcus, cu_die, pointer_size) == DWARF_CB_ABORT) + if (dwarf_cus__create_and_process_cu(dcus, cu_die, + pointer_size, dthr->data) == DWARF_CB_ABORT) goto out_abort; } - if (dcus->conf->thread_exit && dcus->conf->thread_exit() != 0) + if (dcus->conf->thread_exit && + dcus->conf->thread_exit(dcus->conf, dthr->data) != 0) goto out_abort; return (void *)DWARF_CB_OK; @@ -2941,10 +2950,25 @@ out_abort: static int dwarf_cus__threaded_process_cus(struct dwarf_cus *dcus) { pthread_t threads[dcus->conf->nr_jobs]; + struct dwarf_thread dthr[dcus->conf->nr_jobs]; + void *thread_data[dcus->conf->nr_jobs]; + int res; int i; + if (dcus->conf->threads_prepare) { + res = dcus->conf->threads_prepare(dcus->conf, dcus->conf->nr_jobs, thread_data); + if (res != 0) + return res; + } else + memset(thread_data, 0, sizeof(void *) * dcus->conf->nr_jobs); + for (i = 0; i < dcus->conf->nr_jobs; ++i) { - dcus->error = pthread_create(&threads[i], NULL, dwarf_cus__process_cu_thread, dcus); + dthr[i].dcus = dcus; + dthr[i].data = thread_data[i]; + + dcus->error = pthread_create(&threads[i], NULL, + dwarf_cus__process_cu_thread, + &dthr[i]); if (dcus->error) goto out_join; } @@ -2960,6 +2984,13 @@ out_join: dcus->error = (long)res; } + if (dcus->conf->threads_collect) { + res = dcus->conf->threads_collect(dcus->conf, dcus->conf->nr_jobs, + thread_data, dcus->error); + if (dcus->error == 0) + dcus->error = res; + } + return dcus->error; } @@ -2976,7 +3007,8 @@ static int __dwarf_cus__process_cus(struct dwarf_cus *dcus) if (cu_die == NULL) break; - if (dwarf_cus__create_and_process_cu(dcus, cu_die, pointer_size) == DWARF_CB_ABORT) + if (dwarf_cus__create_and_process_cu(dcus, cu_die, + pointer_size, NULL) == DWARF_CB_ABORT) return DWARF_CB_ABORT; dcus->off = noff; @@ -3070,7 +3102,7 @@ static int cus__merge_and_process_cu(struct cus *cus, struct conf_load *conf, if (cu__resolve_func_ret_types(cu) != LSK__KEEPIT) goto out_abort; - if (cus__finalize(cus, cu, conf) == LSK__STOP_LOADING) + if (cus__finalize(cus, cu, conf, NULL) == LSK__STOP_LOADING) goto out_abort; return 0; @@ -3102,7 +3134,7 @@ static int cus__load_module(struct cus *cus, struct conf_load *conf, } if (type_cu != NULL) { - type_lsk = cu__finalize(type_cu, conf); + type_lsk = cu__finalize(type_cu, conf, NULL); if (type_lsk == LSK__KEEPIT) { cus__add(cus, type_cu); } diff --git a/dwarves.h b/dwarves.h index 52d162d67456..de152f9b64cf 100644 --- a/dwarves.h +++ b/dwarves.h @@ -48,8 +48,9 @@ struct conf_fprintf; */ struct conf_load { enum load_steal_kind (*steal)(struct cu *cu, - struct conf_load *conf); - int (*thread_exit)(void); + struct conf_load *conf, + void *thr_data); + int (*thread_exit)(struct conf_load *conf, void *thr_data); void *cookie; char *format_path; int nr_jobs; @@ -70,6 +71,10 @@ struct conf_load { const char *kabi_prefix; struct btf *base_btf; struct conf_fprintf *conf_fprintf; + int (*threads_prepare)(struct conf_load *conf, int nr_threads, + void **thr_data); + int (*threads_collect)(struct conf_load *conf, int nr_threads, + void **thr_data, int error); }; /** struct conf_fprintf - hints to the __fprintf routines diff --git a/pahole.c b/pahole.c index f3a51cb2fe74..f3eeaaca4cdf 100644 --- a/pahole.c +++ b/pahole.c @@ -2799,7 +2799,8 @@ out: static struct type_instance *header; static enum load_steal_kind pahole_stealer(struct cu *cu, - struct conf_load *conf_load) + struct conf_load *conf_load, + void *thr_data) { int ret = LSK__DELETE; diff --git a/pdwtags.c b/pdwtags.c index 2b5ba1bf6745..8b1d6f1c96cb 100644 --- a/pdwtags.c +++ b/pdwtags.c @@ -72,7 +72,8 @@ static int cu__emit_tags(struct cu *cu) } static enum load_steal_kind pdwtags_stealer(struct cu *cu, - struct conf_load *conf_load __maybe_unused) + struct conf_load *conf_load __maybe_unused, + void *thr_data __maybe_unused) { cu__emit_tags(cu); return LSK__DELETE; diff --git a/pfunct.c b/pfunct.c index 5485622e639b..314915b774f4 100644 --- a/pfunct.c +++ b/pfunct.c @@ -489,7 +489,9 @@ int elf_symtabs__show(char *filenames[]) return EXIT_SUCCESS; } -static enum load_steal_kind pfunct_stealer(struct cu *cu, struct conf_load *conf_load __maybe_unused) +static enum load_steal_kind pfunct_stealer(struct cu *cu, + struct conf_load *conf_load __maybe_unused, + void *thr_data __maybe_unused) { if (function_name) { -- 2.30.2