[PATCH 2/3] libdw: Rewrite the memory handler to be thread-safe.
Jonathon Anderson
jma14@rice.edu
Mon Oct 21 16:28:00 GMT 2019
On Mon, Oct 21, 2019 at 18:13, Mark Wielaard <mark@klomp.org> wrote:
> Hi,
>
> Finally back to this patch series.
>
> On Thu, 2019-08-29 at 15:16 +0200, Mark Wielaard wrote:
>> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
>> index 29795c10..fc573cb3 100644
>> --- a/libdw/dwarf_end.c
>> +++ b/libdw/dwarf_end.c
>> @@ -94,14 +94,15 @@ dwarf_end (Dwarf *dwarf)
>> /* And the split Dwarf. */
>> tdestroy (dwarf->split_tree, noop_free);
>>
>> - struct libdw_memblock *memp = dwarf->mem_tail;
>> - /* The first block is allocated together with the Dwarf
>> object. */
>> - while (memp->prev != NULL)
>> + /* Free the internally allocated memory. */
>> + struct libdw_memblock *memp = (struct libdw_memblock
>> *)dwarf->mem_tail;
>> + while (memp != NULL)
>> {
>> struct libdw_memblock *prevp = memp->prev;
>> free (memp);
>> memp = prevp;
>> }
>> + pthread_key_delete (dwarf->mem_key);
>>
>> /* Free the pubnames helper structure. */
>> free (dwarf->pubnames_sets);
>
> This doesn't build on older GCCs (I am using 4.8.5) with this compile
> error:
>
>
> libdw/dwarf_end.c: In function ‘dwarf_end’:
> libdw/dwarf_end.c:98:45: error: cannot convert to a pointer type
> struct libdw_memblock *memp = (struct libdw_memblock
> *)dwarf->mem_tail;
> ^
Ah, whoops. Thanks for catching that one.
>
> This is because mem_tail is defined as:
>
>> diff --git a/libdw/libdwP.h b/libdw/libdwP.h
>> index eebb7d12..ad2599eb 100644
>> --- a/libdw/libdwP.h
>> +++ b/libdw/libdwP.h
>> @@ -218,16 +231,11 @@ struct Dwarf
>> /* Similar for addrx/constx, which will come from .debug_addr
>> section. */
>> struct Dwarf_CU *fake_addr_cu;
>>
>> - /* Internal memory handling. This is basically a simplified
>> - reimplementation of obstacks. Unfortunately the standard
>> obstack
>> - implementation is not usable in libraries. */
>> - struct libdw_memblock
>> - {
>> - size_t size;
>> - size_t remaining;
>> - struct libdw_memblock *prev;
>> - char mem[0];
>> - } *mem_tail;
>> + /* Internal memory handling. Each thread allocates separately
>> and only
>> + allocates from its own blocks, while all the blocks are
>> pushed atomically
>> + onto a unified stack for easy deallocation. */
>> + pthread_key_t mem_key;
>> + atomic_uintptr_t mem_tail;
>>
>> /* Default size of allocated memory blocks. */
>> size_t mem_default_size;
>
> And for older compilers, without stdatomic.h, this means
> atomic_uintptr_t is really:
>
> typedef _Atomic(uintptr_t) atomic_uintptr_t;
> #define _Atomic(T) struct { volatile
> __typeof__(T) __val; }
>
> And you cannot cast a struct to a pointer type directly.
>
> To make this work on both older and newer gcc versions I changed this
> to:
>
> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
> index fc573cb3..76ab9954 100644
> --- a/libdw/dwarf_end.c
> +++ b/libdw/dwarf_end.c
> @@ -95,7 +95,8 @@ dwarf_end (Dwarf *dwarf)
> tdestroy (dwarf->split_tree, noop_free);
>
> /* Free the internally allocated memory. */
> - struct libdw_memblock *memp = (struct libdw_memblock
> *)dwarf->mem_tail;
> + struct libdw_memblock *memp;
> + memp = (struct libdw_memblock *) atomic_load
> (&dwarf->mem_tail);
> while (memp != NULL)
> {
> struct libdw_memblock *prevp = memp->prev;
>
> Does that look reasonable?
It does, although I would prefer:
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 9ca17212..6da9e0cd 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -95,7 +95,9 @@ dwarf_end (Dwarf *dwarf)
tdestroy (dwarf->split_tree, noop_free);
/* Free the internally allocated memory. */
- struct libdw_memblock *memp = (struct libdw_memblock
*)dwarf->mem_tail;
+ struct libdw_memblock *memp;
+ memp = (struct libdw_memblock *)atomic_load(&dwarf->mem_tail,
+
memory_order_relaxed);
while (memp != NULL)
{
struct libdw_memblock *prevp = memp->prev;
Because some idiot thought making seq_cst the default was a good idea.
And this way it notes in the code that this load is non-synchronizing.
-Jonathon
>
> Thanks,
>
> Mark
More information about the Elfutils-devel
mailing list