mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
libdrgn: don't use OpenMP tasking
libomp (at least in LLVM 9 and 10) seems to have buggy OpenMP tasking support. See commit1cc3868955
("CI: temporarily disable Clang") for one example. OpenMP tasks aren't buying us much; they simplify DWARF index updates in some places but complicate it in others. Let's ditch tasks and go back to building an array of CUs to index similar to what we did before commitf83bb7c71b
("libdrgn: move debugging information tracking into drgn_debug_info"). There is no significant performance difference. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
1cc3868955
commit
e0921c5bdb
@ -981,8 +981,8 @@ drgn_debug_info_read_module(struct drgn_debug_info_load_state *load,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
module->state = DRGN_DEBUG_INFO_MODULE_INDEXING;
|
module->state = DRGN_DEBUG_INFO_MODULE_INDEXING;
|
||||||
drgn_dwarf_index_read_module(dindex_state, module);
|
return drgn_dwarf_index_read_module(dindex_state,
|
||||||
return NULL;
|
module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -1023,29 +1023,32 @@ drgn_debug_info_update_index(struct drgn_debug_info_load_state *load)
|
|||||||
c_string_set_size(&dbinfo->module_names) +
|
c_string_set_size(&dbinfo->module_names) +
|
||||||
load->new_modules.size))
|
load->new_modules.size))
|
||||||
return &drgn_enomem;
|
return &drgn_enomem;
|
||||||
|
|
||||||
struct drgn_dwarf_index_update_state dindex_state;
|
struct drgn_dwarf_index_update_state dindex_state;
|
||||||
drgn_dwarf_index_update_begin(&dindex_state, &dbinfo->dindex);
|
if (!drgn_dwarf_index_update_state_init(&dindex_state, &dbinfo->dindex))
|
||||||
/*
|
return &drgn_enomem;
|
||||||
* In OpenMP 5.0, this could be "#pragma omp parallel master taskloop"
|
struct drgn_error *err = NULL;
|
||||||
* (added in GCC 9 and Clang 10).
|
#pragma omp parallel for schedule(dynamic)
|
||||||
*/
|
|
||||||
#pragma omp parallel
|
|
||||||
#pragma omp master
|
|
||||||
#pragma omp taskloop
|
|
||||||
for (size_t i = 0; i < load->new_modules.size; i++) {
|
for (size_t i = 0; i < load->new_modules.size; i++) {
|
||||||
if (drgn_dwarf_index_update_cancelled(&dindex_state))
|
if (err)
|
||||||
continue;
|
continue;
|
||||||
struct drgn_error *module_err =
|
struct drgn_error *module_err =
|
||||||
drgn_debug_info_read_module(load, &dindex_state,
|
drgn_debug_info_read_module(load, &dindex_state,
|
||||||
load->new_modules.data[i]);
|
load->new_modules.data[i]);
|
||||||
if (module_err)
|
if (module_err) {
|
||||||
drgn_dwarf_index_update_cancel(&dindex_state, module_err);
|
#pragma omp critical(drgn_debug_info_update_index_error)
|
||||||
|
if (err)
|
||||||
|
drgn_error_destroy(module_err);
|
||||||
|
else
|
||||||
|
err = module_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct drgn_error *err = drgn_dwarf_index_update_end(&dindex_state);
|
if (!err)
|
||||||
if (err)
|
err = drgn_dwarf_index_update(&dindex_state);
|
||||||
return err;
|
drgn_dwarf_index_update_state_deinit(&dindex_state);
|
||||||
drgn_debug_info_free_modules(dbinfo, true, false);
|
if (!err)
|
||||||
return NULL;
|
drgn_debug_info_free_modules(dbinfo, true, false);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
|
@ -19,6 +19,16 @@
|
|||||||
#include "siphash.h"
|
#include "siphash.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
struct drgn_dwarf_index_pending_cu {
|
||||||
|
struct drgn_debug_info_module *module;
|
||||||
|
const char *buf;
|
||||||
|
size_t len;
|
||||||
|
bool is_64_bit;
|
||||||
|
enum drgn_debug_info_scn scn;
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_pending_cu_vector)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The DWARF abbreviation table gets translated into a series of instructions.
|
* The DWARF abbreviation table gets translated into a series of instructions.
|
||||||
* An instruction <= INSN_MAX_SKIP indicates a number of bytes to be skipped
|
* An instruction <= INSN_MAX_SKIP indicates a number of bytes to be skipped
|
||||||
@ -220,22 +230,26 @@ void drgn_dwarf_index_deinit(struct drgn_dwarf_index *dindex)
|
|||||||
drgn_dwarf_index_namespace_deinit(&dindex->global);
|
drgn_dwarf_index_namespace_deinit(&dindex->global);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drgn_dwarf_index_update_begin(struct drgn_dwarf_index_update_state *state,
|
bool
|
||||||
|
drgn_dwarf_index_update_state_init(struct drgn_dwarf_index_update_state *state,
|
||||||
struct drgn_dwarf_index *dindex)
|
struct drgn_dwarf_index *dindex)
|
||||||
{
|
{
|
||||||
state->dindex = dindex;
|
state->dindex = dindex;
|
||||||
state->old_cus_size = dindex->cus.size;
|
state->max_threads = omp_get_max_threads();
|
||||||
state->err = NULL;
|
state->cus = malloc_array(state->max_threads, sizeof(*state->cus));
|
||||||
|
if (!state->cus)
|
||||||
|
return false;
|
||||||
|
for (size_t i = 0; i < state->max_threads; i++)
|
||||||
|
drgn_dwarf_index_pending_cu_vector_init(&state->cus[i]);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drgn_dwarf_index_update_cancel(struct drgn_dwarf_index_update_state *state,
|
void
|
||||||
struct drgn_error *err)
|
drgn_dwarf_index_update_state_deinit(struct drgn_dwarf_index_update_state *state)
|
||||||
{
|
{
|
||||||
#pragma omp critical(drgn_dwarf_index_update_cancel)
|
for (size_t i = 0; i < state->max_threads; i++)
|
||||||
if (state->err)
|
drgn_dwarf_index_pending_cu_vector_deinit(&state->cus[i]);
|
||||||
drgn_error_destroy(err);
|
free(state->cus);
|
||||||
else
|
|
||||||
state->err = err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *dw_form_to_insn(struct drgn_dwarf_index_cu *cu,
|
static struct drgn_error *dw_form_to_insn(struct drgn_dwarf_index_cu *cu,
|
||||||
@ -1144,81 +1158,62 @@ skip:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drgn_dwarf_index_read_cus(struct drgn_dwarf_index_update_state *state,
|
static struct drgn_error *
|
||||||
struct drgn_debug_info_module *module,
|
drgn_dwarf_index_read_cus(struct drgn_dwarf_index_update_state *state,
|
||||||
enum drgn_debug_info_scn scn)
|
struct drgn_debug_info_module *module,
|
||||||
|
enum drgn_debug_info_scn scn)
|
||||||
{
|
{
|
||||||
|
struct drgn_dwarf_index_pending_cu_vector *cus =
|
||||||
|
&state->cus[omp_get_thread_num()];
|
||||||
|
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
struct drgn_debug_info_buffer buffer;
|
struct drgn_debug_info_buffer buffer;
|
||||||
drgn_debug_info_buffer_init(&buffer, module, scn);
|
drgn_debug_info_buffer_init(&buffer, module, scn);
|
||||||
while (binary_buffer_has_next(&buffer.bb)) {
|
while (binary_buffer_has_next(&buffer.bb)) {
|
||||||
const char *cu_buf = buffer.bb.pos;
|
struct drgn_dwarf_index_pending_cu *cu =
|
||||||
|
drgn_dwarf_index_pending_cu_vector_append_entry(cus);
|
||||||
|
if (!cu)
|
||||||
|
return &drgn_enomem;
|
||||||
|
cu->module = module;
|
||||||
|
cu->buf = buffer.bb.pos;
|
||||||
uint32_t unit_length32;
|
uint32_t unit_length32;
|
||||||
if ((err = binary_buffer_next_u32(&buffer.bb, &unit_length32)))
|
if ((err = binary_buffer_next_u32(&buffer.bb, &unit_length32)))
|
||||||
goto err;
|
return err;
|
||||||
bool is_64_bit = unit_length32 == UINT32_C(0xffffffff);
|
cu->is_64_bit = unit_length32 == UINT32_C(0xffffffff);
|
||||||
if (is_64_bit) {
|
if (cu->is_64_bit) {
|
||||||
uint64_t unit_length64;
|
uint64_t unit_length64;
|
||||||
if ((err = binary_buffer_next_u64(&buffer.bb,
|
if ((err = binary_buffer_next_u64(&buffer.bb,
|
||||||
&unit_length64)))
|
&unit_length64)))
|
||||||
goto err;
|
return err;
|
||||||
if (unit_length64 > SIZE_MAX) {
|
if (unit_length64 > SIZE_MAX) {
|
||||||
err = binary_buffer_error(&buffer.bb,
|
return binary_buffer_error(&buffer.bb,
|
||||||
"unit length is too large");
|
"unit length is too large");
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
if ((err = binary_buffer_skip(&buffer.bb,
|
if ((err = binary_buffer_skip(&buffer.bb,
|
||||||
unit_length64)))
|
unit_length64)))
|
||||||
goto err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
if ((err = binary_buffer_skip(&buffer.bb,
|
if ((err = binary_buffer_skip(&buffer.bb,
|
||||||
unit_length32)))
|
unit_length32)))
|
||||||
goto err;
|
return err;
|
||||||
}
|
|
||||||
size_t cu_len = buffer.bb.pos - cu_buf;
|
|
||||||
|
|
||||||
#pragma omp task
|
|
||||||
{
|
|
||||||
struct drgn_dwarf_index_cu cu = {
|
|
||||||
.module = module,
|
|
||||||
.buf = cu_buf,
|
|
||||||
.len = cu_len,
|
|
||||||
.is_64_bit = is_64_bit,
|
|
||||||
.is_type_unit = scn == DRGN_SCN_DEBUG_TYPES,
|
|
||||||
};
|
|
||||||
struct drgn_dwarf_index_cu_buffer cu_buffer;
|
|
||||||
drgn_dwarf_index_cu_buffer_init(&cu_buffer, &cu);
|
|
||||||
struct drgn_error *cu_err = read_cu(&cu_buffer);
|
|
||||||
if (cu_err)
|
|
||||||
goto cu_err;
|
|
||||||
|
|
||||||
cu_err = index_cu_first_pass(state->dindex, &cu_buffer);
|
|
||||||
if (cu_err)
|
|
||||||
goto cu_err;
|
|
||||||
|
|
||||||
#pragma omp critical(drgn_dwarf_index_cus)
|
|
||||||
if (!drgn_dwarf_index_cu_vector_append(&state->dindex->cus,
|
|
||||||
&cu))
|
|
||||||
cu_err = &drgn_enomem;
|
|
||||||
if (cu_err) {
|
|
||||||
cu_err:
|
|
||||||
drgn_dwarf_index_cu_deinit(&cu);
|
|
||||||
drgn_dwarf_index_update_cancel(state, cu_err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
cu->len = buffer.bb.pos - cu->buf;
|
||||||
|
cu->scn = scn;
|
||||||
}
|
}
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
err:
|
|
||||||
drgn_dwarf_index_update_cancel(state, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drgn_dwarf_index_read_module(struct drgn_dwarf_index_update_state *state,
|
struct drgn_error *
|
||||||
struct drgn_debug_info_module *module)
|
drgn_dwarf_index_read_module(struct drgn_dwarf_index_update_state *state,
|
||||||
|
struct drgn_debug_info_module *module)
|
||||||
{
|
{
|
||||||
drgn_dwarf_index_read_cus(state, module, DRGN_SCN_DEBUG_INFO);
|
struct drgn_error *err;
|
||||||
if (module->scn_data[DRGN_SCN_DEBUG_TYPES])
|
err = drgn_dwarf_index_read_cus(state, module, DRGN_SCN_DEBUG_INFO);
|
||||||
drgn_dwarf_index_read_cus(state, module, DRGN_SCN_DEBUG_TYPES);
|
if (!err && module->scn_data[DRGN_SCN_DEBUG_TYPES]) {
|
||||||
|
err = drgn_dwarf_index_read_cus(state, module,
|
||||||
|
DRGN_SCN_DEBUG_TYPES);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1691,16 +1686,56 @@ static void drgn_dwarf_index_rollback(struct drgn_dwarf_index *dindex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
drgn_dwarf_index_update_end(struct drgn_dwarf_index_update_state *state)
|
drgn_dwarf_index_update(struct drgn_dwarf_index_update_state *state)
|
||||||
{
|
{
|
||||||
struct drgn_dwarf_index *dindex = state->dindex;
|
struct drgn_dwarf_index *dindex = state->dindex;
|
||||||
|
|
||||||
if (state->err)
|
size_t old_cus_size = dindex->cus.size;
|
||||||
|
size_t new_cus_size = old_cus_size;
|
||||||
|
for (size_t i = 0; i < state->max_threads; i++)
|
||||||
|
new_cus_size += state->cus[i].size;
|
||||||
|
if (!drgn_dwarf_index_cu_vector_reserve(&dindex->cus, new_cus_size))
|
||||||
|
return &drgn_enomem;
|
||||||
|
for (size_t i = 0; i < state->max_threads; i++) {
|
||||||
|
for (size_t j = 0; j < state->cus[i].size; j++) {
|
||||||
|
struct drgn_dwarf_index_pending_cu *pending_cu =
|
||||||
|
&state->cus[i].data[j];
|
||||||
|
dindex->cus.data[dindex->cus.size++] = (struct drgn_dwarf_index_cu){
|
||||||
|
.module = pending_cu->module,
|
||||||
|
.buf = pending_cu->buf,
|
||||||
|
.len = pending_cu->len,
|
||||||
|
.is_64_bit = pending_cu->is_64_bit,
|
||||||
|
.is_type_unit =
|
||||||
|
pending_cu->scn == DRGN_SCN_DEBUG_TYPES,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drgn_error *err = NULL;
|
||||||
|
#pragma omp parallel for schedule(dynamic)
|
||||||
|
for (size_t i = old_cus_size; i < dindex->cus.size; i++) {
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
struct drgn_dwarf_index_cu *cu = &dindex->cus.data[i];
|
||||||
|
struct drgn_dwarf_index_cu_buffer cu_buffer;
|
||||||
|
drgn_dwarf_index_cu_buffer_init(&cu_buffer, cu);
|
||||||
|
struct drgn_error *cu_err = read_cu(&cu_buffer);
|
||||||
|
if (!cu_err)
|
||||||
|
cu_err = index_cu_first_pass(state->dindex, &cu_buffer);
|
||||||
|
if (cu_err) {
|
||||||
|
#pragma omp critical(drgn_dwarf_index_update_end_error)
|
||||||
|
if (err)
|
||||||
|
drgn_error_destroy(cu_err);
|
||||||
|
else
|
||||||
|
err = cu_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
#pragma omp parallel for schedule(dynamic)
|
#pragma omp parallel for schedule(dynamic)
|
||||||
for (size_t i = state->old_cus_size; i < dindex->cus.size; i++) {
|
for (size_t i = old_cus_size; i < dindex->cus.size; i++) {
|
||||||
if (drgn_dwarf_index_update_cancelled(state))
|
if (err)
|
||||||
continue;
|
continue;
|
||||||
struct drgn_dwarf_index_cu *cu = &dindex->cus.data[i];
|
struct drgn_dwarf_index_cu *cu = &dindex->cus.data[i];
|
||||||
struct drgn_dwarf_index_cu_buffer buffer;
|
struct drgn_dwarf_index_cu_buffer buffer;
|
||||||
@ -1710,20 +1745,22 @@ drgn_dwarf_index_update_end(struct drgn_dwarf_index_update_state *state)
|
|||||||
buffer.bb.pos += cu->is_64_bit ? 16 : 12;
|
buffer.bb.pos += cu->is_64_bit ? 16 : 12;
|
||||||
struct drgn_error *cu_err =
|
struct drgn_error *cu_err =
|
||||||
index_cu_second_pass(&dindex->global, &buffer);
|
index_cu_second_pass(&dindex->global, &buffer);
|
||||||
if (cu_err)
|
if (cu_err) {
|
||||||
drgn_dwarf_index_update_cancel(state, cu_err);
|
#pragma omp critical(drgn_dwarf_index_update_end_error)
|
||||||
|
if (err)
|
||||||
|
drgn_error_destroy(cu_err);
|
||||||
|
else
|
||||||
|
err = cu_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (state->err) {
|
if (err) {
|
||||||
drgn_dwarf_index_rollback(state->dindex);
|
drgn_dwarf_index_rollback(dindex);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
for (size_t i = state->old_cus_size; i < dindex->cus.size; i++)
|
for (size_t i = old_cus_size; i < dindex->cus.size; i++)
|
||||||
drgn_dwarf_index_cu_deinit(&dindex->cus.data[i]);
|
drgn_dwarf_index_cu_deinit(&dindex->cus.data[i]);
|
||||||
dindex->cus.size = state->old_cus_size;
|
dindex->cus.size = old_cus_size;
|
||||||
return state->err;
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *index_namespace(struct drgn_dwarf_index_namespace *ns)
|
static struct drgn_error *index_namespace(struct drgn_dwarf_index_namespace *ns)
|
||||||
|
@ -25,6 +25,14 @@ typedef struct {} omp_lock_t;
|
|||||||
#define omp_destroy_lock(lock) do {} while (0)
|
#define omp_destroy_lock(lock) do {} while (0)
|
||||||
#define omp_set_lock(lock) do {} while (0)
|
#define omp_set_lock(lock) do {} while (0)
|
||||||
#define omp_unset_lock(lock) do {} while (0)
|
#define omp_unset_lock(lock) do {} while (0)
|
||||||
|
static inline int omp_get_thread_num(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int omp_get_max_threads(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
@ -183,78 +191,43 @@ void drgn_dwarf_index_init(struct drgn_dwarf_index *dindex);
|
|||||||
*/
|
*/
|
||||||
void drgn_dwarf_index_deinit(struct drgn_dwarf_index *dindex);
|
void drgn_dwarf_index_deinit(struct drgn_dwarf_index *dindex);
|
||||||
|
|
||||||
|
DEFINE_VECTOR_TYPE(drgn_dwarf_index_pending_cu_vector,
|
||||||
|
struct drgn_dwarf_index_pending_cu)
|
||||||
|
|
||||||
/** State tracked while updating a @ref drgn_dwarf_index. */
|
/** State tracked while updating a @ref drgn_dwarf_index. */
|
||||||
struct drgn_dwarf_index_update_state {
|
struct drgn_dwarf_index_update_state {
|
||||||
struct drgn_dwarf_index *dindex;
|
struct drgn_dwarf_index *dindex;
|
||||||
size_t old_cus_size;
|
/** Per-thread arrays of CUs to be indexed. */
|
||||||
struct drgn_error *err;
|
struct drgn_dwarf_index_pending_cu_vector *cus;
|
||||||
|
size_t max_threads;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare to update a @ref drgn_dwarf_index.
|
* Initialize state for updating a @ref drgn_dwarf_index.
|
||||||
*
|
*
|
||||||
* @param[out] state Initialized update state. Must be passed to @ref
|
* @return @c true on success, @c false on failure to allocate memory.
|
||||||
* drgn_dwarf_index_update_end().
|
|
||||||
*/
|
*/
|
||||||
void drgn_dwarf_index_update_begin(struct drgn_dwarf_index_update_state *state,
|
bool
|
||||||
|
drgn_dwarf_index_update_state_init(struct drgn_dwarf_index_update_state *state,
|
||||||
struct drgn_dwarf_index *dindex);
|
struct drgn_dwarf_index *dindex);
|
||||||
|
|
||||||
|
/** Deinitialize state for updating a @ref drgn_dwarf_index. */
|
||||||
|
void
|
||||||
|
drgn_dwarf_index_update_state_deinit(struct drgn_dwarf_index_update_state *state);
|
||||||
|
|
||||||
|
/** Read a module for updating a @ref drgn_dwarf_index. */
|
||||||
|
struct drgn_error *
|
||||||
|
drgn_dwarf_index_read_module(struct drgn_dwarf_index_update_state *state,
|
||||||
|
struct drgn_debug_info_module *module);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finish updating a @ref drgn_dwarf_index.
|
* Update a @ref drgn_dwarf_index.
|
||||||
*
|
*
|
||||||
* This should be called once all of the tasks created by @ref
|
* This should be called once all modules have been read with @ref
|
||||||
* drgn_dwarf_index_read_module() have completed (even if the update was
|
* drgn_dwarf_index_read_module() to finish indexing those modules.
|
||||||
* cancelled).
|
|
||||||
*
|
|
||||||
* If the update was not cancelled, this finishes indexing all modules reported
|
|
||||||
* by @ref drgn_dwarf_index_read_module(). If it was cancelled or there is an
|
|
||||||
* error while indexing, this rolls back the index and removes the newly
|
|
||||||
* reported modules.
|
|
||||||
*
|
|
||||||
* @return @c NULL on success, non-@c NULL if the update was cancelled or there
|
|
||||||
* was another error.
|
|
||||||
*/
|
*/
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
drgn_dwarf_index_update_end(struct drgn_dwarf_index_update_state *state);
|
drgn_dwarf_index_update(struct drgn_dwarf_index_update_state *state);
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel an update of a @ref drgn_dwarf_index.
|
|
||||||
*
|
|
||||||
* This should be called if there is a fatal error and the update must be
|
|
||||||
* aborted.
|
|
||||||
*
|
|
||||||
* @param[in] err Error to report. This will be returned from @ref
|
|
||||||
* drgn_dwarf_index_update_end(). If an error has already been reported, this
|
|
||||||
* error is destroyed.
|
|
||||||
*/
|
|
||||||
void drgn_dwarf_index_update_cancel(struct drgn_dwarf_index_update_state *state,
|
|
||||||
struct drgn_error *err);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether an update of a @ref drgn_dwarf_index has been cancelled by
|
|
||||||
* @ref drgn_dwarf_index_update_cancel().
|
|
||||||
*
|
|
||||||
* Because updating is parallelized, this allows tasks other than the one that
|
|
||||||
* encountered the error to "fail fast".
|
|
||||||
*/
|
|
||||||
static inline bool
|
|
||||||
drgn_dwarf_index_update_cancelled(struct drgn_dwarf_index_update_state *state)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* No need for omp critical/omp atomic since this is a best-effort
|
|
||||||
* optimization.
|
|
||||||
*/
|
|
||||||
return state->err != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a module for updating a @ref drgn_dwarf_index.
|
|
||||||
*
|
|
||||||
* This creates OpenMP tasks to begin indexing the module. It may cancel the
|
|
||||||
* update.
|
|
||||||
*/
|
|
||||||
void drgn_dwarf_index_read_module(struct drgn_dwarf_index_update_state *state,
|
|
||||||
struct drgn_debug_info_module *module);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator over DWARF debugging information.
|
* Iterator over DWARF debugging information.
|
||||||
|
Loading…
Reference in New Issue
Block a user