Hi Aaron,

On Thu, 2026-07-02 at 18:32 -0400, Aaron Merey wrote:
> Document the user thread safety model for elfutils libraries when built
> with --enable-thread-safety.

Probably should be added to Makefile.am EXTRA_DIST so it is included in
make dist and installed in %doc for config/elfutils.spec.in

> Signed-off-by: Aaron Merey <[email protected]>
> ---
>  THREAD-SAFETY | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 110 insertions(+)
>  create mode 100644 THREAD-SAFETY
> 
> diff --git a/THREAD-SAFETY b/THREAD-SAFETY
> new file mode 100644
> index 00000000..5434b32c
> --- /dev/null
> +++ b/THREAD-SAFETY
> @@ -0,0 +1,110 @@
> +# elfutils thread safety
> +
> +Status: under development and not officially supported.  Enable with 
> configure
> +option `--enable-thread-safety`.
> +
> +Experimental support is available for libelf and libdw.  libdwfl thread 
> safety
> +is under development. libasm, libdwelf and libdwfl_stacktrace are not 
> currently
> +supported.

Although libasm is a separate library, libdwfl.h, libdwelf.h and
libdwfl_stacktrace.h interfaces are technically part of the libdw.so
library. Maybe make a separation between libraries and source
interfaces?

> +libdebuginfod: Up to one debuginfod_client handle per thread. Distinct client
> +handles may be used concurrently.

Is this really only one debuginfod_client handle per thread? Or do you
mean that a debuginfod_client may only used/called from the one thread
that created it?

> +Elfutils library functions called on distinct library handles which share no
> +state may be called concurrently in multiple threads.

How does the user know which library handles share state? Can that be
deduced from the derived handles table below? If so, please add that
here. 

> +For cases where a library handle is shared across threads, library functions
> +are divided into two thread safety types:  Thread-safe and caller-serialized.
> +
> +Thread-safe functions may run concurrently across threads even if the handles
> +are shared.
> +
> +A caller-serialized function must not run concurrently with any other library
> +function call on the same handle, on any handle derived from it (see below),
> +or on any handle it is derived from. The caller is responsible for 
> serializing
> +these calls.

I had to read this a couple of times, but I think it is a good way to
describe what can and cannot be run concurrently without some kind of
synchronization. Maybe be explicit that caller-serialized functions
must also not run concurrently with any thread-safe function (it is
implied by the "any other library function call...", but I had to
remind myself while reviewing the caller-serialized functions below).

Does this mean that to safely call these caller-serialized functions
one should associate a lock with the "highest" derived handle (Elf or
Dwarf in most cases) and only call these functions when one has the
lock for that handle? Just wondering if we can provide an example how
calling these caller-serialized functions should look like in a
concurrent setup.

> +
> +Caller-serialized functions
> +
> +The following libelf and libdw public library functions are 
> caller-serialized.
> +All other functions in these libraries are thread-safe.
> +
> +  libelf   elf32_checksum, elf32_newehdr, elf32_newphdr, elf32_xlatetof,
> +           elf32_xlatetom, elf64_checksum, elf64_newehdr, elf64_newphdr,
> +           elf64_xlatetof, elf64_xlatetom, elf_begin (non-NULL ref),
> +           elf_cntl, elf_compress, elf_compress_gnu, elf_end, elf_fill,
> +           elf_flagdata, elf_flagehdr, elf_flagelf, elf_flagphdr,
> +           elf_flagscn, elf_flagshdr, elf_newdata, elf_newscn, elf_next,
> +           elf_rand, elf_update
> +
> +  gelf     gelf_checksum, gelf_newehdr, gelf_newphdr, gelf_update_*,
> +           gelf_xlatetof, gelf_xlatetom
> +
> +  libdw    dwarf_begin_elf, dwarf_cfi_end, dwarf_end, dwarf_new_oom_handler,
> +           dwarf_setalt

This looks right, but I don't really know how to verify.

> +  libdwfl  TBD
> +
> +
> +Derived handles
> +
> +A handle is derived from another when it is obtained from it and shares or
> +copies its state. Concurrency limitations of caller-serialized functions 
> apply
> +to both derived handles and ancestor handles.
> +
> +For example, an Elf_Data is derived from an Elf_Scn and the Elf_Scn is 
> derived
> +from an Elf.  In this case the caller must ensure that elf_flagdata is not
> +called on the Elf_Data concurrently with either elf_newdata called on its
> +associated Elf_Scn or elf_update called on its associated Elf.
> +
> +After a caller-serialized function runs, handles previously derived from any
> +handles used as arguments may be invalid and should be re-derived before 
> further
> +use.

But this is only for the handle itself and any derived handle, not any
"ancestor" handles?

> +Indentation below shows derivation.  ElfXX refers to both Elf32 and Elf64.
> +
> +libelf:
> +  Elf
> +    Elf_Scn
> +      Elf_Data
> +        ElfXX_*         except ElfXX_Ehdr, ElfXX_Phdr and ElfXX_Shdr
> +        GElf_*          except GElf_Ehdr, GElf_Phdr and GElf_Shdr
> +      ElfXX_Shdr
> +      GElf_Shdr
> +    ElfXX_Ehdr
> +    ElfXX_Phdr
> +    GElf_Ehdr
> +    GElf_Phdr
> +    Elf_Arsym
> +    Elf                 archive member, elf_clone
> +      Elf_Arhdr
> +
> +libdw:
> +  Dwarf                 derived from the Elf it was opened with
> +    Dwarf_CU
> +      Dwarf_Die
> +        Dwarf_Attribute
> +          Dwarf_Op
> +          Dwarf_Block
> +      Dwarf_Lines
> +        Dwarf_Line
> +      Dwarf_Files
> +      Dwarf_Abbrev
> +    Dwarf_Aranges
> +      Dwarf_Arange
> +    Dwarf_Macro
> +      Dwarf_Attribute
> +      Dwarf_Files
> +    Dwarf_Global
> +    Dwarf_CFI
> +      Dwarf_Frame
> +        Dwarf_Op
> +    Dwarf               alternate, split, .dwp
> +  Dwarf_CFI             derived from Elf
> +    Dwarf_Frame
> +      Dwarf_Op
> +  Dwarf_CFI_Entry       derived from Elf_Data

Have to think hard what it means that Elf and Dwarf are cyclic, but
apart from that this hierarchy makes sense.

> +libdwfl:
> +  TBD

Thanks,

Mark

Reply via email to