aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmalloc.c
diff options
context:
space:
mode:
authorEli Zaretskii2014-03-04 19:35:15 +0200
committerEli Zaretskii2014-03-04 19:35:15 +0200
commit201572eca80ea77d8e1c25099b4aa2d98bc4d402 (patch)
treeb2aedb9d508729a1b3b30bfe23c2bb13fc42d54f /src/gmalloc.c
parent3106d59bce024deba9d6b2193531c09b6a6d3c91 (diff)
downloademacs-201572eca80ea77d8e1c25099b4aa2d98bc4d402.tar.gz
emacs-201572eca80ea77d8e1c25099b4aa2d98bc4d402.zip
Follow-up improvements for last change in gmalloc.c.
src/gmalloc.c (aligned_alloc): Don't allocate more memory than needed, and don't reallocate if the initial allocation already fits the bill. Suggested by Ken Brown <kbrown@cornell.edu>. Fixes: debbugs:16901
Diffstat (limited to 'src/gmalloc.c')
-rw-r--r--src/gmalloc.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c
index f8d0cfdc30a..9fd62407285 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -38,6 +38,10 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
38#include <w32heap.h> /* for sbrk */ 38#include <w32heap.h> /* for sbrk */
39#endif 39#endif
40 40
41#ifdef emacs
42extern void emacs_abort (void);
43#endif
44
41#ifdef __cplusplus 45#ifdef __cplusplus
42extern "C" 46extern "C"
43{ 47{
@@ -1594,24 +1598,33 @@ aligned_alloc (size_t alignment, size_t size)
1594 /* Figure out how much we will need to pad this particular block 1598 /* Figure out how much we will need to pad this particular block
1595 to achieve the required alignment. */ 1599 to achieve the required alignment. */
1596 adj = (uintptr_t) result % alignment; 1600 adj = (uintptr_t) result % alignment;
1601 if (adj == 0)
1602 adj = alignment;
1597 1603
1598 do 1604 if (adj != 1)
1599 { 1605 {
1600 /* Reallocate the block with only as much excess as it needs. */ 1606 do
1601 free (result); 1607 {
1602 result = malloc (size + alignment - adj); 1608 /* Reallocate the block with only as much excess as it
1603 if (result == NULL) /* Impossible unless interrupted. */ 1609 needs. */
1604 return NULL; 1610 free (result);
1605 1611 result = malloc (size + alignment - adj);
1606 lastadj = adj; 1612 if (result == NULL) /* Impossible unless interrupted. */
1607 adj = (uintptr_t) result % alignment; 1613 return NULL;
1608 /* It's conceivable we might have been so unlucky as to get a 1614
1609 different block with weaker alignment. If so, this block is too 1615 lastadj = adj;
1610 short to contain SIZE after alignment correction. So we must 1616 adj = (uintptr_t) result % alignment;
1611 try again and get another block, slightly larger. */ 1617 if (adj == 0)
1612 } while (adj < lastadj); 1618 adj = alignment;
1619 /* It's conceivable we might have been so unlucky as to get
1620 a different block with weaker alignment. If so, this
1621 block is too short to contain SIZE after alignment
1622 correction. So we must try again and get another block,
1623 slightly larger. */
1624 } while (adj < lastadj);
1625 }
1613 1626
1614 if (adj != 0) 1627 if (adj != alignment)
1615 { 1628 {
1616 /* Record this block in the list of aligned blocks, so that `free' 1629 /* Record this block in the list of aligned blocks, so that `free'
1617 can identify the pointer it is passed, which will be in the middle 1630 can identify the pointer it is passed, which will be in the middle