From 78cdac019d0b7ce72efdf9ab069f0c6a2149f63a Mon Sep 17 00:00:00 2001 From: Paulo Andrade Date: Thu, 1 Oct 2015 18:01:32 -0300 Subject: [PATCH] Avoid corruption of free_list When a thread leaves, arena_thread_freeres is called, the malloc arena associated with the thread is added to the head of free_list, and free_list set to the arena of the exiting thread. A common problem can be described as: 1. thread "t1" uses arena "a" 2. thread "t2" uses arena "a" 3. "t1" exit, making: a->next_free = free_list; free_list = a; 4. "t2" exits, but since free_list == a, it ends with free_list->next_free = free_list; When a program has several short lived threads, and most commonly when there are more threads than arenas, one arena will end up being used by most threads, causing significant contention. --- malloc/arena.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/malloc/arena.c b/malloc/arena.c index b44e307..bbc76ab 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -934,9 +934,18 @@ arena_thread_freeres (void) if (a != NULL) { + mstate b; (void) mutex_lock (&list_lock); - a->next_free = free_list; - free_list = a; + /* Insert "a" last in free_list. */ + if (free_list != NULL) + { + for (b = free_list; b->next_free != NULL; b = b->next_free) + ; + b->next_free = a; + } + else + free_list = a; + a->next_free = NULL; (void) mutex_unlock (&list_lock); } } -- 1.8.3.1