aboutsummaryrefslogtreecommitdiff
path: root/malloc/arena.c
diff options
context:
space:
mode:
Diffstat (limited to 'malloc/arena.c')
-rw-r--r--malloc/arena.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/malloc/arena.c b/malloc/arena.c
index d85f371..2466697 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -99,7 +99,7 @@ int __malloc_initialized = -1;
} while (0)
#define arena_lock(ptr, size) do { \
- if (ptr) \
+ if (ptr && !arena_is_corrupt (ptr)) \
(void) mutex_lock (&ptr->mutex); \
else \
ptr = arena_get2 (ptr, (size), NULL); \
@@ -686,7 +686,7 @@ heap_trim (heap_info *heap, size_t pad)
if (!prev_inuse (p)) /* consolidate backward */
{
p = prev_chunk (p);
- unlink (p, bck, fwd);
+ unlink (ar_ptr, p, bck, fwd);
}
assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0);
assert (((char *) p + new_size) == ((char *) heap + heap->size));
@@ -809,7 +809,7 @@ reused_arena (mstate avoid_arena)
result = next_to_use;
do
{
- if (!mutex_trylock (&result->mutex))
+ if (!arena_is_corrupt (result) && !mutex_trylock (&result->mutex))
goto out;
result = result->next;
@@ -821,7 +821,21 @@ reused_arena (mstate avoid_arena)
if (result == avoid_arena)
result = result->next;
- /* No arena available. Wait for the next in line. */
+ /* Make sure that the arena we get is not corrupted. */
+ mstate begin = result;
+ while (arena_is_corrupt (result) || result == avoid_arena)
+ {
+ result = result->next;
+ if (result == begin)
+ break;
+ }
+
+ /* We could not find any arena that was either not corrupted or not the one
+ we wanted to avoid. */
+ if (result == begin || result == avoid_arena)
+ return NULL;
+
+ /* No arena available without contention. Wait for the next in line. */
LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
(void) mutex_lock (&result->mutex);