aboutsummaryrefslogtreecommitdiffstats
path: root/libdw/libdwP.h
diff options
context:
space:
mode:
Diffstat (limited to 'libdw/libdwP.h')
-rw-r--r--libdw/libdwP.h80
1 files changed, 45 insertions, 35 deletions
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index ad2599eb..36c2acd9 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -149,17 +149,6 @@ enum
#include "dwarf_sig8_hash.h"
-/* Structure for 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];
-};
-
/* This is the structure representing the debugging state. */
struct Dwarf
{
@@ -231,11 +220,22 @@ struct Dwarf
/* Similar for addrx/constx, which will come from .debug_addr section. */
struct Dwarf_CU *fake_addr_cu;
- /* 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;
+ /* Supporting lock for internal memory handling. Ensures threads that have
+ an entry in the mem_tails array are not disturbed by new threads doing
+ allocations for this Dwarf. */
+ pthread_rwlock_t mem_rwl;
+
+ /* Internal memory handling. This is basically a simplified thread-local
+ reimplementation of obstacks. Unfortunately the standard obstack
+ implementation is not usable in libraries. */
+ size_t mem_stacks;
+ struct libdw_memblock
+ {
+ size_t size;
+ size_t remaining;
+ struct libdw_memblock *prev;
+ char mem[0];
+ } **mem_tails;
/* Default size of allocated memory blocks. */
size_t mem_default_size;
@@ -578,34 +578,44 @@ libdw_valid_user_form (int form)
extern void __libdw_seterrno (int value) internal_function;
-/* Memory handling, the easy parts. This macro does not do nor need to do any
- locking for proper concurrent operation. */
+/* Memory handling, the easy parts. */
#define libdw_alloc(dbg, type, tsize, cnt) \
- ({ struct libdw_memblock *_tail = pthread_getspecific (dbg->mem_key); \
- size_t _req = (tsize) * (cnt); \
- type *_result; \
- if (unlikely (_tail == NULL)) \
- _result = (type *) __libdw_allocate (dbg, _req, __alignof (type)); \
+ ({ struct libdw_memblock *_tail = __libdw_alloc_tail(dbg); \
+ size_t _required = (tsize) * (cnt); \
+ type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
+ size_t _padding = ((__alignof (type) \
+ - ((uintptr_t) _result & (__alignof (type) - 1))) \
+ & (__alignof (type) - 1)); \
+ if (unlikely (_tail->remaining < _required + _padding)) \
+ _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
else \
{ \
- _result = (type *) (_tail->mem + (_tail->size - _tail->remaining)); \
- size_t _padding = ((__alignof (type) \
- - ((uintptr_t) _result & (__alignof (type) - 1))) \
- & (__alignof (type) - 1)); \
- if (unlikely (_tail->remaining < _req + _padding)) \
- _result = (type *) __libdw_allocate (dbg, _req, __alignof (type)); \
- else \
- { \
- _req += _padding; \
- _result = (type *) ((char *) _result + _padding); \
- _tail->remaining -= _req; \
- } \
+ _required += _padding; \
+ _result = (type *) ((char *) _result + _padding); \
+ _tail->remaining -= _required; \
} \
_result; })
#define libdw_typed_alloc(dbg, type) \
libdw_alloc (dbg, type, sizeof (type), 1)
+/* Can only be used to undo the last libdw_alloc. */
+#define libdw_unalloc(dbg, type, tsize, cnt) \
+ ({ struct libdw_memblock *_tail = __libdw_thread_tail (dbg); \
+ size_t _required = (tsize) * (cnt); \
+ /* We cannot know the padding, it is lost. */ \
+ _tail->remaining += _required; }) \
+
+#define libdw_typed_unalloc(dbg, type) \
+ libdw_unalloc (dbg, type, sizeof (type), 1)
+
+/* Callback to choose a thread-local memory allocation stack. */
+extern struct libdw_memblock *__libdw_alloc_tail (Dwarf* dbg)
+ __nonnull_attribute__ (1);
+
+extern struct libdw_memblock *__libdw_thread_tail (Dwarf* dbg)
+ __nonnull_attribute__ (1);
+
/* Callback to allocate more. */
extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
__attribute__ ((__malloc__)) __nonnull_attribute__ (1);