summary refs log tree commit diff
path: root/malloc/malloc.c
diff options
context:
space:
mode:
authorFernando J. V. da Silva <fernandojvdasilva@gmail.com>2013-12-06 18:04:10 +0100
committerOndřej Bílka <neleai@seznam.cz>2013-12-06 18:06:56 +0100
commit4b5b548c9fedd5e6d920639e42ea8e5f473c4de3 (patch)
treef199cdf50b63ffd11e161735591efa836fc5d5f5 /malloc/malloc.c
parent0a3ac0aabf30f6fefb4d262bf2db2c2a99ab09a8 (diff)
downloadglibc-4b5b548c9fedd5e6d920639e42ea8e5f473c4de3.tar.gz
glibc-4b5b548c9fedd5e6d920639e42ea8e5f473c4de3.tar.xz
glibc-4b5b548c9fedd5e6d920639e42ea8e5f473c4de3.zip
Fix BZ #15089: malloc_trim always trim for large padding.
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r--malloc/malloc.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 8977687f8c..b3353bd0a3 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2709,52 +2709,54 @@ static int systrim(size_t pad, mstate av)
   char* current_brk;     /* address returned by pre-check sbrk call */
   char* new_brk;         /* address returned by post-check sbrk call */
   size_t pagesz;
+  long  top_area;
 
   pagesz = GLRO(dl_pagesize);
   top_size = chunksize(av->top);
 
+  top_area = top_size - MINSIZE - 1;
+  if (top_area <= pad)
+    return 0;
+
   /* Release in pagesize units, keeping at least one page */
-  extra = (top_size - pad - MINSIZE - 1) & ~(pagesz - 1);
+  extra = (top_area - pad) & ~(pagesz - 1);
 
-  if (extra > 0) {
+  /*
+    Only proceed if end of memory is where we last set it.
+    This avoids problems if there were foreign sbrk calls.
+  */
+  current_brk = (char*)(MORECORE(0));
+  if (current_brk == (char*)(av->top) + top_size) {
 
     /*
-      Only proceed if end of memory is where we last set it.
-      This avoids problems if there were foreign sbrk calls.
+      Attempt to release memory. We ignore MORECORE return value,
+      and instead call again to find out where new end of memory is.
+      This avoids problems if first call releases less than we asked,
+      of if failure somehow altered brk value. (We could still
+      encounter problems if it altered brk in some very bad way,
+      but the only thing we can do is adjust anyway, which will cause
+      some downstream failure.)
     */
-    current_brk = (char*)(MORECORE(0));
-    if (current_brk == (char*)(av->top) + top_size) {
-
-      /*
-	Attempt to release memory. We ignore MORECORE return value,
-	and instead call again to find out where new end of memory is.
-	This avoids problems if first call releases less than we asked,
-	of if failure somehow altered brk value. (We could still
-	encounter problems if it altered brk in some very bad way,
-	but the only thing we can do is adjust anyway, which will cause
-	some downstream failure.)
-      */
 
-      MORECORE(-extra);
-      /* Call the `morecore' hook if necessary.  */
-      void (*hook) (void) = force_reg (__after_morecore_hook);
-      if (__builtin_expect (hook != NULL, 0))
-	(*hook) ();
-      new_brk = (char*)(MORECORE(0));
+    MORECORE(-extra);
+    /* Call the `morecore' hook if necessary.  */
+    void (*hook) (void) = force_reg (__after_morecore_hook);
+    if (__builtin_expect (hook != NULL, 0))
+      (*hook) ();
+    new_brk = (char*)(MORECORE(0));
 
-      LIBC_PROBE (memory_sbrk_less, 2, new_brk, extra);
+    LIBC_PROBE (memory_sbrk_less, 2, new_brk, extra);
 
-      if (new_brk != (char*)MORECORE_FAILURE) {
-	released = (long)(current_brk - new_brk);
+    if (new_brk != (char*)MORECORE_FAILURE) {
+      released = (long)(current_brk - new_brk);
 
-	if (released != 0) {
-	  /* Success. Adjust top. */
-	  av->system_mem -= released;
-	  set_head(av->top, (top_size - released) | PREV_INUSE);
-	  check_malloc_state(av);
-	  return 1;
-	}
-      }
+      if (released != 0) {
+	/* Success. Adjust top. */
+	av->system_mem -= released;
+	set_head(av->top, (top_size - released) | PREV_INUSE);
+	check_malloc_state(av);
+	return 1;
+       }
     }
   }
   return 0;