This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch release/2.23/master updated. glibc-2.23-73-g0266710


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, release/2.23/master has been updated
       via  026671037948fd31009243a2173278dfa0ac9b25 (commit)
      from  e3e0bedf697c8c5858cd7ad1a541a179a20a6320 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=026671037948fd31009243a2173278dfa0ac9b25

commit 026671037948fd31009243a2173278dfa0ac9b25
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Aug 2 12:24:50 2016 +0200

    malloc: Preserve arena free list/thread count invariant [BZ #20370]
    
    It is necessary to preserve the invariant that if an arena is
    on the free list, it has thread attach count zero.  Otherwise,
    when arena_thread_freeres sees the zero attach count, it will
    add it, and without the invariant, an arena could get pushed
    to the list twice, resulting in a cycle.
    
    One possible execution trace looks like this:
    
    Thread 1 examines free list and observes it as empty.
    Thread 2 exits and adds its arena to the free list,
      with attached_threads == 0).
    Thread 1 selects this arena in reused_arena (not from the free list).
    Thread 1 increments attached_threads and attaches itself.
      (The arena remains on the free list.)
    Thread 1 exits, decrements attached_threads,
      and adds the arena to the free list.
    
    The final step creates a cycle in the usual way (by overwriting the
    next_free member with the former list head, while there is another
    list item pointing to the arena structure).
    
    tst-malloc-thread-exit exhibits this issue, but it was only visible
    with a debugger because the incorrect fix in bug 19243 removed
    the assert from get_free_list.
    
    (cherry picked from commit f88aab5d508c13ae4a88124e65773d7d827cd47b)

diff --git a/ChangeLog b/ChangeLog
index ab1ab1f..eeb9973 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-02  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #20370]
+	* malloc/arena.c (get_free_list): Update comment.  Assert that
+	arenas on the free list have no attached threads.
+	(remove_from_free_list): New function.
+	(reused_arena): Call it.
+
 2016-08-04  Florian Weimer  <fweimer@redhat.com>
 
 	Use sysdep.o from libc.a in static libraries.
diff --git a/malloc/arena.c b/malloc/arena.c
index 47715b6..0e5cc0f 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -706,8 +706,7 @@ _int_new_arena (size_t size)
 }
 
 
-/* Remove an arena from free_list.  The arena may be in use because it
-   was attached concurrently to a thread by reused_arena below.  */
+/* Remove an arena from free_list.  */
 static mstate
 get_free_list (void)
 {
@@ -722,7 +721,8 @@ get_free_list (void)
 	  free_list = result->next_free;
 
 	  /* The arena will be attached to this thread.  */
-	  ++result->attached_threads;
+	  assert (result->attached_threads == 0);
+	  result->attached_threads = 1;
 
 	  detach_arena (replaced_arena);
 	}
@@ -739,6 +739,26 @@ get_free_list (void)
   return result;
 }
 
+/* Remove the arena from the free list (if it is present).
+   free_list_lock must have been acquired by the caller.  */
+static void
+remove_from_free_list (mstate arena)
+{
+  mstate *previous = &free_list;
+  for (mstate p = free_list; p != NULL; p = p->next_free)
+    {
+      assert (p->attached_threads == 0);
+      if (p == arena)
+	{
+	  /* Remove the requested arena from the list.  */
+	  *previous = p->next_free;
+	  break;
+	}
+      else
+	previous = &p->next_free;
+    }
+}
+
 /* Lock and return an arena that can be reused for memory allocation.
    Avoid AVOID_ARENA as we have already failed to allocate memory in
    it and it is currently locked.  */
@@ -788,14 +808,25 @@ reused_arena (mstate avoid_arena)
   (void) mutex_lock (&result->mutex);
 
 out:
-  /* Attach the arena to the current thread.  Note that we may have
-     selected an arena which was on free_list.  */
+  /* Attach the arena to the current thread.  */
   {
     /* Update the arena thread attachment counters.   */
     mstate replaced_arena = thread_arena;
     (void) mutex_lock (&free_list_lock);
     detach_arena (replaced_arena);
+
+    /* We may have picked up an arena on the free list.  We need to
+       preserve the invariant that no arena on the free list has a
+       positive attached_threads counter (otherwise,
+       arena_thread_freeres cannot use the counter to determine if the
+       arena needs to be put on the free list).  We unconditionally
+       remove the selected arena from the free list.  The caller of
+       reused_arena checked the free list and observed it to be empty,
+       so the list is very short.  */
+    remove_from_free_list (result);
+
     ++result->attached_threads;
+
     (void) mutex_unlock (&free_list_lock);
   }
 

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog      |    8 ++++++++
 malloc/arena.c |   41 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 5 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]