Skip to content

Commit

Permalink
libdrgn: replace blocking callbacks with hard-coded functions
Browse files Browse the repository at this point in the history
Now that Python support has been squashed into the main libdrgn.so,
there's no reason to go through an indirect call to release the GIL.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
  • Loading branch information
osandov committed Jan 14, 2025
1 parent 4c79230 commit 0987270
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 138 deletions.
4 changes: 2 additions & 2 deletions libdrgn/debug_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -5066,7 +5066,7 @@ drgn_program_load_debug_info(struct drgn_program *prog, const char **paths,
return NULL;
}

drgn_blocking_guard(prog);
drgn_blocking_guard();

const char *env = getenv("DRGN_MAX_DEBUG_INFO_ERRORS");
unsigned int max_warnings = env ? atoi(env) : 5;
Expand Down Expand Up @@ -5282,7 +5282,7 @@ drgn_load_module_debug_info(struct drgn_module **modules, size_t *num_modulesp)
for (size_t i = 0; i < num_wanted_modules; i++)
modules[i]->load_debug_info_generation = generation;

drgn_blocking_guard(prog);
drgn_blocking_guard();

const size_t orig_num_wanted_modules = num_wanted_modules;
drgn_handler_list_for_each_enabled(struct drgn_debug_info_finder,
Expand Down
66 changes: 0 additions & 66 deletions libdrgn/drgn.h
Original file line number Diff line number Diff line change
Expand Up @@ -1824,72 +1824,6 @@ void drgn_program_set_progress_file(struct drgn_program *prog, FILE *file);

/** @} */

/**
* @defgroup Embedding Embedding
*
* Embedding drgn in another runtime.
*
* @{
*/

/**
* Callback before a blocking operation.
*
* @param[in] arg @c callback_arg passed to @ref
* drgn_program_set_blocking_callback().
* @return Opaque pointer to pass to @ref drgn_program_end_blocking_fn().
*/
typedef void *drgn_program_begin_blocking_fn(struct drgn_program *prog,
void *arg);

/**
* Callback after a blocking operation.
*
* @param[in] arg @c callback_arg passed to @ref
* drgn_program_set_blocking_callback().
* @param[in] state Return value of matching call to @ref
* drgn_program_begin_blocking_fn().
*/
typedef void drgn_program_end_blocking_fn(struct drgn_program *prog,
void *arg, void *state);

/**
* Set callbacks around blocking operations.
*
* These callbacks will be called around blocking I/O operations and
* long-running computations. They are intended for things like releasing the
* [global interpreter
* lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock).
* Calls to these callbacks may be nested, but they will always be matched.
*
* @param[in] begin_callback Callback called before a blocking operation. Can be
* @c NULL to unset.
* @param[in] end_callback Callback called after a blocking operation. Can be @c
* NULL to unset.
* @param[in] callback_arg Argument passed to @p begin_callback and @p
* end_callback.
*/
void
drgn_program_set_blocking_callback(struct drgn_program *prog,
drgn_program_begin_blocking_fn *begin_callback,
drgn_program_end_blocking_fn *end_callback,
void *callback_arg);

/**
* Get callbacks set by @ref drgn_program_set_blocking_callback().
*
* @param[out] begin_callback_ret Returned @c begin_callback.
* @param[out] end_callback_ret Returned @c end_callback.
* @param[out] callback_arg_ret Returned @c callback_arg.
*/
void
drgn_program_get_blocking_callback(struct drgn_program *prog,
drgn_program_begin_blocking_fn **begin_callback_ret,
drgn_program_end_blocking_fn **end_callback_ret,
void **callback_arg_ret);

/** @} */

/**
* @defgroup Objects Objects
*
Expand Down
2 changes: 1 addition & 1 deletion libdrgn/dwarf_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -2165,7 +2165,7 @@ static struct drgn_error *index_namespace(struct drgn_namespace_dwarf_index *ns)
>= drgn_dwarf_index_cu_vector_size(&ns->dbinfo->dwarf.index_cus)))
return NULL;

drgn_blocking_guard(ns->dbinfo->prog);
drgn_blocking_guard();

struct drgn_error *err = drgn_dwarf_index_update(ns->dbinfo);
if (err)
Expand Down
35 changes: 0 additions & 35 deletions libdrgn/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,38 +2128,3 @@ drgn_program_element_info(struct drgn_program *prog, struct drgn_type *type,
ret->qualified_type = drgn_type_type(underlying_type);
return drgn_type_bit_size(ret->qualified_type.type, &ret->bit_size);
}

LIBDRGN_PUBLIC void
drgn_program_set_blocking_callback(struct drgn_program *prog,
drgn_program_begin_blocking_fn *begin_callback,
drgn_program_end_blocking_fn *end_callback,
void *callback_arg)
{
prog->begin_blocking_fn = begin_callback;
prog->end_blocking_fn = end_callback;
prog->blocking_arg = callback_arg;
}

LIBDRGN_PUBLIC void
drgn_program_get_blocking_callback(struct drgn_program *prog,
drgn_program_begin_blocking_fn **begin_callback_ret,
drgn_program_end_blocking_fn **end_callback_ret,
void **callback_arg_ret)
{
*begin_callback_ret = prog->begin_blocking_fn;
*end_callback_ret = prog->end_blocking_fn;
*callback_arg_ret = prog->blocking_arg;
}

void *drgn_program_begin_blocking(struct drgn_program *prog)
{
if (!prog->begin_blocking_fn)
return NULL;
return prog->begin_blocking_fn(prog, prog->blocking_arg);
}

void drgn_program_end_blocking(struct drgn_program *prog, void *state)
{
if (prog->end_blocking_fn)
prog->end_blocking_fn(prog, prog->blocking_arg, state);
}
50 changes: 20 additions & 30 deletions libdrgn/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,6 @@ struct drgn_program {
FILE *progress_file;
enum drgn_log_level log_level;
bool default_progress_file;

/*
* Blocking callbacks.
*/
drgn_program_begin_blocking_fn *begin_blocking_fn;
drgn_program_end_blocking_fn *end_blocking_fn;
void *blocking_arg;
};

/** Initialize a @ref drgn_program. */
Expand Down Expand Up @@ -469,49 +462,46 @@ drgn_program_register_symbol_finder_impl(struct drgn_program *prog,
const struct drgn_symbol_finder_ops *ops,
void *arg, size_t enable_index);

#if ENABLE_PYTHON
/**
* Call before a blocking (I/O or long-running) operation.
*
* Must be paired with @ref drgn_program_end_blocking().
* Must be paired with @ref drgn_end_blocking().
*
* @return Opaque pointer to pass to @ref drgn_program_end_blocking().
* @return Opaque pointer to pass to @ref drgn_end_blocking().
*/
void *drgn_program_begin_blocking(struct drgn_program *prog);
void *drgn_begin_blocking(void);

/**
* Call after a blocking (I/O or long-running) operation.
*
* @param[in] state Return value of @ref drgn_program_begin_blocking().
* @param[in] state Return value of @ref drgn_begin_blocking().
*/
void drgn_program_end_blocking(struct drgn_program *prog, void *state);

struct drgn_blocking_guard_struct {
struct drgn_program *prog;
void *state;
};
void drgn_end_blocking(void *state);
#else
static inline void *drgn_begin_blocking(void)
{
return NULL;
}

static inline struct drgn_blocking_guard_struct
drgn_blocking_guard_init(struct drgn_program *prog)
static inline void drgn_end_blocking(void *state)
{
return (struct drgn_blocking_guard_struct){
prog, drgn_program_begin_blocking(prog),
};
}
#endif

static inline void
drgn_blocking_guard_cleanup(struct drgn_blocking_guard_struct *guard)
static inline void drgn_blocking_guard_cleanup(void **statep)
{
drgn_program_end_blocking(guard->prog, guard->state);
drgn_end_blocking(*statep);
}

/**
* Scope guard that wraps @ref drgn_program_begin_blocking() and @ref
* drgn_program_end_blocking().
* Scope guard that wraps @ref drgn_begin_blocking() and @ref
* drgn_end_blocking().
*/
#define drgn_blocking_guard(prog) \
struct drgn_blocking_guard_struct PP_UNIQUE(guard) \
#define drgn_blocking_guard() \
void *PP_UNIQUE(guard) \
__attribute__((__cleanup__(drgn_blocking_guard_cleanup), __unused__)) = \
drgn_blocking_guard_init(prog)
drgn_begin_blocking()

/**
* @}
Expand Down
6 changes: 2 additions & 4 deletions libdrgn/python/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,15 @@ int Program_type_arg(Program *prog, PyObject *type_obj, bool can_be_none,
return 0;
}

static void *drgnpy_begin_blocking(struct drgn_program *prog, void *arg)
void *drgn_begin_blocking(void)
{
PyThreadState *state = PyThreadState_GetUnchecked();
if (state)
PyEval_ReleaseThread(state);
return state;
}

static void drgnpy_end_blocking(struct drgn_program *prog, void *arg, void *state)
void drgn_end_blocking(void *state)
{
if (state)
PyEval_RestoreThread(state);
Expand All @@ -357,8 +357,6 @@ static Program *Program_new_impl(const struct drgn_platform *platform)
prog->cache = no_cleanup_ptr(cache);
pyobjectp_set_init(&prog->objects);
drgn_program_init(&prog->prog, platform);
drgn_program_set_blocking_callback(&prog->prog, drgnpy_begin_blocking,
drgnpy_end_blocking, NULL);
if (Program_init_logging(prog))
return NULL;
return_ptr(prog);
Expand Down

0 comments on commit 0987270

Please sign in to comment.