about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2011-11-09 17:14:39 +0100
committerAndreas Schwab <schwab@redhat.com>2011-11-10 11:00:59 +0100
commit77cdc054e02069d72dcf54a9ad7d7df3a24bcb01 (patch)
tree9556e4989739f6c40f92860f2119375b8d6caec0
parent5f078c3286c177a4d66ad89e7b3930e2d6132586 (diff)
downloadglibc-77cdc054e02069d72dcf54a9ad7d7df3a24bcb01.tar.gz
glibc-77cdc054e02069d72dcf54a9ad7d7df3a24bcb01.tar.xz
glibc-77cdc054e02069d72dcf54a9ad7d7df3a24bcb01.zip
Check malloc arana limit atomically
-rw-r--r--ChangeLog6
-rw-r--r--malloc/arena.c65
2 files changed, 41 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index bf091611c0..edd7dd8a96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-11-10  Andreas Schwab  <schwab@redhat.com>
+
+	* malloc/arena.c (_int_new_arena): Don't increment narenas.
+	(reused_arena): Don't check arena limit.
+	(arena_get2): Atomically check arena limit.
+
 2011-11-08  Ulrich Drepper  <drepper@gmail.com>
 
 	* locale/findlocale.c (_nl_find_locale): Use __strcasecmp_l.
diff --git a/malloc/arena.c b/malloc/arena.c
index 9114fd28e9..042cac85c0 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -747,8 +747,6 @@ _int_new_arena(size_t size)
   main_arena.next = a;
 
 #ifdef PER_THREAD
-  ++narenas;
-
   (void)mutex_unlock(&list_lock);
 #endif
 
@@ -786,30 +784,6 @@ get_free_list (void)
 static mstate
 reused_arena (void)
 {
-  if (narenas <= mp_.arena_test)
-    return NULL;
-
-  static int narenas_limit;
-  if (narenas_limit == 0)
-    {
-      if (mp_.arena_max != 0)
-	narenas_limit = mp_.arena_max;
-      else
-	{
-	  int n  = __get_nprocs ();
-
-	  if (n >= 1)
-	    narenas_limit = NARENAS_FROM_NCORES (n);
-	  else
-	    /* We have no information about the system.  Assume two
-	       cores.  */
-	    narenas_limit = NARENAS_FROM_NCORES (2);
-	}
-    }
-
-  if (narenas < narenas_limit)
-    return NULL;
-
   mstate result;
   static mstate next_to_use;
   if (next_to_use == NULL)
@@ -844,10 +818,41 @@ arena_get2(mstate a_tsd, size_t size)
   mstate a;
 
 #ifdef PER_THREAD
-  if ((a = get_free_list ()) == NULL
-      && (a = reused_arena ()) == NULL)
-    /* Nothing immediately available, so generate a new arena.  */
-    a = _int_new_arena(size);
+  static size_t narenas_limit;
+
+  a = get_free_list ();
+  if (a == NULL)
+    {
+      /* Nothing immediately available, so generate a new arena.  */
+      if (narenas_limit == 0)
+	{
+	  if (mp_.arena_max != 0)
+	    narenas_limit = mp_.arena_max;
+	  else
+	    {
+	      int n  = __get_nprocs ();
+
+	      if (n >= 1)
+		narenas_limit = NARENAS_FROM_NCORES (n);
+	      else
+		/* We have no information about the system.  Assume two
+		   cores.  */
+		narenas_limit = NARENAS_FROM_NCORES (2);
+	    }
+	}
+    repeat:;
+      size_t n = narenas;
+      if (__builtin_expect (n <= mp_.arena_test || n < narenas_limit, 0))
+	{
+	  if (catomic_compare_and_exchange_bool_acq(&narenas, n + 1, n))
+	    goto repeat;
+	  a = _int_new_arena (size);
+	  if (__builtin_expect (a != NULL, 1))
+	    return a;
+	  catomic_decrement(&narenas);
+	}
+      a = reused_arena ();
+    }
 #else
   if(!a_tsd)
     a = a_tsd = &main_arena;